diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index d95a0ea6ce8..8186b13e4f7 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1670,4 +1670,16 @@ atom/proc/GetTypeInAllContents(typepath) if(prob(chance)) step(AM, pick(alldirs)) chance = max(chance - (initial_chance / steps), 0) - steps-- \ No newline at end of file + steps-- + +/proc/get_random_colour(var/simple, var/lower, var/upper) + var/colour + if(simple) + colour = pick(list("FF0000","FF7F00","FFFF00","00FF00","0000FF","4B0082","8F00FF")) + else + for(var/i=1;i<=3;i++) + var/temp_col = "[num2hex(rand(lower,upper))]" + if(length(temp_col )<2) + temp_col = "0[temp_col]" + colour += temp_col + return colour diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index c1f46efe5ad..1cf1997259e 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -120,7 +120,7 @@ datum/controller/game_controller/proc/setup_objects() //Set up roundstart seed list. - populate_seed_list() + //populate_seed_list() world << "\red \b Initializations complete." sleep(-1) diff --git a/code/datums/recipe.dm b/code/datums/recipe.dm index 0f7dcd15b4a..aa21efd793e 100644 --- a/code/datums/recipe.dm +++ b/code/datums/recipe.dm @@ -34,11 +34,12 @@ * */ /datum/recipe - var/list/reagents // example: = list("berryjuice" = 5) // do not list same reagent twice - var/list/items // example: =list(/obj/item/weapon/crowbar, /obj/item/weapon/welder) // place /foo/bar before /foo - var/result //example: = /obj/item/weapon/reagent_containers/food/snacks/donut/normal - var/time = 100 // 1/10 part of second - var/byproduct //example: = /obj/item/weapon/kitchen/mould // byproduct to return, such as a mould or trash + var/list/reagents // example: = list("berryjuice" = 5) // do not list same reagent twice + var/list/items // example: = list(/obj/item/weapon/crowbar, /obj/item/weapon/welder) // place /foo/bar before /foo + var/list/fruit // example: = list("fruit" = 3) + var/result // example: = /obj/item/weapon/reagent_containers/food/snacks/donut/normal + var/time = 100 // 1/10 part of second + var/byproduct // example: = /obj/item/weapon/kitchen/mould // byproduct to return, such as a mould or trash /datum/recipe/proc/check_reagents(var/datum/reagents/avail_reagents) //1=precisely, 0=insufficiently, -1=superfluous @@ -54,25 +55,44 @@ return -1 return . -/datum/recipe/proc/check_items(var/obj/container as obj) //1=precisely, 0=insufficiently, -1=superfluous - if (!items) - if (locate(/obj/) in container) - return -1 - else - return 1 +/datum/recipe/proc/check_fruit(var/obj/container) . = 1 - var/list/checklist = items.Copy() - for (var/obj/O in container) - var/found = 0 - for (var/type in checklist) - if (istype(O,type)) - checklist-=type - found = 1 - break - if (!found) + if(fruit && fruit.len) + var/list/checklist = list() + // You should trust Copy(). + checklist = fruit.Copy() + for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in container) + if(!G.seed || !G.seed.kitchen_tag || isnull(checklist[G.seed.kitchen_tag])) + continue + checklist[G.seed.kitchen_tag]-- + for(var/ktag in checklist) + if(!isnull(checklist[ktag])) + if(checklist[ktag] < 0) + . = 0 + else if(checklist[ktag] > 0) + . = -1 + break + return . + +/datum/recipe/proc/check_items(var/obj/container as obj) + . = 1 + if (items && items.len) + var/list/checklist = list() + checklist = items.Copy() // You should really trust Copy + for(var/obj/O in container) + if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown)) + continue // Fruit is handled in check_fruit(). + var/found = 0 + for(var/i = 1; i < checklist.len+1; i++) + var/item_type = checklist[i] + if (istype(O,item_type)) + checklist.Cut(i, i+1) + found = 1 + break + if (!found) + . = 0 + if (checklist.len) . = -1 - if (checklist.len) - return 0 return . //general version @@ -101,22 +121,19 @@ exact = -1 var/list/datum/recipe/possible_recipes = new for (var/datum/recipe/recipe in avaiable_recipes) - if (recipe.check_reagents(obj.reagents)==exact && recipe.check_items(obj)==exact) + if (recipe.check_reagents(obj.reagents)==exact && recipe.check_items(obj)==exact && recipe.check_fruit(obj)==exact) possible_recipes+=recipe if (possible_recipes.len==0) return null else if (possible_recipes.len==1) return possible_recipes[1] else //okay, let's select the most complicated recipe - var/r_count = 0 - var/i_count = 0 + var/highest_count = 0 . = possible_recipes[1] for (var/datum/recipe/recipe in possible_recipes) - var/N_i = (recipe.items)?(recipe.items.len):0 - var/N_r = (recipe.reagents)?(recipe.reagents.len):0 - if (N_i > i_count || (N_i== i_count && N_r > r_count )) - r_count = N_r - i_count = N_i + var/count = ((recipe.items)?(recipe.items.len):0) + ((recipe.reagents)?(recipe.reagents.len):0) + ((recipe.fruit)?(recipe.fruit.len):0) + if (count >= highest_count) + highest_count = count . = recipe return . diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 8261ecdf294..484f3e2af24 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -910,7 +910,9 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine /obj/item/seeds/amanitamycelium, /obj/item/seeds/reishimycelium, /obj/item/seeds/bananaseed, - /obj/item/seeds/eggyseed) + /obj/item/seeds/random, + /obj/item/seeds/random, + ) cost = 15 containername = "exotic seeds crate" diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index b873e56fa3a..fc617dacdc9 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -681,8 +681,8 @@ /obj/item/weapon/scythe/afterattack(atom/A, mob/user as mob, proximity) if(!proximity) return - if(istype(A, /obj/effect/plantsegment)) - for(var/obj/effect/plantsegment/B in orange(A,1)) + if(istype(A, /obj/effect/plant)) + for(var/obj/effect/plant/B in orange(A,1)) if(prob(80)) qdel(B) qdel(A) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index a6d56952128..92ccf048809 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -245,6 +245,10 @@ its easier to just keep the beam vertical. /atom/proc/relaymove() return +/atom/proc/set_dir(new_dir) + . = new_dir != dir + dir = new_dir + /atom/proc/ex_act() return diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 148d8d323d6..3edec6687eb 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -268,3 +268,5 @@ /atom/movable/proc/canSingulothPull(var/obj/machinery/singularity/singulo) return 1 +/atom/movable/proc/water_act(var/volume, var/temperature, var/source) //amount of water acting : temperature of water in kelvin : object that called it (for shennagins) + return 1 diff --git a/code/game/machinery/atmoalter/portable_atmospherics.dm b/code/game/machinery/atmoalter/portable_atmospherics.dm index ed56300120d..1be7ef4b3c3 100644 --- a/code/game/machinery/atmoalter/portable_atmospherics.dm +++ b/code/game/machinery/atmoalter/portable_atmospherics.dm @@ -67,6 +67,14 @@ return 1 + update_connected_network() + if(!connected_port) + return + + var/datum/pipe_network/network = connected_port.return_network(src) + if (network) + network.update = 1 + disconnect() if(!connected_port) return 0 diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm index 60a4d3d094f..b9ab86027ce 100644 --- a/code/game/machinery/kitchen/gibber.dm +++ b/code/game/machinery/kitchen/gibber.dm @@ -14,10 +14,104 @@ var/gib_throw_dir = WEST // Direction to spit meat and gibs in. Defaults to west. var/gibtime = 40 // Time from starting until meat appears + var/list/victims = list() + use_power = 1 idle_power_usage = 2 active_power_usage = 500 +//gibs anything that stands on it's input + +/obj/machinery/gibber/autogibber + var/acceptdir = NORTH + var/lastacceptdir = NORTH + var/turf/lturf + +/obj/machinery/gibber/autogibber/New() + ..() + spawn(5) + var/turf/T = get_step(src, acceptdir) + if(istype(T)) + lturf = T + +/obj/machinery/gibber/autogibber/process() + if(!lturf || occupant || locked || dirty || operating) + return + + if(acceptdir != lastacceptdir) + lturf = null + lastacceptdir = acceptdir + var/turf/T = get_step(src, acceptdir) + if(istype(T)) + lturf = T + + for(var/mob/living/carbon/human/H in lturf) + if(istype(H) && H.loc == lturf) + visible_message({"\The [src] states, "Food detected!""}) + sleep(30) + if(H.loc == lturf) //still standing there + if(force_move_into_gibber(H)) + ejectclothes(occupant) + cleanbay() + startgibbing(null, 1) + break + +/obj/machinery/gibber/autogibber/proc/force_move_into_gibber(var/mob/living/carbon/human/victim) + if(!istype(victim)) return 0 + visible_message("\The [victim.name] gets sucked into \the [src]!") + + if(victim.client) + victim.client.perspective = EYE_PERSPECTIVE + victim.client.eye = src + + victim.loc = src + src.occupant = victim + + update_icon() + feedinTopanim() + return 1 + +/obj/machinery/gibber/autogibber/proc/ejectclothes(var/mob/living/carbon/human/H) + if(!istype(H)) return 0 + if(H != occupant) return 0 //only using H as a shortcut to typecast + for(var/obj/O in H) + if(istype(O,/obj/item/clothing)) //clothing gets skipped to avoid cleaning out shit + continue + if(istype(O,/obj/item/weapon/implant)) + var/obj/item/weapon/implant/I = O + if(I.implanted) + continue + if(istype(O,/obj/item/organ)) + continue + if(O.flags & NODROP) + qdel(O) //they are already dead by now + H.unEquip(O) + O.loc = src.loc + O.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15) + sleep(1) + + for(var/obj/item/clothing/C in H) + if(C.flags & NODROP) + qdel(C) + H.unEquip(C) + C.loc = src.loc + C.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15) + sleep(1) + + visible_message("\The [src] spits out \the [H.name]'s possessions!") + +/obj/machinery/gibber/autogibber/proc/cleanbay() + var/spats = 0 //keeps track of how many items get spit out. Don't show a message if none are found. + for(var/obj/O in src) + if(istype(O)) + O.loc = src.loc + O.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15) + spats++ + sleep(1) + if(spats) + visible_message("\The [src] spits out more possessions!") + +/* //auto-gibs anything that bumps into it /obj/machinery/gibber/autogibber var/turf/input_plate @@ -46,7 +140,7 @@ if(M.loc == input_plate) M.loc = src M.gib() - +*/ /obj/machinery/gibber/New() ..() @@ -233,9 +327,18 @@ sleep(1) + overlays -= feedee + overlays -= gibberoverlay src.layer = 3 -/obj/machinery/gibber/proc/startgibbing(mob/user as mob) +/obj/machinery/gibber/proc/startgibbing(var/mob/user, var/UserOverride=0) + if(!istype(user) && !UserOverride) + log_debug("Some shit just went down with the gibber at X[x], Y[y], Z[z] with an invalid user. (JMP)") + return + + if(UserOverride) + msg_admin_attack("[occupant] ([occupant.ckey]) was gibbed by an autogibber (\the [src]) at (JMP)") + if(src.operating) return @@ -266,20 +369,25 @@ new /obj/effect/decal/cleanable/blood/gibs(src) - src.occupant.attack_log += "\[[time_stamp()]\] Was gibbed by [user]/[user.ckey]" //One shall not simply gib a mob unnoticed! - user.attack_log += "\[[time_stamp()]\] Gibbed [src.occupant]/[src.occupant.ckey]" + if(!UserOverride) + src.occupant.attack_log += "\[[time_stamp()]\] Was gibbed by [user]/[user.ckey]" //One shall not simply gib a mob unnoticed! + user.attack_log += "\[[time_stamp()]\] Gibbed [src.occupant]/[src.occupant.ckey]" - if(src.occupant.ckey) - msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] gibbed [src.occupant] ([src.occupant.ckey]) (JMP)") + if(src.occupant.ckey) + msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] gibbed [src.occupant] ([src.occupant.ckey]) (JMP)") - if(!iscarbon(user)) - src.occupant.LAssailant = null - else - src.occupant.LAssailant = user + if(!iscarbon(user)) + src.occupant.LAssailant = null + else + src.occupant.LAssailant = user + + if(UserOverride) //this looks ugly but it's better than a copy-pasted startgibbing proc override + occupant.attack_log += "\[[time_stamp()]\] Was gibbed by an autogibber (\the [src])" src.occupant.emote("scream") playsound(src.loc, 'sound/effects/gib.ogg', 50, 1) + victims += "\[[time_stamp()]\] [occupant.name] ([occupant.ckey]) killed by [UserOverride ? "Autogibbing" : "[user] ([user.ckey])"]" //have to do this before ghostizing src.occupant.death(1) src.occupant.ghostize() @@ -293,12 +401,12 @@ for (var/obj/item/thing in contents) //Meat is spawned inside the gibber and thrown out afterwards. thing.loc = get_turf(thing) // Drop it onto the turf for throwing. thing.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15) // Being pelted with bits of meat and bone would hurt. + sleep(1) for (var/obj/effect/gibs in contents) //throw out the gibs too gibs.loc = get_turf(gibs) //drop onto turf for throwing gibs.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(1,5),15) + sleep(1) src.operating = 0 - update_icon() - - + update_icon() \ No newline at end of file diff --git a/code/game/machinery/kitchen/juicer.dm b/code/game/machinery/kitchen/juicer.dm index 86d59679f76..bf963ea3c0d 100644 --- a/code/game/machinery/kitchen/juicer.dm +++ b/code/game/machinery/kitchen/juicer.dm @@ -10,17 +10,21 @@ idle_power_usage = 5 active_power_usage = 100 var/obj/item/weapon/reagent_containers/beaker = null - var/global/list/allowed_items = list ( - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato = "tomatojuice", - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot = "carrotjuice", - /obj/item/weapon/reagent_containers/food/snacks/grown/berries = "berryjuice", - /obj/item/weapon/reagent_containers/food/snacks/grown/banana = "banana", - /obj/item/weapon/reagent_containers/food/snacks/grown/potato = "potato", - /obj/item/weapon/reagent_containers/food/snacks/grown/lemon = "lemonjuice", - /obj/item/weapon/reagent_containers/food/snacks/grown/orange = "orangejuice", - /obj/item/weapon/reagent_containers/food/snacks/grown/lime = "limejuice", + var/global/list/allowed_items = list( /obj/item/weapon/reagent_containers/food/snacks/watermelonslice = "watermelonjuice", - /obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries = "poisonberryjuice", + /obj/item/weapon/reagent_containers/food/snacks/grown = "water", + ) + + var/global/list/allowed_tags = list ( + "tomato" = "tomatojuice", + "carrot" = "carrotjuice", + "berries" = "berryjuice", + "banana" = "banana", + "potato" = "potato", + "lemon" = "lemonjuice", + "orange" = "orangejuice", + "lime" = "limejuice", + "poisonberries" = "poisonberryjuice", ) /obj/machinery/juicer/New() @@ -132,10 +136,15 @@ beaker = null update_icon() -/obj/machinery/juicer/proc/get_juice_id(var/obj/item/weapon/reagent_containers/food/snacks/grown/O) - for (var/i in allowed_items) - if (istype(O, i)) - return allowed_items[i] +/obj/machinery/juicer/proc/get_juice_id(var/obj/item/weapon/reagent_containers/food/snacks/O) + if (istype(O, /obj/item/weapon/reagent_containers/food/snacks/watermelonslice)) + return "watermelonjuice" + else if(istype(O, /obj.item/weapon/reagent_containers/food/snacks/grown)) + var/obj/item/weapon/reagent_containers/food/snacks/grown/G = O + for(var/i in allowed_tags) + if(G.seed.kitchen_tag == allowed_tags[i]) + return allowed_tags[i] + return "water" /obj/machinery/juicer/proc/get_juice_amount(var/obj/item/weapon/reagent_containers/food/snacks/grown/O) if (!istype(O)) diff --git a/code/game/machinery/kitchen/microwave.dm b/code/game/machinery/kitchen/microwave.dm index aaeef39d8d6..17b260747dd 100644 --- a/code/game/machinery/kitchen/microwave.dm +++ b/code/game/machinery/kitchen/microwave.dm @@ -43,6 +43,7 @@ acceptable_reagents |= reagent if (recipe.items) max_n_of_items = max(max_n_of_items,recipe.items.len) + acceptable_items |= /obj/item/weapon/reagent_containers/food/snacks/grown component_parts = list() component_parts += new /obj/item/weapon/circuitboard/microwave(null) diff --git a/code/game/machinery/kitchen/processor.dm b/code/game/machinery/kitchen/processor.dm index 0fe8596d380..9cc323b8b25 100644 --- a/code/game/machinery/kitchen/processor.dm +++ b/code/game/machinery/kitchen/processor.dm @@ -34,19 +34,19 @@ output = /obj/item/weapon/reagent_containers/food/snacks/meatball /datum/food_processor_process/potato - input = /obj/item/weapon/reagent_containers/food/snacks/grown/potato + input = "potato" output = /obj/item/weapon/reagent_containers/food/snacks/fries /datum/food_processor_process/carrot - input = /obj/item/weapon/reagent_containers/food/snacks/grown/carrot + input = "carrot" output = /obj/item/weapon/reagent_containers/food/snacks/carrotfries /datum/food_processor_process/soybeans - input = /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans + input = "soybeans" output = /obj/item/weapon/reagent_containers/food/snacks/soydope /datum/food_processor_process/wheat - input = /obj/item/weapon/reagent_containers/food/snacks/grown/wheat + input = "wheat" output = /obj/item/weapon/reagent_containers/food/snacks/flour /datum/food_processor_process/spaghetti @@ -111,7 +111,11 @@ /obj/machinery/processor/proc/select_recipe(var/X) for (var/Type in typesof(/datum/food_processor_process) - /datum/food_processor_process - /datum/food_processor_process/mob) var/datum/food_processor_process/P = new Type() - if (!istype(X, P.input)) + if(istype(X, /obj/item/weapon/reagent_containers/food/snacks/grown)) + var/obj/item/weapon/reagent_containers/food/snacks/grown/G = X + if(G.seed.kitchen_tag != P.input) + continue + else if (!istype(X, P.input)) continue return P return 0 diff --git a/code/game/machinery/seed_extractor.dm b/code/game/machinery/seed_extractor.dm index f2e45ccdc41..6934ee0ac6c 100644 --- a/code/game/machinery/seed_extractor.dm +++ b/code/game/machinery/seed_extractor.dm @@ -16,10 +16,10 @@ obj/machinery/seed_extractor/attackby(var/obj/item/O as obj, var/mob/user as mob var/datum/seed/new_seed_type if(istype(O, /obj/item/weapon/grown)) var/obj/item/weapon/grown/F = O - new_seed_type = seed_types[F.plantname] + new_seed_type = plant_controller.seeds[F.plantname] else var/obj/item/weapon/reagent_containers/food/snacks/grown/F = O - new_seed_type = seed_types[F.plantname] + new_seed_type = plant_controller.seeds[F.plantname] if(new_seed_type) user << "You extract some seeds from [O]." diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm index 266c72c1a17..0635786cfc2 100644 --- a/code/game/objects/effects/decals/Cleanable/misc.dm +++ b/code/game/objects/effects/decals/Cleanable/misc.dm @@ -171,6 +171,16 @@ icon = 'icons/effects/tomatodecal.dmi' random_icon_states = list("smashed_pie") +/obj/effect/decal/cleanable/fruit_smudge + name = "smudge" + desc = "Some kind of fruit smear." + density = 0 + anchored = 1 + layer = 2 + icon = 'icons/effects/blood.dmi' + icon_state = "mfloor1" + random_icon_states = list("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7") + /obj/effect/decal/cleanable/fungus name = "space fungus" desc = "A fungal growth. Looks pretty nasty." diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index d5d3555e12d..b73c5bf8f1f 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -79,6 +79,9 @@ would spawn and follow the beaker, even if it is carried or thrown. /obj/effect/effect/water/Bump(atom/A) if(reagents) reagents.reaction(A) + if(istype(A,/atom/movable)) + var/atom/movable/AM = A + AM.water_act(life, 310.15, src) return ..() @@ -423,6 +426,28 @@ steam.start() -- spawns the effect return +// Spores +/datum/effect/effect/system/chem_smoke_spread/spores + var/datum/seed/seed + +/datum/effect/effect/system/chem_smoke_spread/spores/New(seed_name) + if(seed_name && plant_controller) + seed = plant_controller.seeds[seed_name] + if(!seed) + del(src) + ..() + + + +/datum/effect/effect/system/chem_smoke_spread/New() + ..() + chemholder = new/obj() + var/datum/reagents/R = new/datum/reagents(500) + chemholder.reagents = R + R.my_atom = chemholder + + + /datum/effect/effect/system/chem_smoke_spread var/total_smoke = 0 // To stop it being spammed and lagging! var/direction @@ -460,16 +485,20 @@ steam.start() -- spawns the effect var/where = "[A.name] | [location.x], [location.y]" var/whereLink = "[where]" - if(carry.my_atom.fingerprintslast) - var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast) - var/more = "" - if(M) - more = "(?)" - msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink])[contained]. Last associated key is [carry.my_atom.fingerprintslast][more].", 0, 1) - log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last associated key is [carry.my_atom.fingerprintslast].") + if(carry && carry.my_atom) + if(carry.my_atom.fingerprintslast) + var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast) + var/more = "" + if(M) + more = "(?)" + msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink])[contained]. Last associated key is [carry.my_atom.fingerprintslast][more].", 0, 1) + log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last associated key is [carry.my_atom.fingerprintslast].") + else + msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key.", 0, 1) + log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.") else - msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key.", 0, 1) - log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.") + msg_admin_attack("A chemical smoke reaction has taken place in ([whereLink]). No associated key. CODERS: carry.my_atom may be null.", 0, 1) + log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key. CODERS: carry.my_atom may be null.") start(effect_range = 2) var/i = 0 @@ -482,6 +511,13 @@ steam.start() -- spawns the effect var/mob/living/carbon/C = A if(!(C.wear_mask && (C.internals != null || C.wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT))) chemholder.reagents.copy_to(C, chemholder.reagents.total_volume) + if(istype(A, /obj/machinery/portable_atmospherics/hydroponics)) + var/obj/machinery/portable_atmospherics/hydroponics/tray = A + chemholder.reagents.copy_to(tray, chemholder.reagents.total_volume) + if(istype(A, /obj/effect/plant)) + var/obj/effect/plant/plant = A + if(chemholder.reagents.has_reagent("atrazine")) + plant.die_off() qdel(smokeholder) for(i=0, i 20) diff --git a/code/game/objects/items/random_items.dm b/code/game/objects/items/random_items.dm index 1a6ab66a72e..d5f13d33c47 100644 --- a/code/game/objects/items/random_items.dm +++ b/code/game/objects/items/random_items.dm @@ -198,7 +198,7 @@ B.desc = "Looks like the label fell off." // B.identify_probability = 0 - +/* /obj/structure/closet/crate/bin/flowers name = "flower barrel" desc = "A bin full of fresh flowers for the bereaved." @@ -211,7 +211,6 @@ AM.pixel_x = rand(-10,10) AM.pixel_y = rand(-5,5) - /obj/structure/closet/crate/bin/plants name = "plant barrel" desc = "Caution: Contents may contain vitamins and minerals. It is recommended that you deep fry them before eating." @@ -234,6 +233,7 @@ var/obj/O = new ptype(src) O.pixel_x = rand(-10,10) O.pixel_y = rand(-5,5) +*/ /obj/structure/closet/secure_closet/random_drinks name = "Unlabelled Booze" diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index 623e117e9f1..f76b927ad37 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -245,6 +245,16 @@ CIGARETTE PACKETS ARE IN FANCY.DM src.pixel_x = rand(-5.0, 5) src.pixel_y = rand(-5.0, 5) +/obj/item/clothing/mask/cigarette/handroll + name = "hand-rolled cigarette" + desc = "A roll of tobacco and nicotine, freshly rolled by hand." + icon_state = "hr_cigoff" + item_state = "hr_cigoff" + icon_on = "hr_cigon" //Note - these are in masks.dmi not in cigarette.dmi + icon_off = "hr_cigoff" + type_butt = /obj/item/weapon/cigbutt + chem_volume = 50 + //////////// // CIGARS // //////////// @@ -485,7 +495,7 @@ obj/item/weapon/rollingpaper name = "rolling paper" desc = "A thin piece of paper used to make fine smokeables." icon = 'icons/obj/cigarettes.dmi' - icon_state = "cig paper" + icon_state = "cig_paper" w_class = 1 diff --git a/code/game/objects/items/weapons/hydroponics.dm b/code/game/objects/items/weapons/hydroponics.dm index a32f7d6d152..9b34938d480 100644 --- a/code/game/objects/items/weapons/hydroponics.dm +++ b/code/game/objects/items/weapons/hydroponics.dm @@ -146,7 +146,7 @@ if(!user.gloves) user << "\red The [name] burns your bare hand!" user.adjustFireLoss(rand(1,5)) - +/* /* * Nettle */ @@ -237,3 +237,4 @@ new /obj/item/clothing/mask/cigarette/pipe/cobpipe (user.loc) del(src) return +*/ \ No newline at end of file diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 2fdd133801b..76c6715b0da 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -146,8 +146,10 @@ if (M.loc == loc) wash(M) check_heat(M) + M.water_act(100, convertHeat(), src) for (var/atom/movable/G in src.loc) G.clean_blood() + G.water_act(100, convertHeat(), src) /obj/machinery/shower/attackby(obj/item/I as obj, mob/user as mob, params) if(I.type == /obj/item/device/analyzer) @@ -163,6 +165,8 @@ if("boiling") watertemp = "normal" user.visible_message("[user] adjusts the shower with the [I].", "You adjust the shower with the [I].") + if(on) + I.water_act(100, convertHeat(), src) /obj/machinery/shower/update_icon() //this is terribly unreadable, but basically it makes the shower mist up overlays.Cut() //once it's been on for a while, in addition to handling the water overlay. @@ -201,10 +205,21 @@ mobpresent -= 1 ..() +/obj/machinery/shower/proc/convertHeat() + switch(watertemp) + if("boiling") + return 340.15 + if("normal") + return 310.15 + if("freezing") + return 230.15 + //Yes, showers are super powerful as far as washing goes. /obj/machinery/shower/proc/wash(atom/movable/O as obj|mob) if(!on) return + O.water_act(100, convertHeat(), src) + if(isliving(O)) var/mob/living/L = O L.ExtinguishMob() @@ -293,22 +308,22 @@ check_heat(C) /obj/machinery/shower/proc/check_heat(mob/M as mob) + M.water_act(100, convertHeat(), src) //convenience if(!on || watertemp == "normal") return if(iscarbon(M)) var/mob/living/carbon/C = M if(watertemp == "freezing") - C.bodytemperature = max(80, C.bodytemperature - 80) + //C.bodytemperature = max(80, C.bodytemperature - 80) C << "The water is freezing!" return if(watertemp == "boiling") - C.bodytemperature = min(500, C.bodytemperature + 35) + //C.bodytemperature = min(500, C.bodytemperature + 35) C.adjustFireLoss(5) C << "The water is searing!" return - /obj/item/weapon/bikehorn/rubberducky name = "rubber ducky" desc = "Rubber ducky you're so fine, you make bathtime lots of fuuun. Rubber ducky I'm awfully fooooond of yooooouuuu~" //thanks doohl @@ -372,7 +387,9 @@ user.visible_message("\blue [user] fills the [RG] using \the [src].","\blue You fill the [RG] using \the [src].") return - else if (istype(O, /obj/item/weapon/melee/baton)) + O.water_act(20,310.15,src) + + if (istype(O, /obj/item/weapon/melee/baton)) var/obj/item/weapon/melee/baton/B = O if (B.bcell.charge > 0 && B.status == 1) flick("baton_active", src) diff --git a/code/modules/food/candy_maker.dm b/code/modules/food/candy_maker.dm index cfe59a95209..269c2fcc33b 100644 --- a/code/modules/food/candy_maker.dm +++ b/code/modules/food/candy_maker.dm @@ -43,6 +43,7 @@ acceptable_reagents |= reagent if (recipe.items) max_n_of_items = max(max_n_of_items,recipe.items.len) + acceptable_items |= /obj/item/weapon/reagent_containers/food/snacks/grown component_parts = list() component_parts += new /obj/item/weapon/circuitboard/candy_maker(null) diff --git a/code/modules/food/grill_new.dm b/code/modules/food/grill_new.dm index 757b5a4ca58..6fcd5e3a31a 100644 --- a/code/modules/food/grill_new.dm +++ b/code/modules/food/grill_new.dm @@ -44,6 +44,7 @@ acceptable_reagents |= reagent if (recipe.items) max_n_of_items = max(max_n_of_items,recipe.items.len) + acceptable_items |= /obj/item/weapon/reagent_containers/food/snacks/grown component_parts = list() component_parts += new /obj/item/weapon/circuitboard/grill(null) diff --git a/code/modules/food/oven_new.dm b/code/modules/food/oven_new.dm index 4fe0f79b396..1b0c3559cf0 100644 --- a/code/modules/food/oven_new.dm +++ b/code/modules/food/oven_new.dm @@ -44,6 +44,7 @@ acceptable_reagents |= reagent if (recipe.items) max_n_of_items = max(max_n_of_items,recipe.items.len) + acceptable_items |= /obj/item/weapon/reagent_containers/food/snacks/grown component_parts = list() component_parts += new /obj/item/weapon/circuitboard/oven(null) diff --git a/code/modules/food/recipes_microwave.dm b/code/modules/food/recipes_microwave.dm index 71c04ed3851..27c47f30fde 100644 --- a/code/modules/food/recipes_microwave.dm +++ b/code/modules/food/recipes_microwave.dm @@ -2,37 +2,6 @@ // see code/datums/recipe.dm - -/* -/datum/recipe/microwave/telebacon - items = list( - /obj/item/weapon/reagent_containers/food/snacks/meat, - /obj/item/device/assembly/signaler - ) - result = /obj/item/weapon/reagent_containers/food/snacks/telebacon - - -/datum/recipe/microwave/syntitelebacon - items = list( - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - /obj/item/device/assembly/signaler - ) - result = /obj/item/weapon/reagent_containers/food/snacks/telebacon - -/datum/recipe/microwave/bun - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough - ) - result = /obj/item/weapon/reagent_containers/food/snacks/bun - -/datum/recipe/microwave/friedegg - reagents = list("sodiumchloride" = 1, "blackpepper" = 1) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/egg - ) - result = /obj/item/weapon/reagent_containers/food/snacks/friedegg -*/ - /datum/recipe/microwave/boiledegg reagents = list("water" = 5) items = list( @@ -41,24 +10,13 @@ result = /obj/item/weapon/reagent_containers/food/snacks/boiledegg /datum/recipe/microwave/dionaroast + fruit = list("apple" = 1) reagents = list("facid" = 5) //It dissolves the carapace. Still poisonous, though. items = list( /obj/item/weapon/holder/diona, - /obj/item/weapon/reagent_containers/food/snacks/grown/apple ) result = /obj/item/weapon/reagent_containers/food/snacks/dionaroast - -/* -/datum/recipe/microwave/bananaphone - reagents = list("psilocybin" = 5) //Trippin' balls, man. - items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/banana, - /obj/item/device/radio - ) - result = /obj/item/weapon/reagent_containers/food/snacks/bananaphone -*/ - /datum/recipe/microwave/jellydonut reagents = list("berryjuice" = 5, "sugar" = 5) items = list( @@ -203,16 +161,6 @@ ) result = /obj/item/weapon/reagent_containers/food/snacks/hotdog -/* -/datum/recipe/microwave/waffles - reagents = list("sugar" = 10) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough - ) - result = /obj/item/weapon/reagent_containers/food/snacks/waffles -*/ - /datum/recipe/microwave/donkpocket items = list( /obj/item/weapon/reagent_containers/food/snacks/dough, @@ -226,91 +174,20 @@ ) result = /obj/item/weapon/reagent_containers/food/snacks/warmdonkpocket - -/* -/datum/recipe/microwave/meatbread - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/meat, - /obj/item/weapon/reagent_containers/food/snacks/meat, - /obj/item/weapon/reagent_containers/food/snacks/meat, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/meatbread - -/datum/recipe/microwave/syntibread - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/meatbread - -/datum/recipe/microwave/xenomeatbread - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/xenomeat, - /obj/item/weapon/reagent_containers/food/snacks/xenomeat, - /obj/item/weapon/reagent_containers/food/snacks/xenomeat, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/xenomeatbread - -/datum/recipe/microwave/bananabread - reagents = list("milk" = 5, "sugar" = 15) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/grown/banana, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/bananabread - -/datum/recipe/microwave/omelette - items = list( - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/omelette - -/datum/recipe/microwave/muffin - reagents = list("milk" = 5, "sugar" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/muffin -*/ - /datum/recipe/microwave/eggplantparm + fruit = list("eggplant" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/grown/eggplant ) result = /obj/item/weapon/reagent_containers/food/snacks/eggplantparm /datum/recipe/microwave/soylenviridians + fruit = list("soybeans" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/flour, /obj/item/weapon/reagent_containers/food/snacks/flour, /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans ) result = /obj/item/weapon/reagent_containers/food/snacks/soylenviridians @@ -324,91 +201,6 @@ ) result = /obj/item/weapon/reagent_containers/food/snacks/soylentgreen -/* -/datum/recipe/microwave/carrotcake - reagents = list("milk" = 5, "sugar" = 15) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot, - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot, - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/carrotcake - -/datum/recipe/microwave/cheesecake - reagents = list("milk" = 5, "sugar" = 15) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesecake - -/datum/recipe/microwave/plaincake - reagents = list("milk" = 5, "sugar" = 15) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/plaincake - -/datum/recipe/microwave/meatpie - items = list( - /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/meat, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/meatpie - -/datum/recipe/microwave/tofupie - items = list( - /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/tofu, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/tofupie - -/datum/recipe/microwave/xemeatpie - items = list( - /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/xenomeat, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/xemeatpie - -/datum/recipe/microwave/pie - reagents = list("sugar" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/grown/banana, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/pie - -/datum/recipe/microwave/cherrypie - reagents = list("sugar" = 10) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/grown/cherries, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/cherrypie - -/datum/recipe/microwave/berryclafoutis - items = list( - /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/grown/berries, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/berryclafoutis - -/datum/recipe/microwave/wingfangchu - reagents = list("soysauce" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/xenomeat, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/wingfangchu -*/ - /datum/recipe/microwave/chaosdonut reagents = list("frostoil" = 5, "capsaicin" = 5, "sugar" = 5) items = list( @@ -416,61 +208,6 @@ ) result = /obj/item/weapon/reagent_containers/food/snacks/donut/chaos -/* -/datum/recipe/microwave/human/kabob - items = list( - /obj/item/stack/rods, - /obj/item/weapon/reagent_containers/food/snacks/meat/human, - /obj/item/weapon/reagent_containers/food/snacks/meat/human, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/human/kabob - -/datum/recipe/microwave/monkeykabob - items = list( - /obj/item/stack/rods, - /obj/item/weapon/reagent_containers/food/snacks/meat/monkey, - /obj/item/weapon/reagent_containers/food/snacks/meat/monkey, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/monkeykabob - -/datum/recipe/microwave/syntikabob - items = list( - /obj/item/stack/rods, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/monkeykabob - -/datum/recipe/microwave/tofukabob - items = list( - /obj/item/stack/rods, - /obj/item/weapon/reagent_containers/food/snacks/tofu, - /obj/item/weapon/reagent_containers/food/snacks/tofu, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/tofukabob - -/datum/recipe/microwave/tofubread - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/tofu, - /obj/item/weapon/reagent_containers/food/snacks/tofu, - /obj/item/weapon/reagent_containers/food/snacks/tofu, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/tofubread - -/datum/recipe/microwave/loadedbakedpotato - items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/potato, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/loadedbakedpotato -*/ - /datum/recipe/microwave/cheesyfries items = list( /obj/item/weapon/reagent_containers/food/snacks/fries, @@ -479,138 +216,25 @@ result = /obj/item/weapon/reagent_containers/food/snacks/cheesyfries /datum/recipe/microwave/cubancarp + fruit = list("chili" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/grown/chili, /obj/item/weapon/reagent_containers/food/snacks/carpmeat, ) result = /obj/item/weapon/reagent_containers/food/snacks/cubancarp /datum/recipe/microwave/popcorn - items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/corn - ) + fruit = list("corn" = 1) result = /obj/item/weapon/reagent_containers/food/snacks/popcorn -/* -/datum/recipe/microwave/cookie - reagents = list("milk" = 5, "sugar" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/chocolatebar, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/cookie - -/datum/recipe/microwave/fortunecookie - reagents = list("sugar" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/doughslice, - /obj/item/weapon/paper, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/fortunecookie - make_food(var/obj/container as obj) - var/obj/item/weapon/paper/paper = locate() in container - paper.loc = null //prevent deletion - var/obj/item/weapon/reagent_containers/food/snacks/fortunecookie/being_cooked = ..(container) - paper.loc = being_cooked - being_cooked.trash = paper //so the paper is left behind as trash without special-snowflake(TM Nodrak) code ~carn - return being_cooked - check_items(var/obj/container as obj) - . = ..() - if (.) - var/obj/item/weapon/paper/paper = locate() in container - if (!paper.info) - return 0 - return . - -/datum/recipe/microwave/meatsteak - reagents = list("sodiumchloride" = 1, "blackpepper" = 1) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/meat - ) - result = /obj/item/weapon/reagent_containers/food/snacks/meatsteak - -/datum/recipe/microwave/syntisteak - reagents = list("sodiumchloride" = 1, "blackpepper" = 1) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh - ) - result = /obj/item/weapon/reagent_containers/food/snacks/meatsteak - -/datum/recipe/microwave/pizzamargherita - items = list( - /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/margherita - -/datum/recipe/microwave/meatpizza - items = list( - /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/meat, - /obj/item/weapon/reagent_containers/food/snacks/meat, - /obj/item/weapon/reagent_containers/food/snacks/meat, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza - -/datum/recipe/microwave/syntipizza - items = list( - /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza - -/datum/recipe/microwave/mushroompizza - items = list( - /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/mushroompizza - -/datum/recipe/microwave/vegetablepizza - items = list( - /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/grown/eggplant, - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot, - /obj/item/weapon/reagent_containers/food/snacks/grown/corn, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza -*/ - /datum/recipe/microwave/spacylibertyduff reagents = list("water" = 5, "vodka" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/libertycap, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/libertycap, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/libertycap, - ) + fruit = list("libertycap" = 3) result = /obj/item/weapon/reagent_containers/food/snacks/spacylibertyduff /datum/recipe/microwave/amanitajelly reagents = list("water" = 5, "vodka" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/amanita, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/amanita, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/amanita, - ) + fruit = list("amanita" = 3) result = /obj/item/weapon/reagent_containers/food/snacks/amanitajelly make_food(var/obj/container as obj) var/obj/item/weapon/reagent_containers/food/snacks/amanitajelly/being_cooked = ..(container) @@ -619,28 +243,21 @@ /datum/recipe/microwave/meatballsoup reagents = list("water" = 10) + fruit = list("potato" = 1, "carrot" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/meatball , - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot, - /obj/item/weapon/reagent_containers/food/snacks/grown/potato, ) result = /obj/item/weapon/reagent_containers/food/snacks/meatballsoup /datum/recipe/microwave/vegetablesoup reagents = list("water" = 10) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot, - /obj/item/weapon/reagent_containers/food/snacks/grown/corn, - /obj/item/weapon/reagent_containers/food/snacks/grown/eggplant, - /obj/item/weapon/reagent_containers/food/snacks/grown/potato, - ) + fruit = list("carrot" = 1, "corn" = 1, "eggplant" = 1, "potato" = 1) result = /obj/item/weapon/reagent_containers/food/snacks/vegetablesoup /datum/recipe/microwave/nettlesoup reagents = list("water" = 10) + fruit = list("nettle" = 1, "potato" = 1) items = list( - /obj/item/weapon/grown/nettle, - /obj/item/weapon/reagent_containers/food/snacks/grown/potato, /obj/item/weapon/reagent_containers/food/snacks/egg, ) result = /obj/item/weapon/reagent_containers/food/snacks/nettlesoup @@ -650,37 +267,19 @@ result= /obj/item/weapon/reagent_containers/food/snacks/wishsoup /datum/recipe/microwave/hotchili + fruit = list("chili" = 1, "tomato" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/meat, - /obj/item/weapon/reagent_containers/food/snacks/grown/chili, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, ) result = /obj/item/weapon/reagent_containers/food/snacks/hotchili /datum/recipe/microwave/coldchili + fruit = list("icechili" = 1, "tomato" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/meat, - /obj/item/weapon/reagent_containers/food/snacks/grown/icepepper, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, ) result = /obj/item/weapon/reagent_containers/food/snacks/coldchili -/* -/datum/recipe/microwave/amanita_pie - items = list( - /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/amanita, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/amanita_pie - -/datum/recipe/microwave/plump_pie - items = list( - /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/plumphelmet, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/plump_pie -*/ - /datum/recipe/microwave/spellburger items = list( /obj/item/weapon/reagent_containers/food/snacks/monkeyburger, @@ -706,45 +305,21 @@ result = /obj/item/weapon/reagent_containers/food/snacks/bigbiteburger /datum/recipe/microwave/enchiladas + fruit = list("chili" = 2, "corn" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/cutlet, - /obj/item/weapon/reagent_containers/food/snacks/grown/chili, - /obj/item/weapon/reagent_containers/food/snacks/grown/chili, - /obj/item/weapon/reagent_containers/food/snacks/grown/corn, ) result = /obj/item/weapon/reagent_containers/food/snacks/enchiladas -/* -/datum/recipe/microwave/creamcheesebread - items = list( - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/creamcheesebread -*/ - /datum/recipe/microwave/monkeysdelight reagents = list("sodiumchloride" = 1, "blackpepper" = 1) + fruit = list("banana" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/flour, /obj/item/weapon/reagent_containers/food/snacks/monkeycube, - /obj/item/weapon/reagent_containers/food/snacks/grown/banana, ) result = /obj/item/weapon/reagent_containers/food/snacks/monkeysdelight -/* -/datum/recipe/microwave/baguette - reagents = list("sodiumchloride" = 1, "blackpepper" = 1) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/baguette -*/ - /datum/recipe/microwave/fishandchips items = list( /obj/item/weapon/reagent_containers/food/snacks/fries, @@ -752,25 +327,6 @@ ) result = /obj/item/weapon/reagent_containers/food/snacks/fishandchips -/* -/datum/recipe/microwave/birthdaycake - reagents = list("milk" = 5, "sugar" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/clothing/head/cakehat - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/birthdaycake - -/datum/recipe/microwave/bread - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/egg - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/bread -*/ - /datum/recipe/microwave/sandwich items = list( /obj/item/weapon/reagent_containers/food/snacks/meatsteak, @@ -784,45 +340,17 @@ items = list( /obj/item/weapon/reagent_containers/food/snacks/sandwich ) - result = /obj/item/weapon/reagent_containers/food/snacks/toastedsandwich - -/* -/datum/recipe/microwave/grilledcheese - items = list( - /obj/item/weapon/reagent_containers/food/snacks/breadslice, - /obj/item/weapon/reagent_containers/food/snacks/breadslice, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/grilledcheese -*/ /datum/recipe/microwave/tomatosoup reagents = list("water" = 10) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, - ) + fruit = list("tomato" = 2) result = /obj/item/weapon/reagent_containers/food/snacks/tomatosoup -/* -/datum/recipe/microwave/rofflewaffles - reagents = list("psilocybin" = 5, "sugar" = 10) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/rofflewaffles -*/ - /datum/recipe/microwave/stew reagents = list("water" = 10) + fruit = list("tomato" = 1, "potato" = 1, "carrot" = 1, "eggplant" = 1, "mushroom" = 1) items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, /obj/item/weapon/reagent_containers/food/snacks/meat, - /obj/item/weapon/reagent_containers/food/snacks/grown/potato, - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot, - /obj/item/weapon/reagent_containers/food/snacks/grown/eggplant, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom, ) result = /obj/item/weapon/reagent_containers/food/snacks/stew @@ -851,20 +379,13 @@ result = /obj/item/weapon/reagent_containers/food/snacks/milosoup /datum/recipe/microwave/stewedsoymeat + fruit = list("carrot" = 1, "tomato" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/soydope, /obj/item/weapon/reagent_containers/food/snacks/soydope, - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, ) result = /obj/item/weapon/reagent_containers/food/snacks/stewedsoymeat -/*/datum/recipe/microwave/spagetti We have the processor now - items = list( - /obj/item/weapon/reagent_containers/food/snacks/doughslice - ) - result= /obj/item/weapon/reagent_containers/food/snacks/spagetti*/ - /datum/recipe/microwave/boiledspagetti reagents = list("water" = 5) items = list( @@ -882,10 +403,9 @@ /datum/recipe/microwave/pastatomato reagents = list("water" = 5) + fruit = list("tomato" = 2) items = list( /obj/item/weapon/reagent_containers/food/snacks/spagetti, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, ) result = /obj/item/weapon/reagent_containers/food/snacks/pastatomato @@ -918,11 +438,11 @@ /datum/recipe/microwave/superbiteburger reagents = list("sodiumchloride" = 5, "blackpepper" = 5) + fruit = list("tomato" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/bigbiteburger, /obj/item/weapon/reagent_containers/food/snacks/dough, /obj/item/weapon/reagent_containers/food/snacks/meat, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, /obj/item/weapon/reagent_containers/food/snacks/boiledegg, ) @@ -930,31 +450,9 @@ /datum/recipe/microwave/candiedapple reagents = list("water" = 5, "sugar" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/apple - ) + fruit = list("apple" = 1) result = /obj/item/weapon/reagent_containers/food/snacks/candiedapple -/* -/datum/recipe/microwave/applepie - items = list( - /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/grown/apple, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/applepie - -/datum/recipe/microwave/applecake - reagents = list("milk" = 5, "sugar" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/grown/apple, - /obj/item/weapon/reagent_containers/food/snacks/grown/apple, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/applecake -*/ - /datum/recipe/microwave/slimeburger reagents = list("slimejelly" = 5) items = list( @@ -993,70 +491,9 @@ ) result = /obj/item/weapon/reagent_containers/food/snacks/jellysandwich/cherry -/* -/datum/recipe/microwave/orangecake - reagents = list("milk" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/grown/orange, - /obj/item/weapon/reagent_containers/food/snacks/grown/orange, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/orangecake - -/datum/recipe/microwave/limecake - reagents = list("milk" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/grown/lime, - /obj/item/weapon/reagent_containers/food/snacks/grown/lime, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/limecake - -/datum/recipe/microwave/lemoncake - reagents = list("milk" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/grown/lemon, - /obj/item/weapon/reagent_containers/food/snacks/grown/lemon, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/lemoncake - -/datum/recipe/microwave/chocolatecake - reagents = list("milk" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/chocolatebar, - /obj/item/weapon/reagent_containers/food/snacks/chocolatebar, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/chocolatecake -*/ - /datum/recipe/microwave/bloodsoup reagents = list("blood" = 10) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/bloodtomato, - /obj/item/weapon/reagent_containers/food/snacks/grown/bloodtomato, - ) + fruit = list("bloodtomato" = 2) result = /obj/item/weapon/reagent_containers/food/snacks/bloodsoup /datum/recipe/microwave/slimesoup @@ -1066,8 +503,8 @@ /datum/recipe/microwave/clownstears reagents = list("water" = 10) + fruit = list("banana" = 1) items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/banana, /obj/item/weapon/ore/clown, ) result = /obj/item/weapon/reagent_containers/food/snacks/clownstears @@ -1083,21 +520,6 @@ reagents = list("toxin" = 5) result = /obj/item/weapon/reagent_containers/food/snacks/mint -/* -/datum/recipe/microwave/braincake - reagents = list("milk" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/brain - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/braincake -*/ - /datum/recipe/microwave/chocolateegg items = list( /obj/item/weapon/reagent_containers/food/snacks/egg, @@ -1105,24 +527,6 @@ ) result = /obj/item/weapon/reagent_containers/food/snacks/chocolateegg -/* -/datum/recipe/microwave/sausage - items = list( - /obj/item/weapon/reagent_containers/food/snacks/meatball, - /obj/item/weapon/reagent_containers/food/snacks/cutlet, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sausage - -/datum/recipe/microwave/fishfingers - items = list( - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/carpmeat, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/fishfingers -*/ - /datum/recipe/microwave/mysterysoup reagents = list("water" = 10) items = list( @@ -1133,69 +537,27 @@ ) result = /obj/item/weapon/reagent_containers/food/snacks/mysterysoup -/* -/datum/recipe/microwave/pumpkinpie - reagents = list("milk" = 5, "sugar" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/grown/pumpkin, - /obj/item/weapon/reagent_containers/food/snacks/egg, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pumpkinpie - -/datum/recipe/microwave/plumphelmetbiscuit - reagents = list("water" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/plumphelmet, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/plumphelmetbiscuit -*/ - /datum/recipe/microwave/mushroomsoup reagents = list("water" = 5, "milk" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/chanterelle, - ) + fruit = list("mushroom" = 1) result = /obj/item/weapon/reagent_containers/food/snacks/mushroomsoup /datum/recipe/microwave/chawanmushi reagents = list("water" = 5, "soysauce" = 5) + fruit = list("mushroom" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/egg, /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/chanterelle, ) result = /obj/item/weapon/reagent_containers/food/snacks/chawanmushi /datum/recipe/microwave/beetsoup reagents = list("water" = 10) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/whitebeet, - /obj/item/weapon/reagent_containers/food/snacks/grown/cabbage, - ) + fruit = list("whitebeet" = 1, "cabbage" = 1) result = /obj/item/weapon/reagent_containers/food/snacks/beetsoup -/* -/datum/recipe/microwave/appletart - reagents = list("sugar" = 5, "milk" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/grown/goldapple, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/appletart -*/ - /datum/recipe/microwave/herbsalad - items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris, - /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris, - /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris, - /obj/item/weapon/reagent_containers/food/snacks/grown/apple, - ) + fruit = list("ambrosia" = 3, "apple" = 1) result = /obj/item/weapon/reagent_containers/food/snacks/herbsalad make_food(var/obj/container as obj) var/obj/item/weapon/reagent_containers/food/snacks/herbsalad/being_cooked = ..(container) @@ -1203,20 +565,12 @@ return being_cooked /datum/recipe/microwave/aesirsalad - items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiadeus, - /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiadeus, - /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiadeus, - /obj/item/weapon/reagent_containers/food/snacks/grown/goldapple, - ) + fruit = list("ambrosiadeus" = 3, "goldapple" = 1) result = /obj/item/weapon/reagent_containers/food/snacks/aesirsalad /datum/recipe/microwave/validsalad + fruit = list("ambrosia" = 3, "potato" = 1) items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris, - /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris, - /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris, - /obj/item/weapon/reagent_containers/food/snacks/grown/potato, /obj/item/weapon/reagent_containers/food/snacks/meatball, ) result = /obj/item/weapon/reagent_containers/food/snacks/validsalad @@ -1225,31 +579,19 @@ being_cooked.reagents.del_reagent("toxin") return being_cooked -/* -/datum/recipe/microwave/cracker - reagents = list("sodiumchloride" = 1) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/doughslice - ) - result = /obj/item/weapon/reagent_containers/food/snacks/cracker -*/ - ////////////////////////////FOOD ADDITTIONS/////////////////////////////// /datum/recipe/microwave/wrap reagents = list("soysauce" = 10) + fruit = list("cabbage" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/friedegg, - /obj/item/weapon/reagent_containers/food/snacks/grown/cabbage, ) result = /obj/item/weapon/reagent_containers/food/snacks/wrap /datum/recipe/microwave/beans reagents = list("ketchup" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans, - /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans, - ) + fruit = list("soybeans" = 2) result = /obj/item/weapon/reagent_containers/food/snacks/beans /datum/recipe/microwave/benedict @@ -1262,10 +604,10 @@ /datum/recipe/microwave/meatbun reagents = list("soysauce" = 5) + fruit = list("cabbage" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/dough, /obj/item/weapon/reagent_containers/food/snacks/meatball, - /obj/item/weapon/reagent_containers/food/snacks/grown/cabbage, ) result = /obj/item/weapon/reagent_containers/food/snacks/meatbun @@ -1284,23 +626,12 @@ ) result = /obj/item/weapon/reagent_containers/food/snacks/notasandwich -/* -/datum/recipe/microwave/sugarcookie - reagents = list("sugar" = 5) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/egg, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sugarcookie -*/ - /datum/recipe/microwave/friedbanana + reagents = list("sugar" = 10, "cornoil" = 5) + fruit = list("banana" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/grown/banana ) - /obj/item/weapon/ - reagents = list("sugar" = 10, "cornoil" = 5) result = /obj/item/weapon/reagent_containers/food/snacks/friedbanana /datum/recipe/microwave/stuffing @@ -1361,34 +692,12 @@ ) result = /obj/item/weapon/reagent_containers/food/snacks/taco -/* -/datum/recipe/microwave/bun - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough - ) - result = /obj/item/weapon/reagent_containers/food/snacks/bun - -/datum/recipe/microwave/flatbread - items = list( - /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough - ) - result = /obj/item/weapon/reagent_containers/food/snacks/flatbread -*/ - /datum/recipe/microwave/meatball items = list( /obj/item/weapon/reagent_containers/food/snacks/rawmeatball ) result = /obj/item/weapon/reagent_containers/food/snacks/meatball -/* -/datum/recipe/microwave/cutlet - items = list( - /obj/item/weapon/reagent_containers/food/snacks/rawcutlet - ) - result = /obj/item/weapon/reagent_containers/food/snacks/cutlet -*/ - /datum/recipe/microwave/fries items = list( /obj/item/weapon/reagent_containers/food/snacks/rawsticks diff --git a/code/modules/food/recipes_oven.dm b/code/modules/food/recipes_oven.dm index 298636c8820..c9b1703dc54 100644 --- a/code/modules/food/recipes_oven.dm +++ b/code/modules/food/recipes_oven.dm @@ -51,11 +51,11 @@ /datum/recipe/oven/bananabread reagents = list("milk" = 5, "sugar" = 15) + fruit = list("banana" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/dough, /obj/item/weapon/reagent_containers/food/snacks/dough, /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/grown/banana, ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/bananabread @@ -68,13 +68,11 @@ /datum/recipe/oven/carrotcake reagents = list("milk" = 5, "sugar" = 15) + fruit = list("carrot" = 3) items = list( /obj/item/weapon/reagent_containers/food/snacks/dough, /obj/item/weapon/reagent_containers/food/snacks/dough, /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot, - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot, - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot, ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/carrotcake @@ -121,24 +119,24 @@ /datum/recipe/oven/pie reagents = list("sugar" = 5) + fruit = list("banana" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/grown/banana, ) result = /obj/item/weapon/reagent_containers/food/snacks/pie /datum/recipe/oven/cherrypie reagents = list("sugar" = 10) + fruit = list("cherries" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/grown/cherries, ) result = /obj/item/weapon/reagent_containers/food/snacks/cherrypie /datum/recipe/oven/berryclafoutis + fruit = list("berries" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/grown/berries, ) result = /obj/item/weapon/reagent_containers/food/snacks/berryclafoutis @@ -157,8 +155,8 @@ result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/tofubread /datum/recipe/oven/loadedbakedpotato + fruit = list("potato" = 1) items = list( - /obj/item/weapon/reagent_containers/food/snacks/grown/potato, /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, ) result = /obj/item/weapon/reagent_containers/food/snacks/loadedbakedpotato @@ -194,73 +192,65 @@ return . /datum/recipe/oven/pizzamargherita + fruit = list("tomato" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/margherita /datum/recipe/oven/meatpizza + fruit = list("tomato" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, /obj/item/weapon/reagent_containers/food/snacks/meat, /obj/item/weapon/reagent_containers/food/snacks/meat, /obj/item/weapon/reagent_containers/food/snacks/meat, /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza /datum/recipe/oven/syntipizza + fruit = list("tomato" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza /datum/recipe/oven/mushroompizza + fruit = list("mushroom" = 5, "tomato" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom, /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/mushroompizza /datum/recipe/oven/vegetablepizza + fruit = list("eggplant" = 1, "carrot" = 1, "corn" = 1, "tomato" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/grown/eggplant, - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot, - /obj/item/weapon/reagent_containers/food/snacks/grown/corn, - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/vegetablepizza /datum/recipe/oven/amanita_pie + fruit = list("amanita" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/amanita, ) result = /obj/item/weapon/reagent_containers/food/snacks/amanita_pie /datum/recipe/oven/plump_pie + fruit = list("plumphelmet" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/plumphelmet, ) result = /obj/item/weapon/reagent_containers/food/snacks/plump_pie @@ -300,74 +290,58 @@ result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/bread /datum/recipe/oven/applepie + fruit = list("apple" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/grown/apple, ) result = /obj/item/weapon/reagent_containers/food/snacks/applepie /datum/recipe/oven/applecake reagents = list("milk" = 5, "sugar" = 5) + fruit = list("apple" = 2) items = list( /obj/item/weapon/reagent_containers/food/snacks/dough, /obj/item/weapon/reagent_containers/food/snacks/dough, /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/grown/apple, - /obj/item/weapon/reagent_containers/food/snacks/grown/apple, ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/applecake /datum/recipe/oven/orangecake reagents = list("milk" = 5) + fruit = list("orange" = 2) items = list( - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/grown/orange, - /obj/item/weapon/reagent_containers/food/snacks/grown/orange, + /obj/item/weapon/reagent_containers/food/snacks/dough, + /obj/item/weapon/reagent_containers/food/snacks/dough, + /obj/item/weapon/reagent_containers/food/snacks/dough, ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/orangecake /datum/recipe/oven/limecake reagents = list("milk" = 5) + fruit = list("lime" = 2) items = list( - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/grown/lime, - /obj/item/weapon/reagent_containers/food/snacks/grown/lime, + /obj/item/weapon/reagent_containers/food/snacks/dough, + /obj/item/weapon/reagent_containers/food/snacks/dough, + /obj/item/weapon/reagent_containers/food/snacks/dough, ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/limecake /datum/recipe/oven/lemoncake reagents = list("milk" = 5) + fruit = list("lemon" = 2) items = list( - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/grown/lemon, - /obj/item/weapon/reagent_containers/food/snacks/grown/lemon, + /obj/item/weapon/reagent_containers/food/snacks/dough, + /obj/item/weapon/reagent_containers/food/snacks/dough, + /obj/item/weapon/reagent_containers/food/snacks/dough, ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/lemoncake /datum/recipe/oven/chocolatecake reagents = list("milk" = 5) items = list( - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, + /obj/item/weapon/reagent_containers/food/snacks/dough, + /obj/item/weapon/reagent_containers/food/snacks/dough, + /obj/item/weapon/reagent_containers/food/snacks/dough, /obj/item/weapon/reagent_containers/food/snacks/chocolatebar, /obj/item/weapon/reagent_containers/food/snacks/chocolatebar, ) @@ -376,33 +350,29 @@ /datum/recipe/oven/braincake reagents = list("milk" = 5) items = list( - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/egg, + /obj/item/weapon/reagent_containers/food/snacks/dough, + /obj/item/weapon/reagent_containers/food/snacks/dough, + /obj/item/weapon/reagent_containers/food/snacks/dough, /obj/item/organ/brain ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/braincake /datum/recipe/oven/pumpkinpie reagents = list("milk" = 5, "sugar" = 5) + fruit = list("pumpkin" = 1) items = list( - /obj/item/weapon/reagent_containers/food/snacks/flour, - /obj/item/weapon/reagent_containers/food/snacks/grown/pumpkin, - /obj/item/weapon/reagent_containers/food/snacks/egg, + /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pumpkinpie /datum/recipe/oven/appletart reagents = list("sugar" = 5, "milk" = 5) + fruit = list("goldapple" = 1) items = list( /obj/item/weapon/reagent_containers/food/snacks/flour, /obj/item/weapon/reagent_containers/food/snacks/flour, /obj/item/weapon/reagent_containers/food/snacks/flour, /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/weapon/reagent_containers/food/snacks/grown/goldapple, ) result = /obj/item/weapon/reagent_containers/food/snacks/appletart diff --git a/code/modules/hydroponics/_hydro_setup.dm b/code/modules/hydroponics/_hydro_setup.dm new file mode 100644 index 00000000000..a3fd4604a66 --- /dev/null +++ b/code/modules/hydroponics/_hydro_setup.dm @@ -0,0 +1,58 @@ +//Misc +#define DEAD_PLANT_COLOUR "#C2A180" + +// Definitions for genes (trait groupings) +#define GENE_BIOCHEMISTRY "biochemistry" +#define GENE_HARDINESS "hardiness" +#define GENE_ENVIRONMENT "environment" +#define GENE_METABOLISM "metabolism" +#define GENE_STRUCTURE "appearance" +#define GENE_DIET "diet" +#define GENE_PIGMENT "pigment" +#define GENE_OUTPUT "output" +#define GENE_ATMOSPHERE "atmosphere" +#define GENE_VIGOUR "vigour" +#define GENE_FRUIT "fruit" +#define GENE_SPECIAL "special" + +#define ALL_GENES list(GENE_BIOCHEMISTRY,GENE_HARDINESS,GENE_ENVIRONMENT,GENE_METABOLISM,GENE_STRUCTURE,GENE_DIET,GENE_PIGMENT,GENE_OUTPUT,GENE_ATMOSPHERE,GENE_VIGOUR,GENE_FRUIT,GENE_SPECIAL) + +//Definitions for traits (individual descriptors) +#define TRAIT_CHEMS 1 +#define TRAIT_EXUDE_GASSES 2 +#define TRAIT_ALTER_TEMP 3 +#define TRAIT_POTENCY 4 +#define TRAIT_HARVEST_REPEAT 5 +#define TRAIT_PRODUCES_POWER 6 +#define TRAIT_JUICY 7 +#define TRAIT_PRODUCT_ICON 8 +#define TRAIT_PLANT_ICON 0 +#define TRAIT_CONSUME_GASSES 10 +#define TRAIT_REQUIRES_NUTRIENTS 11 +#define TRAIT_NUTRIENT_CONSUMPTION 12 +#define TRAIT_REQUIRES_WATER 13 +#define TRAIT_WATER_CONSUMPTION 14 +#define TRAIT_CARNIVOROUS 15 +#define TRAIT_PARASITE 16 +#define TRAIT_STINGS 17 +#define TRAIT_IDEAL_HEAT 18 +#define TRAIT_HEAT_TOLERANCE 19 +#define TRAIT_IDEAL_LIGHT 20 +#define TRAIT_LIGHT_TOLERANCE 21 +#define TRAIT_LOWKPA_TOLERANCE 22 +#define TRAIT_HIGHKPA_TOLERANCE 23 +#define TRAIT_EXPLOSIVE 24 +#define TRAIT_TOXINS_TOLERANCE 25 +#define TRAIT_PEST_TOLERANCE 26 +#define TRAIT_WEED_TOLERANCE 27 +#define TRAIT_ENDURANCE 28 +#define TRAIT_YIELD 29 +#define TRAIT_SPREAD 30 +#define TRAIT_MATURATION 31 +#define TRAIT_PRODUCTION 32 +#define TRAIT_TELEPORTING 33 +#define TRAIT_PLANT_COLOUR 34 +#define TRAIT_PRODUCT_COLOUR 35 +#define TRAIT_BIOLUM 36 +#define TRAIT_BIOLUM_COLOUR 37 +#define TRAIT_IMMUTABLE 38 \ No newline at end of file diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm new file mode 100644 index 00000000000..056edc02d6f --- /dev/null +++ b/code/modules/hydroponics/grown.dm @@ -0,0 +1,394 @@ +//Grown foods. +/obj/item/weapon/reagent_containers/food/snacks/grown + + name = "fruit" + icon = 'icons/obj/hydroponics_products.dmi' + icon_state = "blank" + desc = "Nutritious! Probably." + + var/plantname + var/datum/seed/seed + var/potency = -1 + +/obj/item/weapon/reagent_containers/food/snacks/grown/New(newloc,planttype) + + ..() + if(!dried_type) + dried_type = type + src.pixel_x = rand(-5.0, 5) + src.pixel_y = rand(-5.0, 5) + + // Fill the object up with the appropriate reagents. + if(planttype) + plantname = planttype + + if(!plantname) + return + + if(!plant_controller) + sleep(250) // ugly hack, should mean roundstart plants are fine. + if(!plant_controller) + world << "Plant controller does not exist and [src] requires it. Aborting." + del(src) + return + + seed = plant_controller.seeds[plantname] + + if(!seed) + return + + name = "[seed.seed_name]" + + update_icon() + + if(!seed.chems) + return + + potency = seed.get_trait(TRAIT_POTENCY) + + for(var/rid in seed.chems) + var/list/reagent_data = seed.chems[rid] + if(reagent_data && reagent_data.len) + var/rtotal = reagent_data[1] + if(reagent_data.len > 1 && potency > 0) + rtotal += round(potency/reagent_data[2]) + reagents.add_reagent(rid,max(1,rtotal)) + update_desc() + if(reagents.total_volume > 0) + bitesize = 1+round(reagents.total_volume / 2, 1) + +/obj/item/weapon/reagent_containers/food/snacks/grown/proc/update_desc() + + if(!seed) + return + if(!plant_controller) + sleep(250) // ugly hack, should mean roundstart plants are fine. + if(!plant_controller) + world << "Plant controller does not exist and [src] requires it. Aborting." + del(src) + return + + if(plant_controller.product_descs["[seed.uid]"]) + desc = plant_controller.product_descs["[seed.uid]"] + else + var/list/descriptors = list() + if(reagents.has_reagent("sugar") || reagents.has_reagent("cherryjelly") || reagents.has_reagent("honey") || reagents.has_reagent("berryjuice")) + descriptors |= "sweet" + if(reagents.has_reagent("anti_toxin")) + descriptors |= "astringent" + if(reagents.has_reagent("frostoil")) + descriptors |= "numbing" + if(reagents.has_reagent("nutriment")) + descriptors |= "nutritious" + if(reagents.has_reagent("condensedcapsaicin") || reagents.has_reagent("capsaicin")) + descriptors |= "spicy" + if(reagents.has_reagent("coco")) + descriptors |= "bitter" + if(reagents.has_reagent("orangejuice") || reagents.has_reagent("lemonjuice") || reagents.has_reagent("limejuice")) + descriptors |= "sweet-sour" + if(reagents.has_reagent("radium") || reagents.has_reagent("uranium")) + descriptors |= "radioactive" + if(reagents.has_reagent("amatoxin") || reagents.has_reagent("toxin")) + descriptors |= "poisonous" + if(reagents.has_reagent("psilocybin") || reagents.has_reagent("space_drugs")) + descriptors |= "hallucinogenic" + if(reagents.has_reagent("bicaridine")) + descriptors |= "medicinal" + if(reagents.has_reagent("gold")) + descriptors |= "shiny" + if(reagents.has_reagent("lube")) + descriptors |= "slippery" + if(reagents.has_reagent("pacid") || reagents.has_reagent("sacid")) + descriptors |= "acidic" + if(seed.get_trait(TRAIT_JUICY)) + descriptors |= "juicy" + if(seed.get_trait(TRAIT_STINGS)) + descriptors |= "stinging" + if(seed.get_trait(TRAIT_TELEPORTING)) + descriptors |= "glowing" + if(seed.get_trait(TRAIT_EXPLOSIVE)) + descriptors |= "bulbous" + + var/descriptor_num = rand(2,4) + var/descriptor_count = descriptor_num + desc = "A" + while(descriptors.len && descriptor_num > 0) + var/chosen = pick(descriptors) + descriptors -= chosen + desc += "[(descriptor_count>1 && descriptor_count!=descriptor_num) ? "," : "" ] [chosen]" + descriptor_num-- + if(seed.seed_noun == "spores") + desc += " mushroom" + else + desc += " fruit" + plant_controller.product_descs["[seed.uid]"] = desc + desc += ". Delicious! Probably." + +/obj/item/weapon/reagent_containers/food/snacks/grown/update_icon() + if(!seed || !plant_controller || !plant_controller.plant_icon_cache) + return + overlays.Cut() + var/image/plant_icon + var/icon_key = "fruit-[seed.get_trait(TRAIT_PRODUCT_ICON)]-[seed.get_trait(TRAIT_PRODUCT_COLOUR)]-[seed.get_trait(TRAIT_PLANT_COLOUR)]" + if(plant_controller.plant_icon_cache[icon_key]) + plant_icon = plant_controller.plant_icon_cache[icon_key] + else + plant_icon = image('icons/obj/hydroponics_products.dmi',"blank") + var/image/fruit_base = image('icons/obj/hydroponics_products.dmi',"[seed.get_trait(TRAIT_PRODUCT_ICON)]-product") + fruit_base.color = "[seed.get_trait(TRAIT_PRODUCT_COLOUR)]" + plant_icon.overlays |= fruit_base + if("[seed.get_trait(TRAIT_PRODUCT_ICON)]-leaf" in icon_states('icons/obj/hydroponics_products.dmi')) + var/image/fruit_leaves = image('icons/obj/hydroponics_products.dmi',"[seed.get_trait(TRAIT_PRODUCT_ICON)]-leaf") + fruit_leaves.color = "[seed.get_trait(TRAIT_PLANT_COLOUR)]" + plant_icon.overlays |= fruit_leaves + plant_controller.plant_icon_cache[icon_key] = plant_icon + overlays |= plant_icon + +/obj/item/weapon/reagent_containers/food/snacks/grown/Crossed(var/mob/living/M) + if(seed && seed.get_trait(TRAIT_JUICY) == 2) + if(istype(M)) + + if(M.buckled) + return + + if(istype(M,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + if(H.shoes && H.shoes.flags & NOSLIP) + return + + M.stop_pulling() + M << "You slipped on the [name]!" + playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3) + M.Stun(8) + M.Weaken(5) + seed.thrown_at(src,M) + sleep(-1) + if(src) del(src) + return + +/obj/item/weapon/reagent_containers/food/snacks/grown/throw_impact(atom/hit_atom) + ..() + if(seed) seed.thrown_at(src,hit_atom) + +/obj/item/weapon/reagent_containers/food/snacks/grown/attackby(var/obj/item/weapon/W, var/mob/user) + + if(seed) + if(seed.get_trait(TRAIT_PRODUCES_POWER) && istype(W, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/C = W + if(C.use(5)) + //TODO: generalize this. + user << "You add some cable to the [src.name] and slide it inside the battery casing." + var/obj/item/weapon/stock_parts/cell/potato/pocell = new /obj/item/weapon/stock_parts/cell/potato(get_turf(user)) + if(src.loc == user && !(user.l_hand && user.r_hand) && istype(user,/mob/living/carbon/human)) + user.put_in_hands(pocell) + pocell.maxcharge = src.potency * 10 + pocell.charge = pocell.maxcharge + del(src) + return + else if(W.sharp) + if(seed.kitchen_tag == "pumpkin") // Ugggh these checks are awful. + user.show_message("You carve a face into [src]!", 1) + new /obj/item/clothing/head/hardhat/pumpkinhead (user.loc) + del(src) + return + else if(seed.kitchen_tag == "potato") + user << "You slice \the [src] into sticks." + new /obj/item/weapon/reagent_containers/food/snacks/rawsticks(get_turf(src)) + del(src) + return + else if(seed.kitchen_tag == "carrot") + user << "You slice \the [src] into sticks." + new /obj/item/weapon/reagent_containers/food/snacks/carrotfries(get_turf(src)) + del(src) + return + else if(seed.kitchen_tag == "watermelon") + user << "You slice \the [src] into large slices." + for(var/i=0,i<5,i++) + new /obj/item/weapon/reagent_containers/food/snacks/watermelonslice(get_turf(src)) + del(src) + return + else if(seed.kitchen_tag == "soybeans") + user << "You roughly chop up \the [src]." + new /obj/item/weapon/reagent_containers/food/snacks/soydope(get_turf(src)) + del(src) + return + else if(seed.chems) + if(istype(W,/obj/item/weapon/hatchet) && !isnull(seed.chems["woodpulp"])) + user.show_message("You make planks out of \the [src]!", 1) + for(var/i=0,i<2,i++) + var/obj/item/stack/sheet/wood/NG = new (user.loc) + NG.color = seed.get_trait(TRAIT_PRODUCT_COLOUR) + for (var/obj/item/stack/sheet/wood/G in user.loc) + if(G==NG) + continue + if(G.amount>=G.max_amount) + continue + G.attackby(NG, user) + user << "You add the newly-formed wood to the stack. It now contains [NG.amount] planks." + del(src) + return + else if(istype(W, /obj/item/weapon/rollingpaper)) + if(seed.kitchen_tag == "ambrosia" || seed.kitchen_tag == "ambrosiadeus" || seed.kitchen_tag == "tobacco" || seed.kitchen_tag == "stobacco") + user.unEquip(W) + if(seed.kitchen_tag == "ambrosia") + var/obj/item/clothing/mask/cigarette/joint/J = new /obj/item/clothing/mask/cigarette/joint(user.loc) + J.chem_volume = src.reagents.total_volume + src.reagents.trans_to(J, J.chem_volume) + del(W) + user.put_in_active_hand(J) + else if(seed.kitchen_tag == "ambrosiadeus") + var/obj/item/clothing/mask/cigarette/joint/deus/J = new /obj/item/clothing/mask/cigarette/joint/deus(user.loc) + J.chem_volume = src.reagents.total_volume + src.reagents.trans_to(J, J.chem_volume) + del(W) + user.put_in_active_hand(J) + else if(seed.kitchen_tag == "tobacco" || seed.kitchen_tag == "stobacco") + var/obj/item/clothing/mask/cigarette/handroll/J = new /obj/item/clothing/mask/cigarette/handroll(user.loc) + J.chem_volume = src.reagents.total_volume + src.reagents.trans_to(J, J.chem_volume) + del(W) + user.put_in_active_hand(J) + user << "\blue You roll the [src] into a rolling paper." + del(src) + else + user << "\red You can't roll a smokable from the [src]." + + ..() + +/obj/item/weapon/reagent_containers/food/snacks/grown/attack(var/mob/living/carbon/M, var/mob/user, var/def_zone) + if(user == M) + return ..() + + if(user.a_intent == "hurt") + + // This is being copypasted here because reagent_containers (WHY DOES FOOD DESCEND FROM THAT) overrides it completely. + // TODO: refactor all food paths to be less horrible and difficult to work with in this respect. ~Z + if(!istype(M) || (can_operate(M) && do_surgery(M,user,src))) return 0 + + user.lastattacked = M + M.lastattacker = user + user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" + M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" + msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" ) + + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + var/hit = H.attacked_by(src, user, def_zone) + if(hit && hitsound) + playsound(loc, hitsound, 50, 1, -1) + return hit + else + if(attack_verb.len) + user.visible_message("[M] has been [pick(attack_verb)] with [src] by [user]!") + else + user.visible_message("[M] has been attacked with [src] by [user]!") + + if (hitsound) + playsound(loc, hitsound, 50, 1, -1) + switch(damtype) + if("brute") + M.take_organ_damage(force) + if(prob(33)) + var/turf/simulated/location = get_turf(M) + if(istype(location)) location.add_blood_floor(M) + if("fire") + if (!(RESIST_COLD in M.mutations)) + M.take_organ_damage(0, force) + M.updatehealth() + + if(seed && seed.get_trait(TRAIT_STINGS)) + if(!reagents || reagents.total_volume <= 0) + return + reagents.remove_any(rand(1,3)) + seed.thrown_at(src,M) + sleep(-1) + if(!src) + return + if(prob(35)) + if(user) + user << "\The [src] has fallen to bits." + //user.drop_from_inventory(src) + del(src) + + add_fingerprint(user) + return 1 + + else + ..() + +/obj/item/weapon/reagent_containers/food/snacks/grown/attack_self(mob/user as mob) + + if(!seed) + return + + if(istype(user.loc,/turf/space)) + return + + if(user.a_intent == "hurt") + user.visible_message("\The [user] squashes \the [src]!") + seed.thrown_at(src,user) + sleep(-1) + if(src) del(src) + return + + if(seed.kitchen_tag == "grass") + user.show_message("You make a grass tile out of \the [src]!", 1) + for(var/i=0,i<2,i++) + var/obj/item/stack/tile/grass/G = new (user.loc) + G.color = seed.get_trait(TRAIT_PRODUCT_COLOUR) + for (var/obj/item/stack/tile/grass/NG in user.loc) + if(G==NG) + continue + if(NG.amount>=NG.max_amount) + continue + NG.attackby(G, user) + user << "You add the newly-formed grass to the stack. It now contains [G.amount] tiles." + del(src) + return + + if(seed.get_trait(TRAIT_SPREAD) > 0) + user << "You plant the [src.name]." + new /obj/machinery/portable_atmospherics/hydroponics/soil/invisible(get_turf(user),src.seed) + new /obj/effect/plant(get_turf(user), src.seed) + del(src) + return + + /* + if(seed.kitchen_tag) + switch(seed.kitchen_tag) + if("shand") + var/obj/item/stack/medical/bruise_pack/tajaran/poultice = new /obj/item/stack/medical/bruise_pack/tajaran(user.loc) + poultice.heal_brute = potency + user << "You mash the leaves into a poultice." + del(src) + return + if("mtear") + var/obj/item/stack/medical/ointment/tajaran/poultice = new /obj/item/stack/medical/ointment/tajaran(user.loc) + poultice.heal_burn = potency + user << "You mash the petals into a poultice." + del(src) + return + */ + +/obj/item/weapon/reagent_containers/food/snacks/grown/pickup(mob/user) + ..() + if(!seed) + return + if(seed.get_trait(TRAIT_BIOLUM)) + user.SetLuminosity(user.luminosity + seed.get_trait(TRAIT_BIOLUM)) + SetLuminosity(0) + if(seed.get_trait(TRAIT_STINGS)) + var/mob/living/carbon/human/H = user + if(istype(H) && H.gloves) + return + if(!reagents || reagents.total_volume <= 0) + return + reagents.remove_any(rand(1,3)) //Todo, make it actually remove the reagents the seed uses. + seed.do_thorns(H,src) + seed.do_sting(H,src,pick("r_hand","l_hand")) + +/obj/item/weapon/reagent_containers/food/snacks/grown/dropped(mob/user) + ..() + if(seed && seed.get_trait(TRAIT_BIOLUM)) + user.SetLuminosity(user.luminosity - seed.get_trait(TRAIT_BIOLUM)) + SetLuminosity(seed.get_trait(TRAIT_BIOLUM)) diff --git a/code/modules/hydroponics/grown_inedible.dm b/code/modules/hydroponics/grown_inedible.dm index a7cb080602b..8c23033a586 100644 --- a/code/modules/hydroponics/grown_inedible.dm +++ b/code/modules/hydroponics/grown_inedible.dm @@ -8,7 +8,7 @@ var/plantname var/potency = 1 -/obj/item/weapon/grown/New() +/obj/item/weapon/grown/New(newloc,planttype) ..() @@ -17,112 +17,20 @@ R.my_atom = src //Handle some post-spawn var stuff. - spawn(1) - // Fill the object up with the appropriate reagents. - if(!isnull(plantname)) - var/datum/seed/S = seed_types[plantname] - if(!S || !S.chems) - return - - potency = S.potency - - for(var/rid in S.chems) - var/list/reagent_data = S.chems[rid] - var/rtotal = reagent_data[1] - if(reagent_data.len > 1 && potency > 0) - rtotal += round(potency/reagent_data[2]) - reagents.add_reagent(rid,max(1,rtotal)) - -/obj/item/weapon/grown/proc/changePotency(newValue) //-QualityVan - potency = newValue - -/obj/item/weapon/grown/log - name = "towercap" - name = "tower-cap log" - desc = "It's better than bad, it's good!" - icon = 'icons/obj/harvest.dmi' - icon_state = "logs" - force = 5 - throwforce = 5 - w_class = 3.0 - throw_speed = 3 - throw_range = 3 - origin_tech = "materials=1" - attack_verb = list("bashed", "battered", "bludgeoned", "whacked") - - attackby(obj/item/weapon/W as obj, mob/user as mob, params) - if(istype(W, /obj/item/weapon/circular_saw) || istype(W, /obj/item/weapon/hatchet) || (istype(W, /obj/item/weapon/twohanded/fireaxe) && W:wielded) || istype(W, /obj/item/weapon/melee/energy)) - user.show_message("You make planks out of \the [src]!", 1) - for(var/i=0,i<2,i++) - var/obj/item/stack/sheet/wood/NG = new (user.loc) - for (var/obj/item/stack/sheet/wood/G in user.loc) - if(G==NG) - continue - if(G.amount>=G.max_amount) - continue - G.attackby(NG, user, params) - usr << "You add the newly-formed wood to the stack. It now contains [NG.amount] planks." - del(src) + if(planttype) + plantname = planttype + var/datum/seed/S = plant_controller.seeds[plantname] + if(!S || !S.chems) return -/obj/item/weapon/grown/sunflower // FLOWER POWER! - plantname = "sunflowers" - name = "sunflower" - desc = "It's beautiful! A certain person might beat you to death if you trample these." - icon = 'icons/obj/harvest.dmi' - icon_state = "sunflower" - damtype = "fire" - force = 0 - throwforce = 1 - w_class = 1.0 - throw_speed = 1 - throw_range = 3 + potency = S.get_trait(TRAIT_POTENCY) -/obj/item/weapon/grown/sunflower/attack(mob/M as mob, mob/user as mob) - M << " [user] smacks you with a sunflower!FLOWER POWER" - user << " Your sunflower's FLOWER POWER strikes [M]" - -/obj/item/weapon/grown/nettle // -- Skie - plantname = "nettle" - desc = "It's probably not wise to touch it with bare hands..." - icon = 'icons/obj/weapons.dmi' - name = "nettle" - icon_state = "nettle" - damtype = "fire" - force = 15 - throwforce = 1 - w_class = 2.0 - throw_speed = 1 - throw_range = 3 - origin_tech = "combat=1" - New() - ..() - spawn(5) - force = round((5+potency/5), 1) - -/obj/item/weapon/grown/nettle/pickup(mob/living/carbon/human/user as mob) - if(!user.gloves) - user << "\red The nettle burns your bare hand!" - if(istype(user, /mob/living/carbon/human)) - var/organ = ((user.hand ? "l_":"r_") + "arm") - var/obj/item/organ/external/affecting = user.get_organ(organ) - if(affecting.take_damage(0,force)) - user.UpdateDamageIcon() - else - user.take_organ_damage(0,force) - -/obj/item/weapon/grown/nettle/afterattack(atom/A as mob|obj, mob/user as mob, proximity) - if(!proximity) return - if(force > 0) - force -= rand(1,(force/3)+1) // When you whack someone with it, leaves fall off - playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - else - usr << "All the leaves have fallen off the nettle from violent whacking." - del(src) - -/obj/item/weapon/grown/nettle/changePotency(newValue) //-QualityVan - potency = newValue - force = round((5+potency/5), 1) + for(var/rid in S.chems) + var/list/reagent_data = S.chems[rid] + var/rtotal = reagent_data[1] + if(reagent_data.len > 1 && potency > 0) + rtotal += round(potency/reagent_data[2]) + reagents.add_reagent(rid,max(1,rtotal)) /obj/item/weapon/grown/deathnettle // -- Skie plantname = "deathnettle" @@ -147,53 +55,10 @@ viewers(user) << "\red [user] is eating some of the [src.name]! It looks like \he's trying to commit suicide." return (BRUTELOSS|TOXLOSS) -/obj/item/weapon/grown/deathnettle/pickup(mob/living/carbon/human/user as mob) - if(!user.gloves) - if(istype(user, /mob/living/carbon/human)) - var/organ = ((user.hand ? "l_":"r_") + "arm") - var/obj/item/organ/external/affecting = user.get_organ(organ) - if(affecting.take_damage(0,force)) - user.UpdateDamageIcon() - else - user.take_organ_damage(0,force) - if(prob(50)) - user.Paralyse(5) - user << "\red You are stunned by the Deathnettle when you try picking it up!" - -/obj/item/weapon/grown/deathnettle/attack(mob/living/carbon/M as mob, mob/user as mob) - if(!..()) return - if(istype(M, /mob/living)) - M << "\red You are stunned by the powerful acid of the Deathnettle!" - - M.attack_log += text("\[[time_stamp()]\] Had the [src.name] used on them by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] on [M.name] ([M.ckey])") - msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] used the [src.name] on [M.name] ([M.ckey]) (JMP)") - - playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - - M.eye_blurry += force/7 - if(prob(20)) - M.Paralyse(force/6) - M.Weaken(force/15) - M.drop_item() - -/obj/item/weapon/grown/deathnettle/afterattack(atom/A as mob|obj, mob/user as mob, proximity) - if(!proximity) return - if (force > 0) - force -= rand(1,(force/3)+1) // When you whack someone with it, leaves fall off - - else - usr << "All the leaves have fallen off the deathnettle from violent whacking." - del(src) - -/obj/item/weapon/grown/deathnettle/changePotency(newValue) //-QualityVan - potency = newValue - force = round((5+potency/2.5), 1) - /obj/item/weapon/corncob name = "corn cob" desc = "A reminder of meals gone by." - icon = 'icons/obj/harvest.dmi' + icon = 'icons/obj/trash.dmi' icon_state = "corncob" item_state = "corncob" w_class = 2.0 @@ -201,10 +66,21 @@ throw_speed = 4 throw_range = 20 -/obj/item/weapon/corncob/attackby(obj/item/weapon/W as obj, mob/user as mob, params) +/obj/item/weapon/corncob/attackby(obj/item/weapon/W as obj, mob/user as mob) ..() if(istype(W, /obj/item/weapon/circular_saw) || istype(W, /obj/item/weapon/hatchet) || istype(W, /obj/item/weapon/kitchen/utensil/knife) || istype(W, /obj/item/weapon/kitchenknife) || istype(W, /obj/item/weapon/kitchenknife/ritual)) user << "You use [W] to fashion a pipe out of the corn cob!" new /obj/item/clothing/mask/cigarette/pipe/cobpipe (user.loc) del(src) return + +/obj/item/weapon/bananapeel + name = "banana peel" + desc = "A peel from a banana." + icon = 'icons/obj/items.dmi' + icon_state = "banana_peel" + item_state = "banana_peel" + w_class = 2.0 + throwforce = 0 + throw_speed = 4 + throw_range = 20 diff --git a/code/modules/hydroponics/grown_predefined.dm b/code/modules/hydroponics/grown_predefined.dm new file mode 100644 index 00000000000..682ce791e91 --- /dev/null +++ b/code/modules/hydroponics/grown_predefined.dm @@ -0,0 +1,40 @@ +// Predefined types for placing on the map. + +/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/libertycap + plantname = "libertycap" + +/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris + plantname = "ambrosia" + +/obj/item/weapon/reagent_containers/food/snacks/grown/tomato + plantname = "tomato" + +/obj/item/weapon/reagent_containers/food/snacks/grown/carrot + plantname = "carrot" + +/obj/item/weapon/reagent_containers/food/snacks/grown/berries + plantname = "berries" + +/obj/item/weapon/reagent_containers/food/snacks/grown/banana + plantname = "banana" + +/obj/item/weapon/reagent_containers/food/snacks/grown/chili + plantname = "chili" + +/obj/item/weapon/reagent_containers/food/snacks/grown/lemon + plantname = "lemon" + +/obj/item/weapon/reagent_containers/food/snacks/grown/cherries + plantname = "cherry" + +/obj/item/weapon/reagent_containers/food/snacks/grown/orange + plantname = "orange" + +/obj/item/weapon/reagent_containers/food/snacks/grown/corn + plantname = "corn" + +/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/amanita + plantname = "amanita" + +/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiadeus + plantname = "ambrosiadeus" \ No newline at end of file diff --git a/code/modules/hydroponics/seed.dm b/code/modules/hydroponics/seed.dm new file mode 100644 index 00000000000..abb67db4615 --- /dev/null +++ b/code/modules/hydroponics/seed.dm @@ -0,0 +1,743 @@ +/datum/plantgene + var/genetype // Label used when applying trait. + var/list/values // Values to copy into the target seed datum. + +/datum/seed + //Tracking. + var/uid // Unique identifier. + var/name // Index for global list. + var/seed_name // Plant name for seed packet. + var/seed_noun = "seeds" // Descriptor for packet. + var/display_name // Prettier name. + var/roundstart // If set, seed will not display variety number. + var/mysterious // Only used for the random seed packets. + var/can_self_harvest = 0 // Mostly used for living mobs. + var/growth_stages = 0 // Number of stages the plant passes through before it is mature. + var/list/traits = list() // Initialized in New() + var/list/mutants // Possible predefined mutant varieties, if any. + var/list/chems // Chemicals that plant produces in products/injects into victim. + var/list/consume_gasses // The plant will absorb these gasses during its life. + var/list/exude_gasses // The plant will exude these gasses during its life. + var/kitchen_tag // Used by the reagent grinder. + var/trash_type // Garbage item produced when eaten. + var/splat_type = /obj/effect/decal/cleanable/fruit_smudge // Graffiti decal. + var/has_mob_product + +/datum/seed/New() + + set_trait(TRAIT_IMMUTABLE, 0) // If set, plant will never mutate. If -1, plant is highly mutable. + set_trait(TRAIT_HARVEST_REPEAT, 0) // If 1, this plant will fruit repeatedly. + set_trait(TRAIT_PRODUCES_POWER, 0) // Can be used to make a battery. + set_trait(TRAIT_JUICY, 0) // When thrown, causes a splatter decal. + set_trait(TRAIT_EXPLOSIVE, 0) // When thrown, acts as a grenade. + set_trait(TRAIT_CARNIVOROUS, 0) // 0 = none, 1 = eat pests in tray, 2 = eat living things (when a vine). + set_trait(TRAIT_PARASITE, 0) // 0 = no, 1 = gain health from weed level. + set_trait(TRAIT_STINGS, 0) // Can cause damage/inject reagents when thrown or handled. + set_trait(TRAIT_YIELD, 0) // Amount of product. + set_trait(TRAIT_SPREAD, 0) // 0 limits plant to tray, 1 = creepers, 2 = vines. + set_trait(TRAIT_MATURATION, 0) // Time taken before the plant is mature. + set_trait(TRAIT_PRODUCTION, 0) // Time before harvesting can be undertaken again. + set_trait(TRAIT_TELEPORTING, 0) // Uses the bluespace tomato effect. + set_trait(TRAIT_BIOLUM, 0) // Plant is bioluminescent. + set_trait(TRAIT_ALTER_TEMP, 0) // If set, the plant will periodically alter local temp by this amount. + set_trait(TRAIT_PRODUCT_ICON, 0) // Icon to use for fruit coming from this plant. + set_trait(TRAIT_PLANT_ICON, 0) // Icon to use for the plant growing in the tray. + set_trait(TRAIT_PRODUCT_COLOUR, 0) // Colour to apply to product icon. + set_trait(TRAIT_BIOLUM_COLOUR, 0) // The colour of the plant's radiance. + set_trait(TRAIT_POTENCY, 1) // General purpose plant strength value. + set_trait(TRAIT_REQUIRES_NUTRIENTS, 1) // The plant can starve. + set_trait(TRAIT_REQUIRES_WATER, 1) // The plant can become dehydrated. + set_trait(TRAIT_WATER_CONSUMPTION, 3) // Plant drinks this much per tick. + set_trait(TRAIT_LIGHT_TOLERANCE, 5) // Departure from ideal that is survivable. + set_trait(TRAIT_TOXINS_TOLERANCE, 5) // Resistance to poison. + set_trait(TRAIT_PEST_TOLERANCE, 5) // Threshold for pests to impact health. + set_trait(TRAIT_WEED_TOLERANCE, 5) // Threshold for weeds to impact health. + set_trait(TRAIT_IDEAL_LIGHT, 8) // Preferred light level in luminosity. + set_trait(TRAIT_HEAT_TOLERANCE, 20) // Departure from ideal that is survivable. + set_trait(TRAIT_LOWKPA_TOLERANCE, 25) // Low pressure capacity. + set_trait(TRAIT_ENDURANCE, 100) // Maximum plant HP when growing. + set_trait(TRAIT_HIGHKPA_TOLERANCE, 200) // High pressure capacity. + set_trait(TRAIT_IDEAL_HEAT, 293) // Preferred temperature in Kelvin. + set_trait(TRAIT_NUTRIENT_CONSUMPTION, 0.25) // Plant eats this much per tick. + set_trait(TRAIT_PLANT_COLOUR, "#46B543") // Colour of the plant icon. + + spawn(5) + sleep(-1) + update_growth_stages() + +/datum/seed/proc/get_trait(var/trait) + return traits["[trait]"] + +/datum/seed/proc/set_trait(var/trait,var/nval,var/ubound,var/lbound, var/degrade) + if(!isnull(degrade)) nval *= degrade + if(!isnull(ubound)) nval = min(nval,ubound) + if(!isnull(lbound)) nval = max(nval,lbound) + traits["[trait]"] = nval + +/datum/seed/proc/create_spores(var/turf/T, var/obj/item/thrown) + if(!T) + return + if(!istype(T)) + T = get_turf(T) + if(!T) + return + + var/datum/reagents/R = new/datum/reagents(100) + R.my_atom = thrown + if(chems.len) + for(var/rid in chems) + var/injecting = min(5,max(1,get_trait(TRAIT_POTENCY)/3)) + R.add_reagent(rid,injecting) + + var/datum/effect/effect/system/chem_smoke_spread/S = new() + S.attach(T) + S.set_up(R, round(get_trait(TRAIT_POTENCY)/4), 0, T) + S.start() + +// Does brute damage to a target. +/datum/seed/proc/do_thorns(var/mob/living/carbon/human/target, var/obj/item/fruit, var/target_limb) + + if(!get_trait(TRAIT_CARNIVOROUS)) + return + + if(!istype(target)) + if(istype(target, /mob/living/simple_animal/mouse) || istype(target, /mob/living/simple_animal/lizard)) + new /obj/effect/decal/cleanable/blood/splatter(get_turf(target)) + del(target) + return + + + if(!target_limb) target_limb = pick("l_foot","r_foot","l_leg","r_leg","l_hand","r_hand","l_arm", "r_arm","head","chest","groin") + var/obj/item/organ/external/affecting = target.get_organ(target_limb) + var/damage = 0 + + if(get_trait(TRAIT_CARNIVOROUS)) + if(get_trait(TRAIT_CARNIVOROUS) == 2) + if(affecting) + target << "\The [fruit]'s thorns pierce your [affecting.name] greedily!" + else + target << "\The [fruit]'s thorns pierce your flesh greedily!" + damage = get_trait(TRAIT_POTENCY)/2 + else + if(affecting) + target << "\The [fruit]'s thorns dig deeply into your [affecting.name]!" + else + target << "\The [fruit]'s thorns dig deeply into your flesh!" + damage = get_trait(TRAIT_POTENCY)/5 + else + return + + if(affecting) + affecting.take_damage(damage, 0) + affecting.add_autopsy_data("Thorns",damage) + else + target.adjustBruteLoss(damage) + target.UpdateDamageIcon() + target.updatehealth() + +// Adds reagents to a target. +/datum/seed/proc/do_sting(var/mob/living/carbon/human/target, var/obj/item/fruit) + if(!get_trait(TRAIT_STINGS)) + return + if(chems && chems.len) + + var/body_coverage = HEAD|HEADCOVERSMOUTH|HEADCOVERSEYES|UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS + + for(var/obj/item/clothing/clothes in target) + if(target.l_hand == clothes|| target.r_hand == clothes) + continue + body_coverage &= ~(clothes.body_parts_covered) + + if(!body_coverage) + return + + target << "You are stung by \the [fruit]!" + for(var/rid in chems) + var/injecting = min(5,max(1,get_trait(TRAIT_POTENCY)/5)) + target.reagents.add_reagent(rid,injecting) + +//Splatter a turf. +/datum/seed/proc/splatter(var/turf/T,var/obj/item/thrown) + if(splat_type) + var/obj/effect/plant/splat = new splat_type(T, src) + if(!istype(splat)) // Plants handle their own stuff. + splat.name = "[thrown.name] [pick("smear","smudge","splatter")]" + if(get_trait(TRAIT_BIOLUM)) + if(get_trait(TRAIT_BIOLUM_COLOUR)) + splat.l_color = get_trait(TRAIT_BIOLUM_COLOUR) + splat.SetLuminosity(get_trait(TRAIT_BIOLUM)) + if(get_trait(TRAIT_PRODUCT_COLOUR)) + splat.color = get_trait(TRAIT_PRODUCT_COLOUR) + + if(chems) + for(var/mob/living/M in T.contents) + if(!M.reagents) + continue + for(var/chem in chems) + var/injecting = min(5,max(1,get_trait(TRAIT_POTENCY)/3)) + M.reagents.add_reagent(chem,injecting) + +//Applies an effect to a target atom. +/datum/seed/proc/thrown_at(var/obj/item/thrown,var/atom/target, var/force_explode) + + var/splatted + var/turf/origin_turf = get_turf(target) + + if(force_explode || get_trait(TRAIT_EXPLOSIVE)) + + create_spores(origin_turf, thrown) + + var/flood_dist = min(10,max(1,get_trait(TRAIT_POTENCY)/15)) + var/list/open_turfs = list() + var/list/closed_turfs = list() + var/list/valid_turfs = list() + open_turfs |= origin_turf + + // Flood fill to get affected turfs. + while(open_turfs.len) + var/turf/T = pick(open_turfs) + open_turfs -= T + closed_turfs |= T + valid_turfs |= T + + for(var/dir in alldirs) + var/turf/neighbor = get_step(T,dir) + if(!neighbor || (neighbor in closed_turfs) || (neighbor in open_turfs)) + continue + if(neighbor.density || get_dist(neighbor,origin_turf) > flood_dist || istype(neighbor,/turf/space)) + closed_turfs |= neighbor + continue + // Check for windows. + var/no_los + var/turf/last_turf = origin_turf + for(var/turf/target_turf in getline(origin_turf,neighbor)) + if(!last_turf.Enter(target_turf) || target_turf.density) + no_los = 1 + break + last_turf = target_turf + if(!no_los && !origin_turf.Enter(neighbor)) + no_los = 1 + if(no_los) + closed_turfs |= neighbor + continue + open_turfs |= neighbor + + for(var/turf/T in valid_turfs) + for(var/mob/living/M in T.contents) + apply_special_effect(M) + splatter(T,thrown) + origin_turf.visible_message("The [thrown.name] explodes!") + del(thrown) + return + + if(istype(target,/mob/living)) + splatted = apply_special_effect(target,thrown) + else if(istype(target,/turf)) + splatted = 1 + for(var/mob/living/M in target.contents) + apply_special_effect(M) + + if(get_trait(TRAIT_JUICY) && splatted) + splatter(origin_turf,thrown) + origin_turf.visible_message("The [thrown.name] splatters against [target]!") + del(thrown) + +/datum/seed/proc/handle_environment(var/turf/current_turf, var/datum/gas_mixture/environment, var/light_supplied, var/check_only) + + var/health_change = 0 + /* + // Handle gas consumption. + if(consume_gasses && consume_gasses.len) + var/missing_gas = 0 + for(var/gas in consume_gasses) + if(environment && environment.gas && environment.gas[gas] && \ + environment.gas[gas] >= consume_gasses[gas]) + if(!check_only) + environment.adjust_gas(gas,-consume_gasses[gas],1) + else + missing_gas++ + + if(missing_gas > 0) + health_change += missing_gas * HYDRO_SPEED_MULTIPLIER + */ + + // Process it. + var/pressure = environment.return_pressure() + if(pressure < get_trait(TRAIT_LOWKPA_TOLERANCE)|| pressure > get_trait(TRAIT_HIGHKPA_TOLERANCE)) + health_change += rand(1,3) * HYDRO_SPEED_MULTIPLIER + + if(abs(environment.temperature - get_trait(TRAIT_IDEAL_HEAT)) > get_trait(TRAIT_HEAT_TOLERANCE)) + health_change += rand(1,3) * HYDRO_SPEED_MULTIPLIER + + /* + // Handle gas production. + if(exude_gasses && exude_gasses.len && !check_only) + for(var/gas in exude_gasses) + environment.adjust_gas(gas, max(1,round((exude_gasses[gas]*(get_trait(TRAIT_POTENCY)/5))/exude_gasses.len))) + */ + + // Handle light requirements. + if(!light_supplied) + var/area/A = get_area(current_turf) + if(A) + if(A.lighting_use_dynamic) + light_supplied = max(0,min(10,current_turf.lighting_lumcount)-5) + else + light_supplied = 5 + if(light_supplied) + if(abs(light_supplied - get_trait(TRAIT_IDEAL_LIGHT)) > get_trait(TRAIT_LIGHT_TOLERANCE)) + health_change += rand(1,3) * HYDRO_SPEED_MULTIPLIER + + return health_change + +/datum/seed/proc/apply_special_effect(var/mob/living/target,var/obj/item/thrown) + + var/impact = 1 + do_sting(target,thrown) + do_thorns(target,thrown) + + // Bluespace tomato code copied over from grown.dm. + if(get_trait(TRAIT_TELEPORTING)) + + //Plant potency determines radius of teleport. + var/outer_teleport_radius = get_trait(TRAIT_POTENCY)/5 + var/inner_teleport_radius = get_trait(TRAIT_POTENCY)/15 + + var/list/turfs = list() + if(inner_teleport_radius > 0) + for(var/turf/T in orange(target,outer_teleport_radius)) + if(get_dist(target,T) >= inner_teleport_radius) + turfs |= T + + if(turfs.len) + // Moves the mob, causes sparks. + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, get_turf(target)) + s.start() + var/turf/picked = get_turf(pick(turfs)) // Just in case... + new/obj/effect/decal/cleanable/molten_item(get_turf(target)) // Leave a pile of goo behind for dramatic effect... + target.loc = picked // And teleport them to the chosen location. + + impact = 1 + + return impact + +//Creates a random seed. MAKE SURE THE LINE HAS DIVERGED BEFORE THIS IS CALLED. +/datum/seed/proc/randomize() + + roundstart = 0 + seed_name = "strange plant" // TODO: name generator. + display_name = "strange plants" // TODO: name generator. + mysterious = 1 + seed_noun = pick("spores","nodes","cuttings","seeds") + + set_trait(TRAIT_POTENCY,rand(5,30),200,0) + set_trait(TRAIT_PRODUCT_ICON,pick(plant_controller.plant_product_sprites)) + set_trait(TRAIT_PLANT_ICON,pick(plant_controller.plant_sprites)) + set_trait(TRAIT_PLANT_COLOUR,"#[get_random_colour(0,75,190)]") + set_trait(TRAIT_PRODUCT_COLOUR,"#[get_random_colour(0,75,190)]") + update_growth_stages() + + if(prob(20)) + set_trait(TRAIT_HARVEST_REPEAT,1) + + if(prob(15)) + if(prob(15)) + set_trait(TRAIT_JUICY,2) + else + set_trait(TRAIT_JUICY,1) + + if(prob(5)) + set_trait(TRAIT_STINGS,1) + + if(prob(5)) + set_trait(TRAIT_PRODUCES_POWER,1) + + if(prob(1)) + set_trait(TRAIT_EXPLOSIVE,1) + else if(prob(1)) + set_trait(TRAIT_TELEPORTING,1) + + if(prob(5)) + consume_gasses = list() + var/gas = pick("oxygen","nitrogen","plasma","carbon_dioxide") + consume_gasses[gas] = rand(3,9) + + if(prob(5)) + exude_gasses = list() + var/gas = pick("oxygen","nitrogen","plasma","carbon_dioxide") + exude_gasses[gas] = rand(3,9) + + chems = list() + if(prob(80)) + chems["nutriment"] = list(rand(1,10),rand(10,20)) + + var/additional_chems = rand(0,5) + + if(additional_chems) + var/list/possible_chems = list( + "woodpulp", + "styptic_powder", + "methamphetamine", + "cryoxadone", + "blood", + "water", + "potassium", + "plasticide", + "mutationtoxin", + "amutationtoxin", + "epinephrine", + "space_drugs", + "salglu_solution", + "mercury", + "sugar", + "radium", + "mutadone", + "mannitol", + "thermite", + "sal_acid", + "atropine", + "omnizine", + "salbutamol", + "plasma", + "synaptizine", + "haloperidol", + "potass_iodide", + "mitocholide", + "toxin", + "rezadone", + "antihol", + "slimejelly", + "cyanide", + "lsd", + "morphine" + ) + + for(var/x=1;x<=additional_chems;x++) + if(!possible_chems.len) + break + var/new_chem = pick(possible_chems) + possible_chems -= new_chem + chems[new_chem] = list(rand(1,10),rand(10,20)) + + if(prob(90)) + set_trait(TRAIT_REQUIRES_NUTRIENTS,1) + set_trait(TRAIT_NUTRIENT_CONSUMPTION,rand(25)/25) + else + set_trait(TRAIT_REQUIRES_NUTRIENTS,0) + + if(prob(90)) + set_trait(TRAIT_REQUIRES_WATER,1) + set_trait(TRAIT_WATER_CONSUMPTION,rand(10)) + else + set_trait(TRAIT_REQUIRES_WATER,0) + + set_trait(TRAIT_IDEAL_HEAT, rand(100,400)) + set_trait(TRAIT_HEAT_TOLERANCE, rand(10,30)) + set_trait(TRAIT_IDEAL_LIGHT, rand(2,10)) + set_trait(TRAIT_LIGHT_TOLERANCE, rand(2,7)) + set_trait(TRAIT_TOXINS_TOLERANCE, rand(2,7)) + set_trait(TRAIT_PEST_TOLERANCE, rand(2,7)) + set_trait(TRAIT_WEED_TOLERANCE, rand(2,7)) + set_trait(TRAIT_LOWKPA_TOLERANCE, rand(10,50)) + set_trait(TRAIT_HIGHKPA_TOLERANCE,rand(100,300)) + + if(prob(5)) + set_trait(TRAIT_ALTER_TEMP,rand(-5,5)) + + if(prob(1)) + set_trait(TRAIT_IMMUTABLE,-1) + + var/carnivore_prob = rand(100) + if(carnivore_prob < 5) + set_trait(TRAIT_CARNIVOROUS,2) + else if(carnivore_prob < 10) + set_trait(TRAIT_CARNIVOROUS,1) + + if(prob(10)) + set_trait(TRAIT_PARASITE,1) + + var/vine_prob = rand(100) + if(vine_prob < 5) + set_trait(TRAIT_SPREAD,2) + else if(vine_prob < 10) + set_trait(TRAIT_SPREAD,1) + + if(prob(5)) + set_trait(TRAIT_BIOLUM,1) + set_trait(TRAIT_BIOLUM_COLOUR,"#[get_random_colour(0,75,190)]") + + set_trait(TRAIT_ENDURANCE,rand(60,100)) + set_trait(TRAIT_YIELD,rand(3,15)) + set_trait(TRAIT_MATURATION,rand(5,15)) + set_trait(TRAIT_PRODUCTION,get_trait(TRAIT_MATURATION)+rand(2,5)) + +//Returns a key corresponding to an entry in the global seed list. +/datum/seed/proc/get_mutant_variant() + if(!mutants || !mutants.len || get_trait(TRAIT_IMMUTABLE) > 0) return 0 + return pick(mutants) + +//Mutates the plant overall (randomly). +/datum/seed/proc/mutate(var/degree,var/turf/source_turf) + + if(!degree || get_trait(TRAIT_IMMUTABLE) > 0) return + + source_turf.visible_message("\The [display_name] quivers!") + + //This looks like shit, but it's a lot easier to read/change this way. + var/total_mutations = rand(1,1+degree) + for(var/i = 0;i\The [display_name] withers rapidly!") + if(1) + set_trait(TRAIT_NUTRIENT_CONSUMPTION,get_trait(TRAIT_NUTRIENT_CONSUMPTION)+rand(-(degree*0.1),(degree*0.1)),5,0) + set_trait(TRAIT_WATER_CONSUMPTION, get_trait(TRAIT_WATER_CONSUMPTION) +rand(-degree,degree),50,0) + set_trait(TRAIT_JUICY, !get_trait(TRAIT_JUICY)) + set_trait(TRAIT_STINGS, !get_trait(TRAIT_STINGS)) + if(2) + set_trait(TRAIT_IDEAL_HEAT, get_trait(TRAIT_IDEAL_HEAT) + (rand(-5,5)*degree),800,70) + set_trait(TRAIT_HEAT_TOLERANCE, get_trait(TRAIT_HEAT_TOLERANCE) + (rand(-5,5)*degree),800,70) + set_trait(TRAIT_LOWKPA_TOLERANCE, get_trait(TRAIT_LOWKPA_TOLERANCE)+ (rand(-5,5)*degree),80,0) + set_trait(TRAIT_HIGHKPA_TOLERANCE, get_trait(TRAIT_HIGHKPA_TOLERANCE)+(rand(-5,5)*degree),500,110) + set_trait(TRAIT_EXPLOSIVE,1) + if(3) + set_trait(TRAIT_IDEAL_LIGHT, get_trait(TRAIT_IDEAL_LIGHT)+(rand(-1,1)*degree),30,0) + set_trait(TRAIT_LIGHT_TOLERANCE, get_trait(TRAIT_LIGHT_TOLERANCE)+(rand(-2,2)*degree),10,0) + if(4) + set_trait(TRAIT_TOXINS_TOLERANCE, get_trait(TRAIT_TOXINS_TOLERANCE)+(rand(-2,2)*degree),10,0) + if(5) + set_trait(TRAIT_WEED_TOLERANCE, get_trait(TRAIT_WEED_TOLERANCE)+(rand(-2,2)*degree),10, 0) + if(prob(degree*5)) + set_trait(TRAIT_CARNIVOROUS, get_trait(TRAIT_CARNIVOROUS)+rand(-degree,degree),2, 0) + if(get_trait(TRAIT_CARNIVOROUS)) + source_turf.visible_message("\The [display_name] shudders hungrily.") + if(6) + set_trait(TRAIT_WEED_TOLERANCE, get_trait(TRAIT_WEED_TOLERANCE)+(rand(-2,2)*degree),10, 0) + if(prob(degree*5)) + set_trait(TRAIT_PARASITE,!get_trait(TRAIT_PARASITE)) + if(7) + if(get_trait(TRAIT_YIELD) != -1) + set_trait(TRAIT_YIELD, get_trait(TRAIT_YIELD)+(rand(-2,2)*degree),10,0) + if(8) + set_trait(TRAIT_ENDURANCE, get_trait(TRAIT_ENDURANCE)+(rand(-5,5)*degree),100,10) + set_trait(TRAIT_PRODUCTION, get_trait(TRAIT_PRODUCTION)+(rand(-1,1)*degree),10, 1) + set_trait(TRAIT_POTENCY, get_trait(TRAIT_POTENCY)+(rand(-20,20)*degree),200, 0) + if(prob(degree*5)) + set_trait(TRAIT_SPREAD, get_trait(TRAIT_SPREAD)+rand(-1,1),2, 0) + source_turf.visible_message("\The [display_name] spasms visibly, shifting in the tray.") + if(9) + set_trait(TRAIT_MATURATION, get_trait(TRAIT_MATURATION)+(rand(-1,1)*degree),30, 0) + if(prob(degree*5)) + set_trait(TRAIT_HARVEST_REPEAT, !get_trait(TRAIT_HARVEST_REPEAT)) + if(10) + if(prob(degree*2)) + set_trait(TRAIT_BIOLUM, !get_trait(TRAIT_BIOLUM)) + if(get_trait(TRAIT_BIOLUM)) + source_turf.visible_message("\The [display_name] begins to glow!") + if(prob(degree*2)) + set_trait(TRAIT_BIOLUM_COLOUR,"#[get_random_colour(0,75,190)]") + source_turf.visible_message("\The [display_name]'s glow changes colour!") + else + source_turf.visible_message("\The [display_name]'s glow dims...") + if(11) + set_trait(TRAIT_TELEPORTING,1) + + return + +//Mutates a specific trait/set of traits. +/datum/seed/proc/apply_gene(var/datum/plantgene/gene) + + if(!gene || !gene.values || get_trait(TRAIT_IMMUTABLE) > 0) return + + // Splicing products has some detrimental effects on yield and lifespan. + // We handle this before we do the rest of the looping, as normal traits don't really include lists. + switch(gene.genetype) + if(GENE_BIOCHEMISTRY) + for(var/trait in list(TRAIT_YIELD, TRAIT_ENDURANCE)) + if(get_trait(trait) > 0) set_trait(trait,get_trait(trait),null,1,0.85) + + if(!chems) chems = list() + + var/list/gene_value = gene.values["[TRAIT_CHEMS]"] + for(var/rid in gene_value) + + var/list/gene_chem = gene_value[rid] + + if(!chems[rid]) + chems[rid] = gene_chem.Copy() + continue + + for(var/i=1;i<=gene_chem.len;i++) + + if(isnull(gene_chem[i])) gene_chem[i] = 0 + + if(chems[rid][i]) + chems[rid][i] = max(1,round((gene_chem[i] + chems[rid][i])/2)) + else + chems[rid][i] = gene_chem[i] + + var/list/new_gasses = gene.values["[TRAIT_EXUDE_GASSES]"] + if(islist(new_gasses)) + if(!exude_gasses) exude_gasses = list() + exude_gasses |= new_gasses + for(var/gas in exude_gasses) + exude_gasses[gas] = max(1,round(exude_gasses[gas]*0.8)) + + gene.values["[TRAIT_EXUDE_GASSES]"] = null + gene.values["[TRAIT_CHEMS]"] = null + + if(GENE_DIET) + var/list/new_gasses = gene.values["[TRAIT_CONSUME_GASSES]"] + consume_gasses |= new_gasses + gene.values["[TRAIT_CONSUME_GASSES]"] = null + if(GENE_METABOLISM) + has_mob_product = gene.values["mob_product"] + gene.values["mob_product"] = null + + for(var/trait in gene.values) + set_trait(trait,gene.values["[trait]"]) + + update_growth_stages() + +//Returns a list of the desired trait values. +/datum/seed/proc/get_gene(var/genetype) + + if(!genetype) return 0 + + var/list/traits_to_copy + var/datum/plantgene/P = new() + P.genetype = genetype + P.values = list() + + switch(genetype) + if(GENE_BIOCHEMISTRY) + P.values["[TRAIT_CHEMS]"] = chems + P.values["[TRAIT_EXUDE_GASSES]"] = exude_gasses + traits_to_copy = list(TRAIT_POTENCY) + if(GENE_OUTPUT) + traits_to_copy = list(TRAIT_PRODUCES_POWER,TRAIT_BIOLUM) + if(GENE_ATMOSPHERE) + traits_to_copy = list(TRAIT_HEAT_TOLERANCE,TRAIT_LOWKPA_TOLERANCE,TRAIT_HIGHKPA_TOLERANCE) + if(GENE_HARDINESS) + traits_to_copy = list(TRAIT_TOXINS_TOLERANCE,TRAIT_PEST_TOLERANCE,TRAIT_WEED_TOLERANCE,TRAIT_ENDURANCE) + if(GENE_METABOLISM) + P.values["mob_product"] = has_mob_product + traits_to_copy = list(TRAIT_REQUIRES_NUTRIENTS,TRAIT_REQUIRES_WATER,TRAIT_ALTER_TEMP) + if(GENE_VIGOUR) + traits_to_copy = list(TRAIT_PRODUCTION,TRAIT_MATURATION,TRAIT_YIELD,TRAIT_SPREAD) + if(GENE_DIET) + P.values["[TRAIT_CONSUME_GASSES]"] = consume_gasses + traits_to_copy = list(TRAIT_CARNIVOROUS,TRAIT_PARASITE,TRAIT_NUTRIENT_CONSUMPTION,TRAIT_WATER_CONSUMPTION) + if(GENE_ENVIRONMENT) + traits_to_copy = list(TRAIT_IDEAL_HEAT,TRAIT_IDEAL_LIGHT,TRAIT_LIGHT_TOLERANCE) + if(GENE_PIGMENT) + traits_to_copy = list(TRAIT_PLANT_COLOUR,TRAIT_PRODUCT_COLOUR,TRAIT_BIOLUM_COLOUR) + if(GENE_STRUCTURE) + traits_to_copy = list(TRAIT_PLANT_ICON,TRAIT_PRODUCT_ICON,TRAIT_HARVEST_REPEAT) + if(GENE_FRUIT) + traits_to_copy = list(TRAIT_STINGS,TRAIT_EXPLOSIVE,TRAIT_JUICY) + if(GENE_SPECIAL) + traits_to_copy = list(TRAIT_TELEPORTING) + + for(var/trait in traits_to_copy) + P.values["[trait]"] = get_trait(trait) + return (P ? P : 0) + +//Place the plant products at the feet of the user. +/datum/seed/proc/harvest(var/mob/user,var/yield_mod,var/harvest_sample,var/force_amount) + + if(!user) + return + + if(!force_amount && get_trait(TRAIT_YIELD) == 0 && !harvest_sample) + if(istype(user)) user << "You fail to harvest anything useful." + else + if(istype(user)) user << "You [harvest_sample ? "take a sample" : "harvest"] from the [display_name]." + + //This may be a new line. Update the global if it is. + if(name == "new line" || !(name in plant_controller.seeds)) + uid = plant_controller.seeds.len + 1 + name = "[uid]" + plant_controller.seeds[name] = src + + if(harvest_sample) + var/obj/item/seeds/seeds = new(get_turf(user)) + seeds.seed_type = name + seeds.update_seed() + return + + var/total_yield = 0 + if(!isnull(force_amount)) + total_yield = force_amount + else + if(get_trait(TRAIT_YIELD) > -1) + if(isnull(yield_mod) || yield_mod < 1) + yield_mod = 0 + total_yield = get_trait(TRAIT_YIELD) + else + total_yield = get_trait(TRAIT_YIELD) + rand(yield_mod) + total_yield = max(1,total_yield) + + currently_querying = list() + for(var/i = 0;iThe pod disgorges [product]!") + handle_living_product(product) + +// When the seed in this machine mutates/is modified, the tray seed value +// is set to a new datum copied from the original. This datum won't actually +// be put into the global datum list until the product is harvested, though. +/datum/seed/proc/diverge(var/modified) + + if(get_trait(TRAIT_IMMUTABLE) > 0) return + + //Set up some basic information. + var/datum/seed/new_seed = new + new_seed.name = "new line" + new_seed.uid = 0 + new_seed.roundstart = 0 + new_seed.can_self_harvest = can_self_harvest + new_seed.kitchen_tag = kitchen_tag + new_seed.trash_type = trash_type + new_seed.has_mob_product = has_mob_product + //Copy over everything else. + if(mutants) new_seed.mutants = mutants.Copy() + if(chems) new_seed.chems = chems.Copy() + if(consume_gasses) new_seed.consume_gasses = consume_gasses.Copy() + if(exude_gasses) new_seed.exude_gasses = exude_gasses.Copy() + + new_seed.seed_name = "[(roundstart ? "[(modified ? "modified" : "mutant")] " : "")][seed_name]" + new_seed.display_name = "[(roundstart ? "[(modified ? "modified" : "mutant")] " : "")][display_name]" + new_seed.seed_noun = seed_noun + new_seed.traits = traits.Copy() + new_seed.update_growth_stages() + return new_seed + +/datum/seed/proc/update_growth_stages() + if(get_trait(TRAIT_PLANT_ICON)) + growth_stages = plant_controller.plant_sprites[get_trait(TRAIT_PLANT_ICON)] + else + growth_stages = 0 diff --git a/code/modules/hydroponics/seed_controller.dm b/code/modules/hydroponics/seed_controller.dm new file mode 100644 index 00000000000..6a329b9d974 --- /dev/null +++ b/code/modules/hydroponics/seed_controller.dm @@ -0,0 +1,150 @@ +// Attempts to offload processing for the spreading plants from the MC. +// Processes vines/spreading plants. + +#define PLANTS_PER_TICK 500 // Cap on number of plant segments processed. +#define PLANT_TICK_TIME 75 // Number of ticks between the plant processor cycling. + +// Debug for testing seed genes. +/client/proc/show_plant_genes() + set category = "Debug" + set name = "Show Plant Genes" + set desc = "Prints the round's plant gene masks." + + if(!holder) return + + if(!plant_controller || !plant_controller.gene_tag_masks) + usr << "Gene masks not set." + return + + for(var/mask in plant_controller.gene_tag_masks) + usr << "[mask]: [plant_controller.gene_tag_masks[mask]]" + +var/global/datum/controller/plants/plant_controller // Set in New(). + +/datum/controller/plants + + var/plants_per_tick = PLANTS_PER_TICK + var/plant_tick_time = PLANT_TICK_TIME + var/list/product_descs = list() // Stores generated fruit descs. + var/list/plant_queue = list() // All queued plants. + var/list/seeds = list() // All seed data stored here. + var/list/gene_tag_masks = list() // Gene obfuscation for delicious trial and error goodness. + var/list/plant_icon_cache = list() // Stores images of growth, fruits and seeds. + 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. + +/datum/controller/plants/New() + if(plant_controller && plant_controller != src) + log_debug("Rebuilding plant controller.") + del(plant_controller) + plant_controller = src + setup() + process() + +// Predefined/roundstart varieties use a string key to make it +// easier to grab the new variety when mutating. Post-roundstart +// and mutant varieties use their uid converted to a string instead. +// Looks like shit but it's sort of necessary. +/datum/controller/plants/proc/setup() + + // Build the icon lists. + for(var/icostate in icon_states('icons/obj/hydroponics_growing.dmi')) + var/split = findtext(icostate,"-") + if(!split) + // invalid icon_state + continue + + var/ikey = copytext(icostate,(split+1)) + if(ikey == "dead") + // don't count dead icons + continue + ikey = text2num(ikey) + var/base = copytext(icostate,1,split) + + if(!(plant_sprites[base]) || (plant_sprites[base] 0) return 0 - return pick(mutants) - -//Mutates the plant overall (randomly). -/datum/seed/proc/mutate(var/degree,var/turf/source_turf) - - if(!degree || immutable > 0) return - - source_turf.visible_message("\blue \The [display_name] quivers!") - - //This looks like shit, but it's a lot easier to read/change this way. - var/total_mutations = rand(1,1+degree) - for(var/i = 0;ichanges colour!") - else - source_turf.visible_message("\blue \The [display_name]'s glow dims...") - if(11) - if(prob(degree*2)) - flowers = !flowers - if(flowers) - source_turf.visible_message("\blue \The [display_name] sprouts a bevy of flowers!") - if(prob(degree*2)) - flower_colour = "#[pick(list("FF0000","FF7F00","FFFF00","00FF00","0000FF","4B0082","8F00FF"))]" - source_turf.visible_message("\blue \The [display_name]'s flowers changes colour!") - else - source_turf.visible_message("\blue \The [display_name]'s flowers wither and fall off.") - return - -//Mutates a specific trait/set of traits. -/datum/seed/proc/apply_gene(var/datum/plantgene/gene) - - if(!gene || !gene.values || immutable > 0) return - - switch(gene.genetype) - - //Splicing products has some detrimental effects on yield and lifespan. - if("products") - - if(gene.values.len < 6) return - - yield = round(yield*0.5) - endurance = round(endurance*0.5) - lifespan = round(lifespan*0.8) - - if(!products) products = list() - products |= gene.values[1] - - if(!chems) chems = list() - for(var/rid in gene.values[2]) - var/existing_chem - for(var/chem in chems) - if(rid == chem) - existing_chem = 1 - break - - if(existing_chem) - chems[rid][1] = max(1,round((chems[rid][1]+gene.values[2][rid][1])/2)) - chems[rid][2] = max(1,round((chems[rid][2]+gene.values[2][rid][2])/2)) - else - chems[rid] = gene.values[2][rid] - - var/list/new_gasses = gene.values[3] - if(istype(new_gasses)) - if(!exude_gasses) exude_gasses = list() - exude_gasses |= new_gasses - for(var/gas in exude_gasses) - exude_gasses[gas] = max(1,round(exude_gasses[gas]*0.8)) - - alter_temp = gene.values[4] - potency = gene.values[5] - harvest_repeat = gene.values[6] - - if("consumption") - - if(gene.values.len < 7) return - - consume_gasses = gene.values[1] - requires_nutrients = gene.values[2] - nutrient_consumption = gene.values[3] - requires_water = gene.values[4] - water_consumption = gene.values[5] - carnivorous = gene.values[6] - parasite = gene.values[7] - - if("environment") - - if(gene.values.len < 6) return - - ideal_heat = gene.values[1] - heat_tolerance = gene.values[2] - ideal_light = gene.values[3] - light_tolerance = gene.values[4] - lowkpa_tolerance = gene.values[5] - highkpa_tolerance = gene.values[6] - - if("resistance") - - if(gene.values.len < 3) return - - toxins_tolerance = gene.values[1] - pest_tolerance = gene.values[2] - weed_tolerance = gene.values[3] - - if("vigour") - - if(gene.values.len < 6) return - - endurance = gene.values[1] - yield = gene.values[2] - lifespan = gene.values[3] - spread = gene.values[4] - maturation = gene.values[5] - production = gene.values[6] - - if("flowers") - - if(gene.values.len < 7) return - - product_icon = gene.values[1] - product_colour = gene.values[2] - biolum = gene.values[3] - biolum_colour = gene.values[4] - flowers = gene.values[5] - flower_icon = gene.values[6] - flower_colour = gene.values[7] - -//Returns a list of the desired trait values. -/datum/seed/proc/get_gene(var/genetype) - - if(!genetype) return 0 - - var/datum/plantgene/P = new() - P.genetype = genetype - - switch(genetype) - if("products") - P.values = list( - (products ? products : 0), - (chems ? chems : 0), - (exude_gasses ? exude_gasses : 0), - (alter_temp ? alter_temp : 0), - (potency ? potency : 0), - (harvest_repeat ? harvest_repeat : 0) - ) - - if("consumption") - P.values = list( - (consume_gasses ? consume_gasses : 0), - (requires_nutrients ? requires_nutrients : 0), - (nutrient_consumption ? nutrient_consumption : 0), - (requires_water ? requires_water : 0), - (water_consumption ? water_consumption : 0), - (carnivorous ? carnivorous : 0), - (parasite ? parasite : 0) - ) - - if("environment") - P.values = list( - (ideal_heat ? ideal_heat : 0), - (heat_tolerance ? heat_tolerance : 0), - (ideal_light ? ideal_light : 0), - (light_tolerance ? light_tolerance : 0), - (lowkpa_tolerance ? lowkpa_tolerance : 0), - (highkpa_tolerance ? highkpa_tolerance : 0) - ) - - if("resistance") - P.values = list( - (toxins_tolerance ? toxins_tolerance : 0), - (pest_tolerance ? pest_tolerance : 0), - (weed_tolerance ? weed_tolerance : 0) - ) - - if("vigour") - P.values = list( - (endurance ? endurance : 0), - (yield ? yield : 0), - (lifespan ? lifespan : 0), - (spread ? spread : 0), - (maturation ? maturation : 0), - (production ? production : 0) - ) - - if("flowers") - P.values = list( - (product_icon ? product_icon : 0), - (product_colour ? product_colour : 0), - (biolum ? biolum : 0), - (biolum_colour ? biolum_colour : 0), - (flowers ? flowers : 0), - (flower_icon ? flower_icon : 0), - (flower_colour ? flower_colour : 0) - ) - - return (P ? P : 0) - -//Place the plant products at the feet of the user. -/datum/seed/proc/harvest(var/mob/user,var/yield_mod,var/harvest_sample) - if(!user) - return - - var/got_product - if(!isnull(products) && products.len && yield > 0) - got_product = 1 - - if(!got_product) - user << "\red You fail to harvest anything useful." - else - user << "You [harvest_sample ? "take a sample" : "harvest"] from the [display_name]." - - //This may be a new line. Update the global if it is. - if(name == "new line" || !(name in seed_types)) - uid = seed_types.len + 1 - name = "[uid]" - seed_types[name] = src - - if(harvest_sample) - var/obj/item/seeds/seeds = new(get_turf(user)) - seeds.seed_type = name - seeds.update_seed() - return - - var/total_yield - if(isnull(yield_mod) || yield_mod < 1) - yield_mod = 0 - total_yield = yield - else - total_yield = max(1,rand(yield_mod,yield_mod+yield)) - - currently_querying = list() - for(var/i = 0;i 0) return - - //Set up some basic information. - var/datum/seed/new_seed = new - new_seed.name = "new line" - new_seed.uid = 0 - new_seed.roundstart = 0 - - //Copy over everything else. - if(products) new_seed.products = products.Copy() - if(mutants) new_seed.mutants = mutants.Copy() - if(chems) new_seed.chems = chems.Copy() - if(consume_gasses) new_seed.consume_gasses = consume_gasses.Copy() - if(exude_gasses) new_seed.exude_gasses = exude_gasses.Copy() - - new_seed.seed_name = "[(roundstart ? "[(modified ? "modified" : "mutant")] " : " ")][seed_name]" - new_seed.display_name = "[(roundstart ? "[(modified ? "modified" : "mutant")] " : " ")][display_name]" - new_seed.seed_noun = seed_noun - - new_seed.requires_nutrients = requires_nutrients - new_seed.nutrient_consumption = nutrient_consumption - new_seed.requires_water = requires_water - new_seed.water_consumption = water_consumption - new_seed.ideal_heat = ideal_heat - new_seed.heat_tolerance = heat_tolerance - new_seed.ideal_light = ideal_light - new_seed.light_tolerance = light_tolerance - new_seed.toxins_tolerance = toxins_tolerance - new_seed.lowkpa_tolerance = lowkpa_tolerance - new_seed.highkpa_tolerance = highkpa_tolerance - new_seed.pest_tolerance = pest_tolerance - new_seed.weed_tolerance = weed_tolerance - new_seed.endurance = endurance - new_seed.yield = yield - new_seed.lifespan = lifespan - new_seed.maturation = maturation - new_seed.production = production - new_seed.growth_stages = growth_stages - new_seed.harvest_repeat = harvest_repeat - new_seed.potency = potency - new_seed.spread = spread - new_seed.carnivorous = carnivorous - new_seed.parasite = parasite - new_seed.plant_icon = plant_icon - new_seed.product_icon = product_icon - new_seed.product_colour = product_colour - new_seed.packet_icon = packet_icon - new_seed.biolum = biolum - new_seed.biolum_colour = biolum_colour - new_seed.flowers = flowers - new_seed.flower_icon = flower_icon - new_seed.alter_temp = alter_temp - - return new_seed - -// Actual roundstart seed types after this point. // Chili plants/variants. /datum/seed/chili - name = "chili" seed_name = "chili" display_name = "chili plants" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/chili) chems = list("capsaicin" = list(3,5), "nutriment" = list(1,25)) - mutants = list("icechili", "ghostchili") - packet_icon = "seed-chili" - plant_icon = "chili" - harvest_repeat = 1 + mutants = list("icechili") + kitchen_tag = "chili" - lifespan = 20 - maturation = 5 - production = 5 - yield = 4 - potency = 20 +/datum/seed/chili/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,5) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,20) + set_trait(TRAIT_PRODUCT_ICON,"chili") + set_trait(TRAIT_PRODUCT_COLOUR,"#ED3300") + set_trait(TRAIT_PLANT_ICON,"bush2") /datum/seed/chili/ice name = "icechili" seed_name = "ice pepper" display_name = "ice-pepper plants" mutants = null - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/icepepper) chems = list("frostoil" = list(3,5), "nutriment" = list(1,50)) - packet_icon = "seed-icepepper" - plant_icon = "chiliice" + kitchen_tag = "icechili" - maturation = 4 - production = 4 - -/datum/seed/chili/ghost - name = "ghostchili" - seed_name = "ghost chili pepper" - display_name = "ghost chili pepper plants" - mutants = null - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/ghost_chilli) - chems = list("capsaicin" = list(8,2), "condensedcapsaicin" = list(4,4), "nutriment" = list(1,25)) - packet_icon = "seed-chilighost" - plant_icon = "chilighost" - growth_stages = 6 - - maturation = 10 - production = 10 - yield = 3 +/datum/seed/chili/ice/New() + ..() + set_trait(TRAIT_MATURATION,4) + set_trait(TRAIT_PRODUCTION,4) + set_trait(TRAIT_PRODUCT_COLOUR,"#00EDC6") // Berry plants/variants. /datum/seed/berry name = "berries" seed_name = "berry" display_name = "berry bush" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/berries) mutants = list("glowberries","poisonberries") - packet_icon = "seed-berry" - plant_icon = "berry" - harvest_repeat = 1 chems = list("nutriment" = list(1,10)) + kitchen_tag = "berries" - lifespan = 20 - maturation = 5 - production = 5 - yield = 2 - potency = 10 +/datum/seed/berry/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_JUICY,1) + set_trait(TRAIT_MATURATION,5) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,2) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"berry") + set_trait(TRAIT_PRODUCT_COLOUR,"#FA1616") + set_trait(TRAIT_PLANT_ICON,"bush") /datum/seed/berry/glow name = "glowberries" seed_name = "glowberry" display_name = "glowberry bush" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/glowberries) mutants = null - packet_icon = "seed-glowberry" - plant_icon = "glowberry" chems = list("nutriment" = list(1,10), "uranium" = list(3,5)) - lifespan = 30 - maturation = 5 - production = 5 - yield = 2 - potency = 10 +/datum/seed/berry/glow/New() + ..() + set_trait(TRAIT_SPREAD,1) + set_trait(TRAIT_BIOLUM,1) + set_trait(TRAIT_BIOLUM_COLOUR,"#006622") + set_trait(TRAIT_MATURATION,5) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,2) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_COLOUR,"c9fa16") /datum/seed/berry/poison name = "poisonberries" seed_name = "poison berry" display_name = "poison berry bush" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries) mutants = list("deathberries") - packet_icon = "seed-poisonberry" - plant_icon = "poisonberry" chems = list("nutriment" = list(1), "toxin" = list(3,5)) + kitchen_tag = "poisonberries" + +/datum/seed/berry/poison/New() + ..() + set_trait(TRAIT_PRODUCT_COLOUR,"#6DC961") /datum/seed/berry/poison/death name = "deathberries" seed_name = "death berry" display_name = "death berry bush" mutants = null - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/deathberries) - packet_icon = "seed-deathberry" - plant_icon = "deathberry" chems = list("nutriment" = list(1), "toxin" = list(3,3), "lexorin" = list(1,5)) - yield = 3 - potency = 50 +/datum/seed/berry/poison/death/New() + ..() + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_POTENCY,50) + set_trait(TRAIT_PRODUCT_COLOUR,"#7A5454") // Nettles/variants. /datum/seed/nettle name = "nettle" seed_name = "nettle" display_name = "nettles" - products = list(/obj/item/weapon/grown/nettle) mutants = list("deathnettle") - packet_icon = "seed-nettle" - plant_icon = "nettle" - harvest_repeat = 1 chems = list("nutriment" = list(1,50), "sacid" = list(0,1)) - lifespan = 30 - maturation = 6 - production = 6 - yield = 4 - potency = 10 - growth_stages = 5 + kitchen_tag = "nettle" + +/datum/seed/nettle/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_STINGS,1) + set_trait(TRAIT_PLANT_ICON,"bush5") + set_trait(TRAIT_PRODUCT_ICON,"nettles") + set_trait(TRAIT_PRODUCT_COLOUR,"#728A54") /datum/seed/nettle/death name = "deathnettle" seed_name = "death nettle" display_name = "death nettles" - products = list(/obj/item/weapon/grown/deathnettle) mutants = null - packet_icon = "seed-deathnettle" - plant_icon = "deathnettle" chems = list("nutriment" = list(1,50), "facid" = list(0,1)) + kitchen_tag = "deathnettle" - maturation = 8 - yield = 2 +/datum/seed/nettle/death/New() + ..() + set_trait(TRAIT_MATURATION,8) + set_trait(TRAIT_YIELD,2) + set_trait(TRAIT_PRODUCT_COLOUR,"#8C5030") + set_trait(TRAIT_PLANT_COLOUR,"#634941") //Tomatoes/variants. /datum/seed/tomato name = "tomato" seed_name = "tomato" display_name = "tomato plant" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/tomato) mutants = list("bluetomato","bloodtomato") - packet_icon = "seed-tomato" - plant_icon = "tomato" - harvest_repeat = 1 chems = list("nutriment" = list(1,10)) + kitchen_tag = "tomato" - lifespan = 25 - maturation = 8 - production = 6 - yield = 2 - potency = 10 +/datum/seed/tomato/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_JUICY,1) + set_trait(TRAIT_MATURATION,8) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,2) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"tomato") + set_trait(TRAIT_PRODUCT_COLOUR,"#D10000") + set_trait(TRAIT_PLANT_ICON,"bush3") /datum/seed/tomato/blood name = "bloodtomato" seed_name = "blood tomato" display_name = "blood tomato plant" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/bloodtomato) - mutants = list("killertomato") - packet_icon = "seed-bloodtomato" - plant_icon = "bloodtomato" + mutants = list("killer") chems = list("nutriment" = list(1,10), "blood" = list(1,5)) + splat_type = /obj/effect/decal/cleanable/blood/splatter + kitchen_tag = "bloodtomato" - yield = 3 +/datum/seed/tomato/blood/New() + ..() + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_PRODUCT_COLOUR,"#FF0000") /datum/seed/tomato/killer name = "killertomato" seed_name = "killer tomato" display_name = "killer tomato plant" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/killertomato) mutants = null - packet_icon = "seed-killertomato" - plant_icon = "killertomato" + can_self_harvest = 1 + has_mob_product = /mob/living/simple_animal/tomato - yield = 2 - growth_stages = 2 +/datum/seed/tomato/killer/New() + ..() + set_trait(TRAIT_YIELD,2) + set_trait(TRAIT_PRODUCT_COLOUR,"#A86747") /datum/seed/tomato/blue name = "bluetomato" seed_name = "blue tomato" display_name = "blue tomato plant" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/bluetomato) mutants = list("bluespacetomato") - packet_icon = "seed-bluetomato" - plant_icon = "bluetomato" chems = list("nutriment" = list(1,20), "lube" = list(1,5)) +/datum/seed/tomato/blue/New() + ..() + set_trait(TRAIT_PRODUCT_COLOUR,"#4D86E8") + set_trait(TRAIT_PLANT_COLOUR,"#070AAD") + /datum/seed/tomato/blue/teleport name = "bluespacetomato" seed_name = "bluespace tomato" display_name = "bluespace tomato plant" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/bluespacetomato) mutants = null - packet_icon = "seed-bluespacetomato" - plant_icon = "bluespacetomato" - chems = list("nutriment" = list(1,20), "singulo" = list(1,5)) + chems = list("nutriment" = list(1,20), "singulo" = list(10,5)) + +/datum/seed/tomato/blue/teleport/New() + ..() + set_trait(TRAIT_TELEPORTING,1) + set_trait(TRAIT_PRODUCT_COLOUR,"#00E5FF") + set_trait(TRAIT_BIOLUM,1) + set_trait(TRAIT_BIOLUM_COLOUR,"#4DA4A8") //Eggplants/varieties. /datum/seed/eggplant name = "eggplant" seed_name = "eggplant" display_name = "eggplants" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/eggplant) mutants = list("realeggplant") - packet_icon = "seed-eggplant" - plant_icon = "eggplant" - harvest_repeat = 1 chems = list("nutriment" = list(1,10)) + kitchen_tag = "eggplant" - lifespan = 25 - maturation = 6 - production = 6 - yield = 2 - potency = 20 - -/datum/seed/eggplant/eggs - name = "realeggplant" - seed_name = "egg-plant" - display_name = "egg-plants" - products = list(/obj/item/weapon/reagent_containers/food/snacks/egg) - mutants = null - packet_icon = "seed-eggy" - plant_icon = "eggy" - - lifespan = 75 - production = 12 +/datum/seed/eggplant/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,2) + set_trait(TRAIT_POTENCY,20) + set_trait(TRAIT_PRODUCT_ICON,"eggplant") + set_trait(TRAIT_PRODUCT_COLOUR,"#892694") + set_trait(TRAIT_PLANT_ICON,"bush4") //Apples/varieties. - /datum/seed/apple name = "apple" seed_name = "apple" display_name = "apple tree" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/apple) mutants = list("poisonapple","goldapple") - packet_icon = "seed-apple" - plant_icon = "apple" - harvest_repeat = 1 chems = list("nutriment" = list(1,10)) + kitchen_tag = "apple" - lifespan = 55 - maturation = 6 - production = 6 - yield = 5 - potency = 10 +/datum/seed/apple/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,5) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"apple") + set_trait(TRAIT_PRODUCT_COLOUR,"#FF540A") + set_trait(TRAIT_PLANT_ICON,"tree2") /datum/seed/apple/poison name = "poisonapple" mutants = null - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/apple/poisoned) chems = list("cyanide" = list(1,5)) /datum/seed/apple/gold name = "goldapple" seed_name = "golden apple" display_name = "gold apple tree" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/goldapple) mutants = null - packet_icon = "seed-goldapple" - plant_icon = "goldapple" chems = list("nutriment" = list(1,10), "gold" = list(1,5)) + kitchen_tag = "goldapple" - maturation = 10 - production = 10 - yield = 3 +/datum/seed/apple/gold/New() + ..() + set_trait(TRAIT_MATURATION,10) + set_trait(TRAIT_PRODUCTION,10) + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_PRODUCT_COLOUR,"#FFDD00") + set_trait(TRAIT_PLANT_COLOUR,"#D6B44D") //Ambrosia/varieties. /datum/seed/ambrosia name = "ambrosia" seed_name = "ambrosia vulgaris" display_name = "ambrosia vulgaris" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris) mutants = list("ambrosiadeus") - packet_icon = "seed-ambrosiavulgaris" - plant_icon = "ambrosiavulgaris" - harvest_repeat = 1 chems = list("nutriment" = list(1), "thc" = list(1,8), "silver_sulfadiazine" = list(1,8,1), "styptic_powder" = list(1,10,1), "toxin" = list(1,10)) + kitchen_tag = "ambrosia" - lifespan = 60 - maturation = 6 - production = 6 - yield = 6 - potency = 5 +/datum/seed/ambrosia/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,6) + set_trait(TRAIT_POTENCY,5) + set_trait(TRAIT_PRODUCT_ICON,"ambrosia") + set_trait(TRAIT_PRODUCT_COLOUR,"#9FAD55") + set_trait(TRAIT_PLANT_ICON,"ambrosia") /datum/seed/ambrosia/deus name = "ambrosiadeus" seed_name = "ambrosia deus" display_name = "ambrosia deus" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiadeus) mutants = null - packet_icon = "seed-ambrosiadeus" - plant_icon = "ambrosiadeus" chems = list("nutriment" = list(1), "styptic_powder" = list(1,8), "synaptizine" = list(1,8,1), "methamphetamine" = list(1,10,1), "thc" = list(1,10)) + kitchen_tag = "ambrosiadeus" + +//Tobacco/varieties +/datum/seed/tobacco + name = "tobacco" + seed_name = "tobacco" + display_name = "tobacco" + mutants = list("stobacco") + chems = list("nutriment" = list(1,40), "nicotine" = list(1,40)) + kitchen_tag = "tobacco" + +/datum/seed/tobacco/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,5) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,6) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"leaf") + set_trait(TRAIT_PRODUCT_COLOUR,"#9FAD55") + set_trait(TRAIT_PLANT_ICON,"bush7") + +/datum/seed/tobacco/space + name = "stobacco" + seed_name = "space tobacco" + display_name = "space tobacco" + mutants = null + chems = list("nutriment" = list(1,40), "nicotine" = list(1,20), "epinephrine" = list(1,30)) + kitchen_tag = "stobacco" + +/datum/seed/tobacco/space/New() + ..() + set_trait(TRAIT_YIELD, 4) + set_trait(TRAIT_POTENCY, 5) + set_trait(TRAIT_PRODUCT_COLOUR,"#A3F0AD") + set_trait(TRAIT_PLANT_COLOUR,"#2A9C61") + +//Tea/varieties +/datum/seed/teaaspera + name = "teaaspera" + seed_name = "tea aspera" + display_name = "tea aspera" + mutants = list("teaastra") + chems = list("teapowder" = list(1,20), "charcoal" = list(1,30)) + +/datum/seed/teaaspera/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,5) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,6) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"leaf2") + set_trait(TRAIT_PRODUCT_COLOUR,"#9FAD55") + set_trait(TRAIT_PLANT_ICON,"tree6") + +/datum/seed/teaastra + name = "teaastra" + seed_name = "tea astra" + display_name = "tea astra" + chems = list("teapowder" = list(1,20), "haloperidol" = list(1,30)) + +/datum/seed/teaastra/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,5) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,6) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"leaf2") + set_trait(TRAIT_PRODUCT_COLOUR,"#A3F0AD") + set_trait(TRAIT_PLANT_COLOUR,"#2A9C61") + set_trait(TRAIT_PLANT_ICON,"tree6") + +//Coffee/varieties +/datum/seed/coffeea + name = "coffeea" + seed_name = "coffee arabica" + display_name = "coffee arabica" + mutants = list("coffeer") + chems = list("coffeepowder" = list(1,20), "synaptizine" = list(1,40)) + kitchen_tag = "coffeea" + +/datum/seed/coffeea/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,5) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,6) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"coffee") + set_trait(TRAIT_PRODUCT_COLOUR,"#ED0000") + set_trait(TRAIT_PLANT_ICON,"bush8") + +/datum/seed/coffeer + name = "coffeer" + seed_name = "coffee robusta" + display_name = "coffee robusta" + chems = list("coffeepowder" = list(1,20), "synaptizine" = list(1,20), "methamphetamine" = list(1,40)) + kitchen_tag = "coffeer" + +/datum/seed/coffeer/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,5) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"coffee") + set_trait(TRAIT_PRODUCT_COLOUR,"#A22043") + set_trait(TRAIT_PLANT_ICON,"bush8") //Mushrooms/varieties. /datum/seed/mushroom @@ -758,824 +411,841 @@ proc/populate_seed_list() seed_name = "chanterelle" seed_noun = "spores" display_name = "chanterelle mushrooms" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/chanterelle) mutants = list("reishi","amanita","plumphelmet") - packet_icon = "mycelium-chanter" - plant_icon = "chanter" chems = list("nutriment" = list(1,25), "fungus" = list(1,10)) + splat_type = /obj/effect/plant + kitchen_tag = "mushroom" - lifespan = 35 - maturation = 7 - production = 1 - yield = 5 - potency = 1 - growth_stages = 3 +/datum/seed/mushroom/New() + ..() + set_trait(TRAIT_MATURATION,7) + set_trait(TRAIT_PRODUCTION,1) + set_trait(TRAIT_YIELD,5) + set_trait(TRAIT_POTENCY,1) + set_trait(TRAIT_PRODUCT_ICON,"mushroom4") + set_trait(TRAIT_PRODUCT_COLOUR,"#DBDA72") + set_trait(TRAIT_PLANT_COLOUR,"#D9C94E") + set_trait(TRAIT_PLANT_ICON,"mushroom") /datum/seed/mushroom/mold name = "mold" seed_name = "brown mold" display_name = "brown mold" - products = null mutants = null - //mutants = list("wallrot") //TBD. - plant_icon = "mold" - lifespan = 50 - maturation = 10 - yield = -1 +/datum/seed/mushroom/mold/New() + ..() + set_trait(TRAIT_SPREAD,1) + set_trait(TRAIT_MATURATION,10) + set_trait(TRAIT_YIELD,-1) + set_trait(TRAIT_PRODUCT_ICON,"mushroom5") + set_trait(TRAIT_PRODUCT_COLOUR,"#7A5F20") + set_trait(TRAIT_PLANT_COLOUR,"#7A5F20") + set_trait(TRAIT_PLANT_ICON,"mushroom9") /datum/seed/mushroom/plump name = "plumphelmet" seed_name = "plump helmet" display_name = "plump helmet mushrooms" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/plumphelmet) mutants = list("walkingmushroom","towercap") - packet_icon = "mycelium-plump" - plant_icon = "plump" chems = list("nutriment" = list(2,10)) + kitchen_tag = "plumphelmet" - lifespan = 25 - maturation = 8 - yield = 4 - potency = 0 +/datum/seed/mushroom/plump/New() + ..() + set_trait(TRAIT_MATURATION,8) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,0) + set_trait(TRAIT_PRODUCT_ICON,"mushroom10") + set_trait(TRAIT_PRODUCT_COLOUR,"#B57BB0") + set_trait(TRAIT_PLANT_COLOUR,"#9E4F9D") + set_trait(TRAIT_PLANT_ICON,"mushroom2") + +/datum/seed/mushroom/plump/walking + name = "walkingmushroom" + seed_name = "walking mushroom" + display_name = "walking mushrooms" + mutants = null + can_self_harvest = 1 + has_mob_product = /mob/living/simple_animal/hostile/mushroom + +/datum/seed/mushroom/plump/walking/New() + ..() + set_trait(TRAIT_MATURATION,5) + set_trait(TRAIT_YIELD,1) + set_trait(TRAIT_PRODUCT_COLOUR,"#FAC0F2") + set_trait(TRAIT_PLANT_COLOUR,"#C4B1C2") /datum/seed/mushroom/hallucinogenic name = "reishi" seed_name = "reishi" display_name = "reishi" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/reishi) mutants = list("libertycap","glowshroom") - packet_icon = "mycelium-reishi" - plant_icon = "reishi" chems = list("nutriment" = list(1,50), "psilocybin" = list(3,5)) - maturation = 10 - production = 5 - yield = 4 - potency = 15 - growth_stages = 4 +/datum/seed/mushroom/hallucinogenic/New() + ..() + set_trait(TRAIT_MATURATION,10) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,15) + set_trait(TRAIT_PRODUCT_ICON,"mushroom11") + set_trait(TRAIT_PRODUCT_COLOUR,"#FFB70F") + set_trait(TRAIT_PLANT_COLOUR,"#F58A18") + set_trait(TRAIT_PLANT_ICON,"mushroom6") /datum/seed/mushroom/hallucinogenic/strong name = "libertycap" seed_name = "liberty cap" display_name = "liberty cap mushrooms" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/libertycap) mutants = null - packet_icon = "mycelium-liberty" - plant_icon = "liberty" chems = list("nutriment" = list(1), "morphine" = list(3,3), "space_drugs" = list(1,25)) + kitchen_tag = "libertycap" - lifespan = 25 - production = 1 - potency = 15 - growth_stages = 3 +/datum/seed/mushroom/hallucinogenic/strong/New() + ..() + set_trait(TRAIT_PRODUCTION,1) + set_trait(TRAIT_POTENCY,15) + set_trait(TRAIT_PRODUCT_ICON,"mushroom8") + set_trait(TRAIT_PRODUCT_COLOUR,"#F2E550") + set_trait(TRAIT_PLANT_COLOUR,"#D1CA82") + set_trait(TRAIT_PLANT_ICON,"mushroom3") /datum/seed/mushroom/poison name = "amanita" seed_name = "fly amanita" display_name = "fly amanita mushrooms" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/amanita) mutants = list("destroyingangel","plastic") - packet_icon = "mycelium-amanita" - plant_icon = "amanita" chems = list("nutriment" = list(1), "amanitin" = list(3,3), "psilocybin" = list(1,25)) + kitchen_tag = "amanita" - lifespan = 50 - maturation = 10 - production = 5 - yield = 4 - potency = 10 +/datum/seed/mushroom/poison/New() + ..() + set_trait(TRAIT_MATURATION,10) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"mushroom") + set_trait(TRAIT_PRODUCT_COLOUR,"#FF4545") + set_trait(TRAIT_PLANT_COLOUR,"#E0DDBA") + set_trait(TRAIT_PLANT_ICON,"mushroom4") /datum/seed/mushroom/poison/death name = "destroyingangel" seed_name = "destroying angel" display_name = "destroying angel mushrooms" mutants = null - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/angel) - packet_icon = "mycelium-angel" - plant_icon = "angel" chems = list("nutriment" = list(1,50), "amanitin" = list(13,3), "psilocybin" = list(1,25)) - maturation = 12 - yield = 2 - potency = 35 +/datum/seed/mushroom/poison/death/New() + ..() + set_trait(TRAIT_MATURATION,12) + set_trait(TRAIT_YIELD,2) + set_trait(TRAIT_POTENCY,35) + set_trait(TRAIT_PRODUCT_ICON,"mushroom3") + set_trait(TRAIT_PRODUCT_COLOUR,"#EDE8EA") + set_trait(TRAIT_PLANT_COLOUR,"#E6D8DD") + set_trait(TRAIT_PLANT_ICON,"mushroom5") /datum/seed/mushroom/towercap name = "towercap" seed_name = "tower cap" display_name = "tower caps" + chems = list("woodpulp" = list(10,1)) mutants = null - products = list(/obj/item/weapon/grown/log) - packet_icon = "mycelium-tower" - plant_icon = "towercap" - lifespan = 80 - maturation = 15 +/datum/seed/mushroom/towercap/New() + ..() + set_trait(TRAIT_MATURATION,15) + set_trait(TRAIT_PRODUCT_ICON,"mushroom7") + set_trait(TRAIT_PRODUCT_COLOUR,"#79A36D") + set_trait(TRAIT_PLANT_COLOUR,"#857F41") + set_trait(TRAIT_PLANT_ICON,"mushroom8") /datum/seed/mushroom/glowshroom name = "glowshroom" seed_name = "glowshroom" display_name = "glowshrooms" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/glowshroom) mutants = null - packet_icon = "mycelium-glowshroom" - plant_icon = "glowshroom" chems = list("radium" = list(1,20)) - lifespan = 120 - maturation = 15 - yield = 3 - potency = 30 - growth_stages = 4 - biolum = 1 - biolum_colour = "#006622" - -/datum/seed/mushroom/walking - name = "walkingmushroom" - seed_name = "walking mushroom" - display_name = "walking mushrooms" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/walkingmushroom) - mutants = null - packet_icon = "mycelium-walkingmushroom" - plant_icon = "walkingmushroom" - chems = list("nutriment" = list(2,10)) - - lifespan = 30 - maturation = 5 - yield = 1 - potency = 0 - growth_stages = 3 +/datum/seed/mushroom/glowshroom/New() + ..() + set_trait(TRAIT_SPREAD,1) + set_trait(TRAIT_MATURATION,15) + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_POTENCY,30) + set_trait(TRAIT_BIOLUM,1) + set_trait(TRAIT_BIOLUM_COLOUR,"#006622") + set_trait(TRAIT_PRODUCT_ICON,"mushroom2") + set_trait(TRAIT_PRODUCT_COLOUR,"#DDFAB6") + set_trait(TRAIT_PLANT_COLOUR,"#EFFF8A") + set_trait(TRAIT_PLANT_ICON,"mushroom7") /datum/seed/mushroom/plastic name = "plastic" seed_name = "plastellium" display_name = "plastellium" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/plastellium) mutants = null - packet_icon = "mycelium-plast" - plant_icon = "plastellium" chems = list("plasticide" = list(1,10)) - lifespan = 15 - maturation = 5 - production = 6 - yield = 6 - potency = 20 +/datum/seed/mushroom/plastic/New() + ..() + set_trait(TRAIT_MATURATION,5) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,6) + set_trait(TRAIT_POTENCY,20) + set_trait(TRAIT_PRODUCT_ICON,"mushroom6") + set_trait(TRAIT_PRODUCT_COLOUR,"#E6E6E6") + set_trait(TRAIT_PLANT_COLOUR,"#E6E6E6") + set_trait(TRAIT_PLANT_ICON,"mushroom10") //Flowers/varieties /datum/seed/flower name = "harebells" seed_name = "harebell" display_name = "harebells" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/harebell) - packet_icon = "seed-harebell" - plant_icon = "harebell" chems = list("nutriment" = list(1,20)) - lifespan = 100 - maturation = 7 - production = 1 - yield = 2 - growth_stages = 4 +/datum/seed/flower/New() + ..() + set_trait(TRAIT_MATURATION,7) + set_trait(TRAIT_PRODUCTION,1) + set_trait(TRAIT_YIELD,2) + set_trait(TRAIT_PRODUCT_ICON,"flower5") + set_trait(TRAIT_PRODUCT_COLOUR,"#C492D6") + set_trait(TRAIT_PLANT_COLOUR,"#6B8C5E") + set_trait(TRAIT_PLANT_ICON,"flower") /datum/seed/flower/poppy name = "poppies" seed_name = "poppy" display_name = "poppies" - packet_icon = "seed-poppy" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/poppy) - plant_icon = "poppy" chems = list("nutriment" = list(1,20), "styptic_powder" = list(1,10)) + kitchen_tag = "poppy" - lifespan = 25 - potency = 20 - maturation = 8 - production = 6 - yield = 6 - growth_stages = 3 +/datum/seed/flower/poppy/New() + ..() + set_trait(TRAIT_POTENCY,20) + set_trait(TRAIT_MATURATION,8) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,6) + set_trait(TRAIT_PRODUCT_ICON,"flower3") + set_trait(TRAIT_PRODUCT_COLOUR,"#B33715") + set_trait(TRAIT_PLANT_ICON,"flower3") /datum/seed/flower/sunflower name = "sunflowers" seed_name = "sunflower" display_name = "sunflowers" - packet_icon = "seed-sunflower" - mutants = list("moonflower", "novaflower") - products = list(/obj/item/weapon/grown/sunflower) - plant_icon = "sunflower" - lifespan = 25 - maturation = 6 - growth_stages = 3 - -/datum/seed/flower/moonflower - name = "moonflowers" - seed_name = "moonflower" - display_name = "moonflowers" - packet_icon = "seed-moonflower" - mutants = null - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/moonflower) - plant_icon = "moonflower" - chems = list("nutriment" = list(1,50), "moonshine" = list(1,10)) - - lifespan = 25 - maturation = 6 - growth_stages = 3 - -/datum/seed/flower/novaflower - name = "novaflowers" - seed_name = "novaflower" - display_name = "novaflowers" - packet_icon = "seed-novaflower" - mutants = null - products = list(/obj/item/weapon/grown/novaflower) - plant_icon = "novaflower" - - lifespan = 25 - maturation = 6 - growth_stages = 3 +/datum/seed/flower/sunflower/New() + ..() + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCT_ICON,"flower2") + set_trait(TRAIT_PRODUCT_COLOUR,"#FFF700") + set_trait(TRAIT_PLANT_ICON,"flower2") //Grapes/varieties /datum/seed/grapes name = "grapes" seed_name = "grape" display_name = "grapevines" - packet_icon = "seed-grapes" mutants = list("greengrapes") - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/grapes) - plant_icon = "grape" - harvest_repeat = 1 chems = list("nutriment" = list(1,10), "sugar" = list(1,5)) - lifespan = 50 - maturation = 3 - production = 5 - yield = 4 - potency = 10 +/datum/seed/grapes/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,3) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"grapes") + set_trait(TRAIT_PRODUCT_COLOUR,"#BB6AC4") + set_trait(TRAIT_PLANT_COLOUR,"#378F2E") + set_trait(TRAIT_PLANT_ICON,"vine") /datum/seed/grapes/green name = "greengrapes" seed_name = "green grape" display_name = "green grapevines" - packet_icon = "seed-greengrapes" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/greengrapes) mutants = null - plant_icon = "greengrape" - chems = list("nutriment" = list(1,10)) + chems = list("nutriment" = list(1,10), "silver_sulfadiazine" = list(3,5)) -//Soybeans/varieties -/datum/seed/soybean - name = "soybean" - seed_name = "soybean" - display_name = "soybeans" - packet_icon = "seed-soybean" - mutants = list("koibean") - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/soybeans) - plant_icon = "soybean" - harvest_repeat = 1 - chems = list("nutriment" = list(1,20), "soybeanoil" = list(1,20)) - - lifespan = 25 - maturation = 4 - production = 4 - yield = 3 - potency = 5 - -/datum/seed/soybean/koi - name = "koibean" - seed_name = "koibean" - display_name = "koi beans" - packet_icon = "seed-koibean" - mutants = null - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/koibeans) - plant_icon = "soybean" - harvest_repeat = 1 - chems = list("nutriment" = list(1,30), "carpotoxin" = list(1,20)) - - lifespan = 25 - maturation = 4 - production = 4 - yield = 3 - potency = 5 - -//Tobacco/varieties -/datum/seed/tobacco - name = "tobacco" - seed_name = "tobacco" - display_name = "tobacco" - packet_icon = "seed-tobacco" - mutants = list("stobacco") - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/tobacco) - plant_icon = "tobacco" - harvest_repeat = 1 - chems = list("nutriment" = list(1,40), "nicotine" = list(1,40)) - - lifespan = 25 - maturation = 5 - production = 5 - yield = 6 - potency = 10 - growth_stages = 3 - -/datum/seed/tobacco/space - name = "stobacco" - seed_name = "space tobacco" - display_name = "space tobacco" - packet_icon = "seed-stobacco" - mutants = null - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/tobacco/space) - plant_icon = "stobacco" - harvest_repeat = 1 - chems = list("nutriment" = list(1,40), "nicotine" = list(1,20), "epinephrine" = list(1,30)) - - lifespan = 25 - maturation = 5 - production = 5 - yield = 4 - potency = 5 - growth_stages = 3 - -//Tea/varieties -/datum/seed/teaaspera - name = "teaaspera" - seed_name = "tea aspera" - display_name = "tea aspera" - packet_icon = "seed-teaaspera" - mutants = list("teaastra") - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/teaaspera) - plant_icon = "teaaspera" - harvest_repeat = 1 - chems = list("teapowder" = list(1,20), "charcoal" = list(1,30)) - - lifespan = 30 - maturation = 5 - production = 5 - yield = 6 - potency = 10 - growth_stages = 5 - -/datum/seed/teaastra - name = "teaastra" - seed_name = "tea astra" - display_name = "tea astra" - packet_icon = "seed-teaastra" - mutants = null - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/teaastra) - plant_icon = "teaastra" - harvest_repeat = 1 - chems = list("teapowder" = list(1,20), "haloperidol" = list(1,30)) - - lifespan = 30 - maturation = 5 - production = 5 - yield = 6 - potency = 10 - growth_stages = 5 - -//Coffee/varieties -/datum/seed/coffeea - name = "coffeea" - seed_name = "coffee arabica" - display_name = "coffee arabica" - packet_icon = "seed-coffeea" - mutants = list("coffeer") - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/coffeea) - plant_icon = "coffeea" - harvest_repeat = 1 - chems = list("coffeepowder" = list(1,20), "synaptizine" = list(1,40)) - - lifespan = 30 - maturation = 5 - production = 5 - yield = 6 - potency = 10 - growth_stages = 5 - -/datum/seed/coffeer - name = "coffeer" - seed_name = "coffee robusta" - display_name = "coffee robusta" - mutants = null - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/coffeer) - plant_icon = "coffeer" - harvest_repeat = 1 - chems = list("coffeepowder" = list(1,20), "synaptizine" = list(1,20), "methamphetamine" = list(1,40)) - - lifespan = 30 - maturation = 5 - production = 5 - yield = 4 - potency = 10 - growth_stages = 5 +/datum/seed/grapes/green/New() + ..() + set_trait(TRAIT_PRODUCT_COLOUR,"42ed2f") //Everything else /datum/seed/peanuts name = "peanut" seed_name = "peanut" display_name = "peanut vines" - packet_icon = "seed-peanut" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/peanut) - plant_icon = "peanut" - harvest_repeat = 1 chems = list("nutriment" = list(1,10)) - lifespan = 55 - maturation = 6 - production = 6 - yield = 6 - potency = 10 +/datum/seed/peanuts/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,6) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"potato") + set_trait(TRAIT_PRODUCT_COLOUR,"#C4AE7A") + set_trait(TRAIT_PLANT_ICON,"bush2") /datum/seed/cabbage name = "cabbage" seed_name = "cabbage" display_name = "cabbages" - packet_icon = "seed-cabbage" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/cabbage) - plant_icon = "cabbage" - harvest_repeat = 1 chems = list("nutriment" = list(1,10)) + kitchen_tag = "cabbage" - lifespan = 50 - maturation = 3 - production = 5 - yield = 4 - potency = 10 - growth_stages = 1 - -/datum/seed/shand - name = "shand" - seed_name = "S'randar's hand" - display_name = "S'randar's hand leaves" - packet_icon = "seed-shand" - products = list(/obj/item/stack/medical/bruise_pack/tajaran) - plant_icon = "shand" - chems = list("styptic_powder" = list(0,10)) - - lifespan = 50 - maturation = 3 - production = 5 - yield = 4 - potency = 10 - growth_stages = 3 - -/datum/seed/mtear - name = "mtear" - seed_name = "Messa's tear" - display_name = "Messa's tear leaves" - packet_icon = "seed-mtear" - products = list(/obj/item/stack/medical/ointment/tajaran) - plant_icon = "mtear" - chems = list("honey" = list(1,10), "silver_sulfadiazine" = list(3,5)) - - lifespan = 50 - maturation = 3 - production = 5 - yield = 4 - potency = 10 - growth_stages = 3 +/datum/seed/cabbage/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,3) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"cabbage") + set_trait(TRAIT_PRODUCT_COLOUR,"#84BD82") + set_trait(TRAIT_PLANT_COLOUR,"#6D9C6B") + set_trait(TRAIT_PLANT_ICON,"vine2") /datum/seed/banana name = "banana" seed_name = "banana" display_name = "banana tree" - packet_icon = "seed-banana" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/banana) - plant_icon = "banana" - harvest_repeat = 1 - chems = list("banana" = list(1,10)) + chems = list("banana" = list(10,10)) + trash_type = /obj/item/weapon/bananapeel + kitchen_tag = "banana" - lifespan = 50 - maturation = 6 - production = 6 - yield = 3 +/datum/seed/banana/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_PRODUCT_ICON,"bananas") + set_trait(TRAIT_PRODUCT_COLOUR,"#FFEC1F") + set_trait(TRAIT_PLANT_COLOUR,"#69AD50") + set_trait(TRAIT_PLANT_ICON,"tree4") /datum/seed/corn name = "corn" seed_name = "corn" display_name = "ears of corn" - packet_icon = "seed-corn" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/corn) - plant_icon = "corn" chems = list("nutriment" = list(1,10), "corn_starch" = list(3,5)) + kitchen_tag = "corn" + trash_type = /obj/item/weapon/corncob - lifespan = 25 - maturation = 8 - production = 6 - yield = 3 - potency = 20 - growth_stages = 3 +/datum/seed/corn/New() + ..() + set_trait(TRAIT_MATURATION,8) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_POTENCY,20) + set_trait(TRAIT_PRODUCT_ICON,"corn") + set_trait(TRAIT_PRODUCT_COLOUR,"#FFF23B") + set_trait(TRAIT_PLANT_COLOUR,"#87C969") + set_trait(TRAIT_PLANT_ICON,"corn") /datum/seed/potato name = "potato" seed_name = "potato" display_name = "potatoes" - packet_icon = "seed-potato" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/potato) - plant_icon = "potato" chems = list("nutriment" = list(1,10)) + kitchen_tag = "potato" - lifespan = 30 - maturation = 10 - production = 1 - yield = 4 - potency = 10 - growth_stages = 4 +/datum/seed/potato/New() + ..() + set_trait(TRAIT_PRODUCES_POWER,1) + set_trait(TRAIT_MATURATION,10) + set_trait(TRAIT_PRODUCTION,1) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"potato") + set_trait(TRAIT_PRODUCT_COLOUR,"#D4CAB4") + set_trait(TRAIT_PLANT_ICON,"bush2") + +/datum/seed/soybean + name = "soybean" + seed_name = "soybean" + display_name = "soybeans" + chems = list("nutriment" = list(1,20), "soybeanoil" = list(1,20)) + kitchen_tag = "soybeans" + +/datum/seed/soybean/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,4) + set_trait(TRAIT_PRODUCTION,4) + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_POTENCY,5) + set_trait(TRAIT_PRODUCT_ICON,"bean") + set_trait(TRAIT_PRODUCT_COLOUR,"#EBE7C0") + set_trait(TRAIT_PLANT_ICON,"stalk") /datum/seed/wheat name = "wheat" seed_name = "wheat" display_name = "wheat stalks" - packet_icon = "seed-wheat" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/wheat) - plant_icon = "wheat" chems = list("nutriment" = list(1,25)) + kitchen_tag = "wheat" - lifespan = 25 - maturation = 6 - production = 1 - yield = 4 - potency = 5 +/datum/seed/wheat/New() + ..() + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCTION,1) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,5) + set_trait(TRAIT_PRODUCT_ICON,"wheat") + set_trait(TRAIT_PRODUCT_COLOUR,"#DBD37D") + set_trait(TRAIT_PLANT_COLOUR,"#BFAF82") + set_trait(TRAIT_PLANT_ICON,"stalk2") /datum/seed/rice name = "rice" seed_name = "rice" display_name = "rice stalks" - packet_icon = "seed-rice" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/ricestalk) - plant_icon = "rice" chems = list("nutriment" = list(1,25)) + kitchen_tag = "rice" - lifespan = 25 - maturation = 6 - production = 1 - yield = 4 - potency = 5 - growth_stages = 4 +/datum/seed/rice/New() + ..() + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCTION,1) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,5) + set_trait(TRAIT_PRODUCT_ICON,"rice") + set_trait(TRAIT_PRODUCT_COLOUR,"#D5E6D1") + set_trait(TRAIT_PLANT_COLOUR,"#8ED17D") + set_trait(TRAIT_PLANT_ICON,"stalk2") /datum/seed/carrots name = "carrot" seed_name = "carrot" display_name = "carrots" - packet_icon = "seed-carrot" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/carrot) - plant_icon = "carrot" chems = list("nutriment" = list(1,20), "oculine" = list(3,5)) + kitchen_tag = "carrot" - lifespan = 25 - maturation = 10 - production = 1 - yield = 5 - potency = 10 - growth_stages = 3 +/datum/seed/carrots/New() + ..() + set_trait(TRAIT_MATURATION,10) + set_trait(TRAIT_PRODUCTION,1) + set_trait(TRAIT_YIELD,5) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"carrot") + set_trait(TRAIT_PRODUCT_COLOUR,"#FFDB4A") + set_trait(TRAIT_PLANT_ICON,"carrot") /datum/seed/weeds name = "weeds" seed_name = "weed" display_name = "weeds" - packet_icon = "seed-ambrosiavulgaris" - plant_icon = "weeds" - lifespan = 100 - maturation = 5 - production = 1 - yield = -1 - potency = -1 - growth_stages = 4 - immutable = -1 +/datum/seed/weeds/New() + ..() + set_trait(TRAIT_MATURATION,5) + set_trait(TRAIT_PRODUCTION,1) + set_trait(TRAIT_YIELD,-1) + set_trait(TRAIT_POTENCY,-1) + set_trait(TRAIT_IMMUTABLE,-1) + set_trait(TRAIT_PRODUCT_ICON,"flower4") + set_trait(TRAIT_PRODUCT_COLOUR,"#FCEB2B") + set_trait(TRAIT_PLANT_COLOUR,"#59945A") + set_trait(TRAIT_PLANT_ICON,"bush6") /datum/seed/whitebeets name = "whitebeet" seed_name = "white-beet" display_name = "white-beets" - packet_icon = "seed-whitebeet" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/whitebeet) - plant_icon = "whitebeet" chems = list("nutriment" = list(0,20), "sugar" = list(1,5)) + kitchen_tag = "whitebeet" - lifespan = 60 - maturation = 6 - production = 6 - yield = 6 - potency = 10 +/datum/seed/whitebeets/New() + ..() + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,6) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"carrot2") + set_trait(TRAIT_PRODUCT_COLOUR,"#EEF5B0") + set_trait(TRAIT_PLANT_COLOUR,"#4D8F53") + set_trait(TRAIT_PLANT_ICON,"carrot2") /datum/seed/sugarcane name = "sugarcane" seed_name = "sugarcane" display_name = "sugarcanes" - packet_icon = "seed-sugarcane" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/sugarcane) - plant_icon = "sugarcane" - harvest_repeat = 1 chems = list("sugar" = list(4,5)) - lifespan = 60 - maturation = 3 - production = 6 - yield = 4 - potency = 10 - growth_stages = 3 +/datum/seed/sugarcane/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,3) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"stalk") + set_trait(TRAIT_PRODUCT_COLOUR,"#B4D6BD") + set_trait(TRAIT_PLANT_COLOUR,"#6BBD68") + set_trait(TRAIT_PLANT_ICON,"stalk3") /datum/seed/watermelon name = "watermelon" seed_name = "watermelon" display_name = "watermelon vine" - packet_icon = "seed-watermelon" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/watermelon) - plant_icon = "watermelon" - harvest_repeat = 1 chems = list("nutriment" = list(1,6)) + kitchen_tag = "watermelon" - lifespan = 50 - maturation = 6 - production = 6 - yield = 3 - potency = 1 +/datum/seed/watermelon/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_JUICY,1) + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_POTENCY,1) + set_trait(TRAIT_PRODUCT_ICON,"vine") + set_trait(TRAIT_PRODUCT_COLOUR,"#326B30") + set_trait(TRAIT_PLANT_COLOUR,"#257522") + set_trait(TRAIT_PLANT_ICON,"vine2") /datum/seed/pumpkin name = "pumpkin" seed_name = "pumpkin" display_name = "pumpkin vine" - packet_icon = "seed-pumpkin" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/pumpkin) - plant_icon = "pumpkin" - harvest_repeat = 1 chems = list("nutriment" = list(1,6)) + kitchen_tag = "pumpkin" - lifespan = 50 - maturation = 6 - production = 6 - yield = 3 - potency = 10 - growth_stages = 3 +/datum/seed/pumpkin/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"vine") + set_trait(TRAIT_PRODUCT_COLOUR,"#B4D4B9") + set_trait(TRAIT_PLANT_COLOUR,"#BAE8C1") + set_trait(TRAIT_PLANT_ICON,"vine2") -/datum/seed/lime +/datum/seed/citrus name = "lime" seed_name = "lime" display_name = "lime trees" - packet_icon = "seed-lime" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/lime) - plant_icon = "lime" - harvest_repeat = 1 chems = list("nutriment" = list(1,20)) + kitchen_tag = "lime" - lifespan = 55 - maturation = 6 - production = 6 - yield = 4 - potency = 15 +/datum/seed/citrus/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_JUICY,1) + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,15) + set_trait(TRAIT_PRODUCT_ICON,"treefruit") + set_trait(TRAIT_PRODUCT_COLOUR,"#3AF026") + set_trait(TRAIT_PLANT_ICON,"tree") -/datum/seed/lemon +/datum/seed/citrus/lemon name = "lemon" seed_name = "lemon" display_name = "lemon trees" - packet_icon = "seed-lemon" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/lemon) - plant_icon = "lemon" - harvest_repeat = 1 chems = list("nutriment" = list(1,20)) + kitchen_tag = "lemon" - lifespan = 55 - maturation = 6 - production = 6 - yield = 4 - potency = 10 +/datum/seed/citrus/lemon/New() + ..() + set_trait(TRAIT_PRODUCES_POWER,1) + set_trait(TRAIT_PRODUCT_COLOUR,"#F0E226") -/datum/seed/orange +/datum/seed/citrus/orange name = "orange" seed_name = "orange" display_name = "orange trees" - packet_icon = "seed-orange" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/orange) - plant_icon = "orange" - harvest_repeat = 1 + kitchen_tag = "orange" chems = list("nutriment" = list(1,20)) - lifespan = 60 - maturation = 6 - production = 6 - yield = 5 - potency = 1 +/datum/seed/citrus/orange/New() + ..() + set_trait(TRAIT_PRODUCT_COLOUR,"#FFC20A") /datum/seed/grass name = "grass" seed_name = "grass" display_name = "grass" - packet_icon = "seed-grass" - products = list(/obj/item/stack/tile/grass) - plant_icon = "grass" - harvest_repeat = 1 + chems = list("nutriment" = list(1,20)) + kitchen_tag = "grass" - lifespan = 60 - maturation = 2 - production = 5 - yield = 5 - growth_stages = 2 +/datum/seed/grass/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,2) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,5) + set_trait(TRAIT_PRODUCT_ICON,"grass") + set_trait(TRAIT_PRODUCT_COLOUR,"#09FF00") + set_trait(TRAIT_PLANT_COLOUR,"#07D900") + set_trait(TRAIT_PLANT_ICON,"grass") /datum/seed/cocoa name = "cocoa" seed_name = "cacao" display_name = "cacao tree" - packet_icon = "seed-cocoapod" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/cocoapod) - plant_icon = "cocoapod" - harvest_repeat = 1 chems = list("nutriment" = list(1,10), "coco" = list(4,5)) - lifespan = 20 - maturation = 5 - production = 5 - yield = 2 - potency = 10 - growth_stages = 5 +/datum/seed/cocoa/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,5) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,2) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"treefruit") + set_trait(TRAIT_PRODUCT_COLOUR,"#CCA935") + set_trait(TRAIT_PLANT_ICON,"tree2") /datum/seed/cherries name = "cherry" seed_name = "cherry" seed_noun = "pits" display_name = "cherry tree" - packet_icon = "seed-cherry" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/cherries) - plant_icon = "cherry" - harvest_repeat = 1 chems = list("nutriment" = list(1,15), "sugar" = list(1,15)) + kitchen_tag = "cherries" - lifespan = 35 - maturation = 5 - production = 5 - yield = 3 - potency = 10 - growth_stages = 5 +/datum/seed/cherries/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_JUICY,1) + set_trait(TRAIT_MATURATION,5) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"cherry") + set_trait(TRAIT_PRODUCT_COLOUR,"#A80000") + set_trait(TRAIT_PLANT_ICON,"tree2") + set_trait(TRAIT_PLANT_COLOUR,"#2F7D2D") /datum/seed/kudzu name = "kudzu" seed_name = "kudzu" display_name = "kudzu vines" - packet_icon = "seed-kudzu" - products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/kudzupod) - plant_icon = "kudzu" - product_colour = "#96D278" chems = list("nutriment" = list(1,50), "charcoal" = list(1,25)) - lifespan = 20 - maturation = 6 - production = 6 - yield = 4 - potency = 10 - growth_stages = 4 - spread = 2 +/datum/seed/kudzu/New() + ..() + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_SPREAD,2) + set_trait(TRAIT_PRODUCT_ICON,"treefruit") + set_trait(TRAIT_PRODUCT_COLOUR,"#96D278") + set_trait(TRAIT_PLANT_COLOUR,"#6F7A63") + set_trait(TRAIT_PLANT_ICON,"vine2") /datum/seed/diona name = "diona" seed_name = "diona" seed_noun = "nodes" display_name = "replicant pods" - packet_icon = "seed-replicapod" - products = list(/mob/living/carbon/monkey/diona) - plant_icon = "replicapod" - product_requires_player = 1 - immutable = 1 + can_self_harvest = 1 + has_mob_product = /mob/living/carbon/monkey/diona - lifespan = 50 - endurance = 8 - maturation = 5 - production = 10 - yield = 1 - potency = 30 +/datum/seed/diona/New() + ..() + set_trait(TRAIT_IMMUTABLE,1) + set_trait(TRAIT_ENDURANCE,8) + set_trait(TRAIT_MATURATION,5) + set_trait(TRAIT_PRODUCTION,10) + set_trait(TRAIT_YIELD,1) + set_trait(TRAIT_POTENCY,30) + set_trait(TRAIT_PRODUCT_ICON,"diona") + set_trait(TRAIT_PRODUCT_COLOUR,"#799957") + set_trait(TRAIT_PLANT_COLOUR,"#66804B") + set_trait(TRAIT_PLANT_ICON,"alien4") /datum/seed/clown name = "clown" seed_name = "clown" seed_noun = "pods" display_name = "laughing clowns" - packet_icon = "seed-replicapod" - products = list(/mob/living/simple_animal/hostile/retaliate/clown) - plant_icon = "replicapod" - product_requires_player = 1 + can_self_harvest = 1 + has_mob_product = /mob/living/simple_animal/hostile/retaliate/clown - lifespan = 100 - endurance = 8 - maturation = 1 - production = 1 - yield = 10 - potency = 30 +/datum/seed/clown/New() + ..() + set_trait(TRAIT_ENDURANCE,8) + set_trait(TRAIT_MATURATION,1) + set_trait(TRAIT_PRODUCTION,1) + set_trait(TRAIT_YIELD,10) + set_trait(TRAIT_POTENCY,30) + set_trait(TRAIT_PRODUCT_ICON,"diona") + set_trait(TRAIT_PRODUCT_COLOUR,"#799957") + set_trait(TRAIT_PLANT_COLOUR,"#66804B") + set_trait(TRAIT_PLANT_ICON,"alien4") + +/datum/seed/shand + name = "shand" + seed_name = "S'randar's hand" + display_name = "S'randar's hand leaves" + chems = list("styptic_powder" = list(0,10)) + kitchen_tag = "shand" + +/datum/seed/shand/New() + ..() + set_trait(TRAIT_MATURATION,3) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"alien3") + set_trait(TRAIT_PRODUCT_COLOUR,"#378C61") + set_trait(TRAIT_PLANT_COLOUR,"#378C61") + set_trait(TRAIT_PLANT_ICON,"tree5") + +/datum/seed/mtear + name = "mtear" + seed_name = "Messa's tear" + display_name = "Messa's tear leaves" + chems = list("honey" = list(1,10), "silver_sulfadiazine" = list(3,5)) + kitchen_tag = "mtear" + +/datum/seed/mtear/New() + ..() + set_trait(TRAIT_MATURATION,3) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"alien4") + set_trait(TRAIT_PRODUCT_COLOUR,"#4CC5C7") + set_trait(TRAIT_PLANT_COLOUR,"#4CC789") + set_trait(TRAIT_PLANT_ICON,"bush7") + +/datum/seed/telriis + name = "telriis" + seed_name = "telriis" + display_name = "telriis grass" + chems = list("wine" = list(1,5), "toxin" = list(1,5), "nutriment" = list(1,6)) + +/datum/seed/telriis/New() + ..() + set_trait(TRAIT_PLANT_ICON,"telriis") + set_trait(TRAIT_ENDURANCE,50) + set_trait(TRAIT_MATURATION,5) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,5) + +/datum/seed/thaadra + name = "thaadra" + seed_name = "thaa'dra" + display_name = "thaa'dra lichen" + chems = list("frostoil" = list(1,5),"nutriment" = list(1,5)) + +/datum/seed/thaadra/New() + ..() + set_trait(TRAIT_PLANT_ICON,"thaadra") + set_trait(TRAIT_ENDURANCE,10) + set_trait(TRAIT_MATURATION,5) + set_trait(TRAIT_PRODUCTION,9) + set_trait(TRAIT_YIELD,2) + set_trait(TRAIT_POTENCY,5) + +/datum/seed/jurlmah + name = "jurlmah" + seed_name = "jurl'mah" + display_name = "jurl'mah reeds" + chems = list("serotrotium" = list(1,5),"nutriment" = list(1,5)) + +/datum/seed/jurlmah/New() + ..() + set_trait(TRAIT_PLANT_ICON,"jurlmah") + set_trait(TRAIT_ENDURANCE,12) + set_trait(TRAIT_MATURATION,8) + set_trait(TRAIT_PRODUCTION,9) + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_POTENCY,10) + +/datum/seed/amauri + name = "amauri" + seed_name = "amauri" + display_name = "amauri plant" + chems = list("condensedcapsaicin" = list(1,5),"nutriment" = list(1,5)) + +/datum/seed/amauri/New() + ..() + set_trait(TRAIT_PLANT_ICON,"amauri") + set_trait(TRAIT_ENDURANCE,10) + set_trait(TRAIT_MATURATION,8) + set_trait(TRAIT_PRODUCTION,9) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,10) + +/datum/seed/gelthi + name = "gelthi" + seed_name = "gelthi" + display_name = "gelthi plant" + chems = list("morphine" = list(1,5),"capsaicin" = list(1,5),"nutriment" = list(1,5)) + +/datum/seed/gelthi/New() + ..() + set_trait(TRAIT_PLANT_ICON,"gelthi") + set_trait(TRAIT_ENDURANCE,15) + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,2) + set_trait(TRAIT_POTENCY,1) + +/datum/seed/vale + name = "vale" + seed_name = "vale" + display_name = "vale bush" + chems = list("sal_acid" = list(1,5),"salbutamol" = list(1,2),"nutriment"= list(1,5)) + +/datum/seed/vale/New() + ..() + set_trait(TRAIT_PLANT_ICON,"vale") + set_trait(TRAIT_ENDURANCE,15) + set_trait(TRAIT_MATURATION,8) + set_trait(TRAIT_PRODUCTION,10) + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_POTENCY,3) + +/datum/seed/surik + name = "surik" + seed_name = "surik" + display_name = "surik vine" + chems = list("haloperidol" = list(1,3),"synaptizine" = list(1,2),"nutriment" = list(1,5)) + +/datum/seed/surik/New() + ..() + set_trait(TRAIT_PLANT_ICON,"surik") + set_trait(TRAIT_ENDURANCE,18) + set_trait(TRAIT_MATURATION,7) + set_trait(TRAIT_PRODUCTION,7) + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_POTENCY,3) /datum/seed/test name = "test" - seed_name = "testing" - seed_noun = "data" - display_name = "runtimes" - packet_icon = "seed-replicapod" - products = list(/mob/living/simple_animal/cat/Runtime) - plant_icon = "replicapod" + seed_name = "test" + display_name = "test trees" + chems = list("omnizine" = list(1,20)) - requires_nutrients = 0 - nutrient_consumption = 0 - requires_water = 0 - water_consumption = 0 - pest_tolerance = 11 - weed_tolerance = 11 - lifespan = 1000 - endurance = 100 - maturation = 1 - production = 1 - yield = 1 - potency = 1 \ No newline at end of file +/datum/seed/test/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_JUICY,1) + set_trait(TRAIT_MATURATION,1) + set_trait(TRAIT_PRODUCTION,1) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,15) + set_trait(TRAIT_PRODUCT_ICON,"treefruit") + set_trait(TRAIT_PRODUCT_COLOUR,"#BB6AC4") + set_trait(TRAIT_PLANT_ICON,"tree") + set_trait(TRAIT_EXPLOSIVE, 1) diff --git a/code/modules/hydroponics/seed_machines.dm b/code/modules/hydroponics/seed_machines.dm index e2416733cc3..cce982372c0 100644 --- a/code/modules/hydroponics/seed_machines.dm +++ b/code/modules/hydroponics/seed_machines.dm @@ -1,7 +1,7 @@ /obj/item/weapon/disk/botany name = "flora data disk" desc = "A small disk used for carrying data on plant genetics." - icon = 'icons/obj/hydroponics.dmi' + icon = 'icons/obj/hydroponics_machines.dmi' icon_state = "disk" w_class = 1.0 @@ -16,7 +16,7 @@ /obj/item/weapon/disk/botany/attack_self(var/mob/user as mob) if(genes.len) var/choice = alert(user, "Are you sure you want to wipe the disk?", "Xenobotany Data", "No", "Yes") - if(src && user && genes && choice == "Yes") + if(src && user && genes && choice && choice == "Yes" && user.Adjacent(get_turf(src))) user << "You wipe the disk data." name = initial(name) desc = initial(name) @@ -33,7 +33,7 @@ new /obj/item/weapon/disk/botany(src) /obj/machinery/botany - icon = 'icons/obj/hydroponics.dmi' + icon = 'icons/obj/hydroponics_machines.dmi' icon_state = "hydrotray3" density = 1 anchored = 1 @@ -44,7 +44,7 @@ var/open = 0 var/active = 0 - var/action_time = 100 + var/action_time = 5 var/last_action = 0 var/eject_disk = 0 var/failed_task = 0 @@ -58,9 +58,6 @@ if(world.time > last_action + action_time) finished_task() -/obj/machinery/botany/attack_paw(mob/user as mob) - return attack_hand(user) - /obj/machinery/botany/attack_ai(mob/user as mob) return attack_hand(user) @@ -82,13 +79,13 @@ visible_message("\icon[src] [src] beeps and spits out [loaded_disk].") loaded_disk = null -/obj/machinery/botany/attackby(obj/item/weapon/W as obj, mob/user as mob, params) +/obj/machinery/botany/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(W,/obj/item/seeds)) if(seed) user << "There is already a seed loaded." - + return var/obj/item/seeds/S =W - if(S.seed && S.seed.immutable > 0) + if(S.seed && S.seed.get_trait(TRAIT_IMMUTABLE) > 0) user << "That seed is not compatible with our genetics technology." else user.drop_item(W) @@ -99,7 +96,7 @@ if(istype(W,/obj/item/weapon/screwdriver)) open = !open - user << "\blue You [open ? "open" : "close"] the maintenance panel." + user << "You [open ? "open" : "close"] the maintenance panel." return if(open) @@ -147,8 +144,8 @@ var/list/data = list() var/list/geneMasks[0] - for(var/gene_tag in gene_tag_masks) - geneMasks.Add(list(list("tag" = gene_tag, "mask" = gene_tag_masks[gene_tag]))) + 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]))) data["geneMasks"] = geneMasks data["activity"] = active @@ -189,10 +186,10 @@ if(!seed) return seed.loc = get_turf(src) - if(seed.seed.name == "new line" || isnull(seed_types[seed.seed.name])) - seed.seed.uid = seed_types.len + 1 + if(seed.seed.name == "new line" || isnull(plant_controller.seeds[seed.seed.name])) + seed.seed.uid = plant_controller.seeds.len + 1 seed.seed.name = "[seed.seed.uid]" - seed_types[seed.seed.name] = seed.seed + plant_controller.seeds[seed.seed.name] = seed.seed seed.update_seed() visible_message("\icon[src] [src] beeps and spits out [seed].") @@ -245,8 +242,8 @@ if(!genetics.roundstart) loaded_disk.genesource += " (variety #[genetics.uid])" - loaded_disk.name += " ([gene_tag_masks[href_list["get_gene"]]], #[genetics.uid])" - loaded_disk.desc += " The label reads \'gene [gene_tag_masks[href_list["get_gene"]]], sampled from [genetics.display_name]\'." + loaded_disk.name += " ([plant_controller.gene_tag_masks[href_list["get_gene"]]], #[genetics.uid])" + loaded_disk.desc += " The label reads \'gene [plant_controller.gene_tag_masks[href_list["get_gene"]]], sampled from [genetics.display_name]\'." eject_disk = 1 degradation += rand(20,60) @@ -291,7 +288,7 @@ for(var/datum/plantgene/P in loaded_disk.genes) if(data["locus"] != "") data["locus"] += ", " - data["locus"] += "[gene_tag_masks[P.genetype]]" + data["locus"] += "[plant_controller.gene_tag_masks[P.genetype]]" else data["disk"] = 0 @@ -321,7 +318,7 @@ last_action = world.time active = 1 - if(!isnull(seed_types[seed.seed.name])) + if(!isnull(plant_controller.seeds[seed.seed.name])) seed.seed = seed.seed.diverge(1) seed.seed_type = seed.seed.name seed.update_seed() @@ -335,4 +332,4 @@ seed.modified += rand(5,10) usr.set_machine(src) - src.add_fingerprint(usr) \ No newline at end of file + src.add_fingerprint(usr) diff --git a/code/modules/hydroponics/seed_mobs.dm b/code/modules/hydroponics/seed_mobs.dm index 4bef08248bc..8b240124550 100644 --- a/code/modules/hydroponics/seed_mobs.dm +++ b/code/modules/hydroponics/seed_mobs.dm @@ -1,5 +1,4 @@ /datum/seed - var/product_requires_player // If yes, product will ask for a player among the ghosts. var/list/currently_querying // Used to avoid asking the same ghost repeatedly. // The following procs are used to grab players for mobs produced by a seed (mostly for dionaea). @@ -7,25 +6,26 @@ /* if(!host || !istype(host)) return - if(product_requires_player) - spawn(0) - request_player(host) - spawn(75) - if(!host.ckey && !host.client) - host.death() // This seems redundant, but a lot of mobs don't - host.stat = 2 // handle death() properly. Better safe than etc. - host.visible_message("\red [host] is malformed and unable to survive. It expires pitifully, leaving behind some seeds.") + spawn(0) + request_player(host) + if(istype(host,/mob/living/simple_animal)) + return + spawn(75) + if(!host.ckey && !host.client) + host.death() // This seems redundant, but a lot of mobs don't + host.stat = 2 // handle death() properly. Better safe than etc. + host.visible_message("[host] is malformed and unable to survive. It expires pitifully, leaving behind some seeds.") - var/total_yield = rand(1,3) - for(var/j = 0;j<=total_yield;j++) - var/obj/item/seeds/S = new(get_turf(host)) - S.seed_type = name - S.update_seed() + var/total_yield = rand(1,3) + for(var/j = 0;j<=total_yield;j++) + var/obj/item/seeds/S = new(get_turf(host)) + S.seed_type = name + S.update_seed() /datum/seed/proc/request_player(var/mob/living/host) if(!host) return for(var/mob/dead/observer/O in player_list) - if(jobban_isbanned(O, "Dionaea") || (!is_alien_whitelisted(src, "Diona") && config.usealienwhitelist)) + if(jobban_isbanned(O, "Dionaea")) continue if(O.client) if(O.client.prefs.be_special & BE_PLANT && !(O.client in currently_querying)) @@ -69,7 +69,7 @@ host << "\green You awaken slowly, stirring into sluggish motion as the air caresses you." // This is a hack, replace with some kind of species blurb proc. - if(istype(host,/mob/living/carbon/monkey/diona)) + if(istype(host,/mob/living/carbon/alien/diona)) host << "You are [host], one of a race of drifting interstellar plantlike creatures that sometimes share their seeds with human traders." host << "Too much darkness will send you into shock and starve you, but light will help you heal." diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seed_packets.dm similarity index 65% rename from code/modules/hydroponics/seeds.dm rename to code/modules/hydroponics/seed_packets.dm index a572b2c8d19..3a2afb74f2a 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seed_packets.dm @@ -1,8 +1,10 @@ +var/global/list/plant_seed_sprites = list() + //Seed packet object/procs. /obj/item/seeds name = "packet of seeds" icon = 'icons/obj/seeds.dmi' - icon_state = "seed" + icon_state = "blank" w_class = 2.0 var/seed_type @@ -10,26 +12,57 @@ var/modified = 0 /obj/item/seeds/New() + while(!plant_controller) + sleep(30) update_seed() ..() //Grabs the appropriate seed datum from the global list. /obj/item/seeds/proc/update_seed() - if(!seed && seed_type && !isnull(seed_types) && seed_types[seed_type]) - seed = seed_types[seed_type] + if(!seed && seed_type && !isnull(plant_controller.seeds) && plant_controller.seeds[seed_type]) + seed = plant_controller.seeds[seed_type] update_appearance() //Updates strings and icon appropriately based on seed datum. /obj/item/seeds/proc/update_appearance() if(!seed) return - icon_state = seed.packet_icon - src.name = "packet of [seed.seed_name] [seed.seed_noun]" - src.desc = "It has a picture of [seed.display_name] on the front." -/obj/item/seeds/examine() - ..() + // Update icon. + overlays.Cut() + var/is_seeds = ((seed.seed_noun in list("seeds","pits","nodes")) ? 1 : 0) + var/image/seed_mask + var/seed_base_key = "base-[is_seeds ? seed.get_trait(TRAIT_PLANT_COLOUR) : "spores"]" + if(plant_seed_sprites[seed_base_key]) + seed_mask = plant_seed_sprites[seed_base_key] + else + seed_mask = image('icons/obj/seeds.dmi',"[is_seeds ? "seed" : "spore"]-mask") + if(is_seeds) // Spore glass bits aren't coloured. + seed_mask.color = seed.get_trait(TRAIT_PLANT_COLOUR) + plant_seed_sprites[seed_base_key] = seed_mask + + var/image/seed_overlay + var/seed_overlay_key = "[seed.get_trait(TRAIT_PRODUCT_ICON)]-[seed.get_trait(TRAIT_PRODUCT_COLOUR)]" + if(plant_seed_sprites[seed_overlay_key]) + seed_overlay = plant_seed_sprites[seed_overlay_key] + else + seed_overlay = image('icons/obj/seeds.dmi',"[seed.get_trait(TRAIT_PRODUCT_ICON)]") + seed_overlay.color = seed.get_trait(TRAIT_PRODUCT_COLOUR) + plant_seed_sprites[seed_overlay_key] = seed_overlay + + overlays |= seed_mask + overlays |= seed_overlay + + if(is_seeds) + src.name = "packet of [seed.seed_name] [seed.seed_noun]" + src.desc = "It has a picture of [seed.display_name] on the front." + else + src.name = "sample of [seed.seed_name] [seed.seed_noun]" + src.desc = "It's labelled as coming from [seed.display_name]." + +/obj/item/seeds/examine(mob/user) + ..(user) if(seed && !seed.roundstart) - usr << "It's tagged as variety #[seed.uid]." + user << "It's tagged as variety #[seed.uid]." /obj/item/seeds/cutting name = "cuttings" @@ -39,12 +72,17 @@ ..() src.name = "packet of [seed.seed_name] cuttings" +/obj/item/seeds/random + seed_type = null + +/obj/item/seeds/random/New() + seed = plant_controller.create_random_seed() + seed_type = seed.name + update_seed() + /obj/item/seeds/replicapod seed_type = "diona" -/obj/item/seeds/poppyseed - seed_type = "poppies" - /obj/item/seeds/chiliseed seed_type = "chili" @@ -81,9 +119,6 @@ /obj/item/seeds/eggplantseed seed_type = "eggplant" -/obj/item/seeds/eggyseed - seed_type = "realeggplant" - /obj/item/seeds/bloodtomatoseed seed_type = "bloodtomato" @@ -114,9 +149,6 @@ /obj/item/seeds/soyaseed seed_type = "soybean" -/obj/item/seeds/koiseed - seed_type = "koibean" - /obj/item/seeds/wheatseed seed_type = "wheat" @@ -222,11 +254,38 @@ /obj/item/seeds/cherryseed seed_type = "cherry" +/obj/item/seeds/tobaccoseed + seed_type = "tobacco" + /obj/item/seeds/kudzuseed seed_type = "kudzu" -/obj/item/seeds/tobaccoseed - seed_type = "tobacco" +/obj/item/seeds/jurlmah + seed_type = "jurlmah" + +/obj/item/seeds/amauri + seed_type = "amauri" + +/obj/item/seeds/gelthi + seed_type = "gelthi" + +/obj/item/seeds/vale + seed_type = "vale" + +/obj/item/seeds/surik + seed_type = "surik" + +/obj/item/seeds/telriis + seed_type = "telriis" + +/obj/item/seeds/thaadra + seed_type = "thaadra" + +/obj/item/seeds/clown + seed_type = "clown" + +/obj/item/seeds/test + seed_type = "test" /obj/item/seeds/stobaccoseed seed_type = "stobacco" @@ -242,10 +301,3 @@ /obj/item/seeds/coffeerseed seed_type = "coffeer" - -/obj/item/seeds/moonflowerseed - seed_type = "moonflower" - -/obj/item/seeds/novaflowerseed - seed_type = "novaflower" - diff --git a/code/modules/hydroponics/seed_storage.dm b/code/modules/hydroponics/seed_storage.dm new file mode 100644 index 00000000000..e64ad1e8131 --- /dev/null +++ b/code/modules/hydroponics/seed_storage.dm @@ -0,0 +1,245 @@ +/datum/seed_pile + var/name + var/amount + var/datum/seed/seed_type // Keeps track of what our seed is + var/list/obj/item/seeds/seeds = list() // Tracks actual objects contained in the pile + var/ID + +/datum/seed_pile/New(var/obj/item/seeds/O, var/ID) + name = O.name + amount = 1 + seed_type = O.seed + seeds += O + src.ID = ID + +/datum/seed_pile/proc/matches(var/obj/item/seeds/O) + if (O.seed == seed_type) + return 1 + return 0 + +/obj/machinery/seed_storage + name = "Seed storage" + desc = "It stores, sorts, and dispenses seeds." + icon = 'icons/obj/vending.dmi' + icon_state = "seeds" + density = 1 + anchored = 1 + use_power = 1 + idle_power_usage = 100 + + var/initialized = 0 // Map-placed ones break if seeds are loaded right at the start of the round, so we do it on the first interaction + var/list/datum/seed_pile/piles = list() + var/list/starting_seeds = list() + var/list/scanner = list() // What properties we can view + +/obj/machinery/seed_storage/random // This is mostly for testing, but I guess admins could spawn it + name = "Random seed storage" + scanner = list("stats", "produce", "soil", "temperature", "light") + starting_seeds = list(/obj/item/seeds/random = 50) + +/obj/machinery/seed_storage/garden + name = "Garden seed storage" + scanner = list("stats") + starting_seeds = list(/obj/item/seeds/appleseed = 3, /obj/item/seeds/bananaseed = 3, /obj/item/seeds/berryseed = 3, /obj/item/seeds/cabbageseed = 3, /obj/item/seeds/carrotseed = 3, /obj/item/seeds/chantermycelium = 3, /obj/item/seeds/cherryseed = 3, /obj/item/seeds/chiliseed = 3, /obj/item/seeds/cocoapodseed = 3, /obj/item/seeds/cornseed = 3, /obj/item/seeds/eggplantseed = 3, /obj/item/seeds/grapeseed = 3, /obj/item/seeds/grassseed = 3, /obj/item/seeds/replicapod = 3, /obj/item/seeds/lemonseed = 3, /obj/item/seeds/limeseed = 3, /obj/item/seeds/mtearseed = 2, /obj/item/seeds/orangeseed = 3, /obj/item/seeds/peanutseed = 3, /obj/item/seeds/plumpmycelium = 3, /obj/item/seeds/poppyseed = 3, /obj/item/seeds/potatoseed = 3, /obj/item/seeds/pumpkinseed = 3, /obj/item/seeds/riceseed = 3, /obj/item/seeds/soyaseed = 3, /obj/item/seeds/sugarcaneseed = 3, /obj/item/seeds/sunflowerseed = 3, /obj/item/seeds/shandseed = 2, /obj/item/seeds/tobaccoseed = 3, /obj/item/seeds/tomatoseed = 3, /obj/item/seeds/towermycelium = 3, /obj/item/seeds/watermelonseed = 3, /obj/item/seeds/wheatseed = 3, /obj/item/seeds/whitebeetseed = 3) + +/obj/machinery/seed_storage/xenobotany + name = "Xenobotany seed storage" + scanner = list("stats", "produce", "soil", "temperature", "light") + starting_seeds = list(/obj/item/seeds/ambrosiavulgarisseed = 3, /obj/item/seeds/appleseed = 3, /obj/item/seeds/amanitamycelium = 2, /obj/item/seeds/bananaseed = 3, /obj/item/seeds/berryseed = 3, /obj/item/seeds/cabbageseed = 3, /obj/item/seeds/carrotseed = 3, /obj/item/seeds/chantermycelium = 3, /obj/item/seeds/cherryseed = 3, /obj/item/seeds/chiliseed = 3, /obj/item/seeds/cocoapodseed = 3, /obj/item/seeds/cornseed = 3, /obj/item/seeds/replicapod = 3, /obj/item/seeds/eggplantseed = 3, /obj/item/seeds/glowshroom = 2, /obj/item/seeds/grapeseed = 3, /obj/item/seeds/grassseed = 3, /obj/item/seeds/lemonseed = 3, /obj/item/seeds/libertymycelium = 2, /obj/item/seeds/limeseed = 3, /obj/item/seeds/mtearseed = 2, /obj/item/seeds/nettleseed = 2, /obj/item/seeds/orangeseed = 3, /obj/item/seeds/peanutseed = 3, /obj/item/seeds/plastiseed = 3, /obj/item/seeds/plumpmycelium = 3, /obj/item/seeds/poppyseed = 3, /obj/item/seeds/potatoseed = 3, /obj/item/seeds/pumpkinseed = 3, /obj/item/seeds/reishimycelium = 2, /obj/item/seeds/riceseed = 3, /obj/item/seeds/soyaseed = 3, /obj/item/seeds/sugarcaneseed = 3, /obj/item/seeds/sunflowerseed = 3, /obj/item/seeds/shandseed = 2, /obj/item/seeds/tobaccoseed = 3, /obj/item/seeds/tomatoseed = 3, /obj/item/seeds/towermycelium = 3, /obj/item/seeds/watermelonseed = 3, /obj/item/seeds/wheatseed = 3, /obj/item/seeds/whitebeetseed = 3) + +/obj/machinery/seed_storage/attack_hand(mob/user as mob) + user.set_machine(src) + interact(user) + +/obj/machinery/seed_storage/interact(mob/user as mob) + if (..()) + return + + if (!initialized) + for(var/typepath in starting_seeds) + var/amount = starting_seeds[typepath] + if(isnull(amount)) amount = 1 + + for (var/i = 1 to amount) + var/O = new typepath + add(O) + initialized = 1 + + var/dat = "

Seed storage contents

" + if (piles.len == 0) + dat += "No seeds" + else + dat += "" + dat += "" + if ("stats" in scanner) + dat += "" + if ("temperature" in scanner) + dat += "" + if ("light" in scanner) + dat += "" + if ("soil" in scanner) + dat += "" + dat += "" + for (var/datum/seed_pile/S in piles) + var/datum/seed/seed = S.seed_type + if(!seed) + continue + dat += "" + dat += "" + dat += "" + if ("stats" in scanner) + dat += "" + if(seed.get_trait(TRAIT_HARVEST_REPEAT)) + dat += "" + else + dat += "" + if ("temperature" in scanner) + dat += "" + if ("light" in scanner) + dat += "" + if ("soil" in scanner) + if(seed.get_trait(TRAIT_REQUIRES_NUTRIENTS)) + if(seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) < 0.05) + dat += "" + else if(seed.get_trait(TRAIT_REQUIRES_NUTRIENTS) > 0.2) + dat += "" + else + dat += "" + else + dat += "" + if(seed.get_trait(TRAIT_REQUIRES_WATER)) + if(seed.get_trait(TRAIT_WATER_CONSUMPTION) < 1) + dat += "" + else if(seed.get_trait(TRAIT_WATER_CONSUMPTION) > 5) + dat += "" + else + dat += "" + else + dat += "" + + dat += "" + dat += "" + dat += "" + dat += "" + dat += "
NameVarietyEYMPrPtHarvestTempLightNutriWaterNotesAmount
[seed.seed_name]#[seed.uid][seed.get_trait(TRAIT_ENDURANCE)][seed.get_trait(TRAIT_YIELD)][seed.get_trait(TRAIT_MATURATION)][seed.get_trait(TRAIT_PRODUCTION)][seed.get_trait(TRAIT_POTENCY)]MultipleSingle[seed.get_trait(TRAIT_IDEAL_HEAT)] K[seed.get_trait(TRAIT_IDEAL_LIGHT)] LLowHighNormNoLowHighNormNo" + switch(seed.get_trait(TRAIT_CARNIVOROUS)) + if(1) + dat += "CARN " + if(2) + dat += "CARN " + switch(seed.get_trait(TRAIT_SPREAD)) + if(1) + dat += "VINE " + if(2) + dat += "VINE " + if ("pressure" in scanner) + if(seed.get_trait(TRAIT_LOWKPA_TOLERANCE) < 20) + dat += "LP " + if(seed.get_trait(TRAIT_HIGHKPA_TOLERANCE) > 220) + dat += "HP " + if ("temperature" in scanner) + if(seed.get_trait(TRAIT_HEAT_TOLERANCE) > 30) + dat += "TEMRES " + else if(seed.get_trait(TRAIT_HEAT_TOLERANCE) < 10) + dat += "TEMSEN " + if ("light" in scanner) + if(seed.get_trait(TRAIT_LIGHT_TOLERANCE) > 10) + dat += "LIGRES " + else if(seed.get_trait(TRAIT_LIGHT_TOLERANCE) < 3) + dat += "LIGSEN " + if(seed.get_trait(TRAIT_TOXINS_TOLERANCE) < 3) + dat += "TOXSEN " + else if(seed.get_trait(TRAIT_TOXINS_TOLERANCE) > 6) + dat += "TOXRES " + if(seed.get_trait(TRAIT_PEST_TOLERANCE) < 3) + dat += "PESTSEN " + else if(seed.get_trait(TRAIT_PEST_TOLERANCE) > 6) + dat += "PESTRES " + if(seed.get_trait(TRAIT_WEED_TOLERANCE) < 3) + dat += "WEEDSEN " + else if(seed.get_trait(TRAIT_WEED_TOLERANCE) > 6) + dat += "WEEDRES " + if(seed.get_trait(TRAIT_PARASITE)) + dat += "PAR " + if ("temperature" in scanner) + if(seed.get_trait(TRAIT_ALTER_TEMP) > 0) + dat += "TEMP+ " + if(seed.get_trait(TRAIT_ALTER_TEMP) < 0) + dat += "TEMP- " + if(seed.get_trait(TRAIT_BIOLUM)) + dat += "LUM " + dat += "[S.amount]Vend Purge
" + + user << browse(dat, "window=seedstorage") + onclose(user, "seedstorage") + +/obj/machinery/seed_storage/Topic(var/href, var/list/href_list) + if (..()) + return + var/task = href_list["task"] + var/ID = text2num(href_list["id"]) + + for (var/datum/seed_pile/N in piles) + if (N.ID == ID) + if (task == "vend") + var/obj/O = pick(N.seeds) + if (O) + --N.amount + N.seeds -= O + if (N.amount <= 0 || N.seeds.len <= 0) + piles -= N + del(N) + O.loc = src.loc + else + piles -= N + del(N) + else if (task == "purge") + for (var/obj/O in N.seeds) + del(O) + piles -= N + del(N) + break + updateUsrDialog() + +/obj/machinery/seed_storage/attackby(var/obj/item/O as obj, var/mob/user as mob) + if (istype(O, /obj/item/seeds)) + add(O) + user.visible_message("[user] puts \the [O.name] into \the [src].", "You put \the [O] into \the [src].") + return + else if (istype(O, /obj/item/weapon/storage/bag/plants)) + var/obj/item/weapon/storage/P = O + var/loaded = 0 + for(var/obj/item/seeds/G in P.contents) + ++loaded + add(G) + if (loaded) + user.visible_message("[user] puts the seeds from \the [O.name] into \the [src].", "You put the seeds from \the [O.name] into \the [src].") + else + user << "There are no seeds in \the [O.name]." + return + else if(istype(O, /obj/item/weapon/wrench)) + playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) + anchored = !anchored + user << "You [anchored ? "wrench" : "unwrench"] \the [src]." + +/obj/machinery/seed_storage/proc/add(var/obj/item/seeds/O as obj) + if (istype(O.loc, /mob)) + var/mob/user = O.loc + user.drop_item(O) + else if(istype(O.loc,/obj/item/weapon/storage)) + var/obj/item/weapon/storage/S = O.loc + S.remove_from_storage(O, src) + + O.loc = src + var/newID = 0 + + for (var/datum/seed_pile/N in piles) + if (N.matches(O)) + ++N.amount + N.seeds += (O) + return + else if(N.ID >= newID) + newID = N.ID + 1 + + piles += new /datum/seed_pile(O, newID) + return diff --git a/code/modules/hydroponics/spreading/spreading.dm b/code/modules/hydroponics/spreading/spreading.dm new file mode 100644 index 00000000000..d4bd00c9c05 --- /dev/null +++ b/code/modules/hydroponics/spreading/spreading.dm @@ -0,0 +1,262 @@ +#define DEFAULT_SEED "glowshroom" +#define VINE_GROWTH_STAGES 5 + +/proc/spacevine_infestation() + spawn() //to stop the secrets panel hanging + var/list/turf/simulated/floor/turfs = list() //list of all the empty floor turfs in the hallway areas + for(var/areapath in typesof(/area/hallway)) + var/area/A = locate(areapath) + for(var/area/B in A.related) + for(var/turf/simulated/floor/F in B.contents) + if(!F.contents.len) + turfs += F + + if(turfs.len) //Pick a turf to spawn at if we can + var/turf/simulated/floor/T = pick(turfs) + var/datum/seed/seed = plant_controller.create_random_seed(1) + seed.set_trait(TRAIT_SPREAD,2) // So it will function properly as vines. + seed.set_trait(TRAIT_POTENCY,rand(70,100)) // Guarantee a wide spread and powerful effects. + new /obj/effect/plant(T,seed) + message_admins("Event: Spacevines spawned at [T.loc] ([T.x],[T.y],[T.z])") + +/obj/effect/dead_plant + anchored = 1 + opacity = 0 + density = 0 + color = DEAD_PLANT_COLOUR + +/obj/effect/dead_plant/attack_hand() + del(src) + +/obj/effect/dead_plant/attackby() + ..() + for(var/obj/effect/plant/neighbor in range(1)) + neighbor.update_neighbors() + del(src) + +/obj/effect/plant + name = "plant" + anchored = 1 + opacity = 0 + density = 0 + icon = 'icons/obj/hydroponics_growing.dmi' + icon_state = "bush4-1" + layer = 3 + pass_flags = PASSTABLE + + var/health = 10 + var/max_health = 100 + var/growth_threshold = 0 + var/growth_type = 0 + var/max_growth = 0 + + var/list/neighbors = list() + var/obj/effect/plant/parent + var/datum/seed/seed + var/floor = 0 + var/spread_chance = 40 + var/spread_distance = 3 + var/evolve_chance = 2 + var/last_tick = 0 + var/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/plant + + var/mob/living/buckled_mob = null + var/movable = 0 + +/obj/effect/plant/Del() + if(plant_controller) + plant_controller.remove_plant(src) + for(var/obj/effect/plant/neighbor in range(1,src)) + plant_controller.add_plant(neighbor) + ..() +/obj/effect/plant/single + spread_chance = 0 + +/obj/effect/plant/New(var/newloc, var/datum/seed/newseed, var/obj/effect/plant/newparent) + ..() + + if(!newparent) + parent = src + else + parent = newparent + + if(!plant_controller) + sleep(250) // ugly hack, should mean roundstart plants are fine. + if(!plant_controller) + world << "Plant controller does not exist and [src] requires it. Aborting." + del(src) + return + + if(!istype(newseed)) + newseed = plant_controller.seeds[DEFAULT_SEED] + seed = newseed + if(!seed) + del(src) + return + + name = seed.display_name + max_health = round(seed.get_trait(TRAIT_ENDURANCE)/2) + if(seed.get_trait(TRAIT_SPREAD)==2) + max_growth = VINE_GROWTH_STAGES + growth_threshold = max_health/VINE_GROWTH_STAGES + icon = 'icons/obj/hydroponics_vines.dmi' + growth_type = 2 // Vines by default. + if(seed.get_trait(TRAIT_CARNIVOROUS) == 2) + growth_type = 1 // WOOOORMS. + else if(!(seed.seed_noun in list("seeds","pits"))) + if(seed.seed_noun == "nodes") + growth_type = 3 // Biomass + else + growth_type = 4 // Mold + else + max_growth = seed.growth_stages + growth_threshold = max_health/seed.growth_stages + + if(max_growth > 2 && prob(50)) + max_growth-- //Ensure some variation in final sprite, makes the carpet of crap look less wonky. + + spread_chance = seed.get_trait(TRAIT_POTENCY) * 4 + spread_distance = ((growth_type>0) ? round(spread_chance*0.6) : round(spread_chance*0.3)) + update_icon() + + spawn(1) // Plants will sometimes be spawned in the turf adjacent to the one they need to end up in, for the sake of correct dir/etc being set. + set_dir(calc_dir()) + update_icon() + plant_controller.add_plant(src) + // Some plants eat through plating. + if(!isnull(seed.chems["facid"])) + var/turf/T = get_turf(src) + T.ex_act(prob(80) ? 3 : 2) + +/obj/effect/plant/update_icon() + //TODO: should really be caching this. + refresh_icon() + if(growth_type == 0 && !floor) + src.transform = null + var/matrix/M = matrix() + // should make the plant flush against the wall it's meant to be growing from. + M.Translate(0,-(rand(12,14))) + switch(dir) + if(WEST) + M.Turn(90) + if(NORTH) + M.Turn(180) + if(EAST) + M.Turn(270) + src.transform = M + var/icon_colour = seed.get_trait(TRAIT_PLANT_COLOUR) + if(icon_colour) + color = icon_colour + // Apply colour and light from seed datum. + if(seed.get_trait(TRAIT_BIOLUM)) + SetLuminosity(1+round(seed.get_trait(TRAIT_POTENCY)/20)) + if(seed.get_trait(TRAIT_BIOLUM_COLOUR)) + l_color = seed.get_trait(TRAIT_BIOLUM_COLOUR) + else + l_color = null + return + else + SetLuminosity(0) + +/obj/effect/plant/proc/refresh_icon() + var/growth = min(max_growth,round(health/growth_threshold)) + var/at_fringe = get_dist(src,parent) + if(spread_distance > 5) + if(at_fringe >= (spread_distance-3)) + max_growth-- + if(at_fringe >= (spread_distance-2)) + max_growth-- + max_growth = max(1,max_growth) + if(growth_type > 0) + switch(growth_type) + if(1) + icon_state = "worms" + if(2) + icon_state = "vines-[growth]" + if(3) + icon_state = "mass-[growth]" + if(4) + icon_state = "mold-[growth]" + else + icon_state = "[seed.get_trait(TRAIT_PLANT_ICON)]-[growth]" + + if(growth>2 && growth == max_growth) + layer = 5 + opacity = 1 + if(!isnull(seed.chems["woodpulp"])) + density = 1 + else + layer = 3 + density = 0 + +/obj/effect/plant/proc/calc_dir(turf/location = loc) + set background = 1 + var/direction = 16 + + for(var/wallDir in cardinal) + var/turf/newTurf = get_step(location,wallDir) + if(newTurf.density) + direction |= wallDir + + for(var/obj/effect/plant/shroom in location) + if(shroom == src) + continue + if(shroom.floor) //special + direction &= ~16 + else + direction &= ~shroom.dir + + var/list/dirList = list() + + for(var/i=1,i<=16,i <<= 1) + if(direction & i) + dirList += i + + if(dirList.len) + var/newDir = pick(dirList) + if(newDir == 16) + floor = 1 + newDir = 1 + return newDir + + floor = 1 + return 1 + +/obj/effect/plant/attackby(var/obj/item/weapon/W, var/mob/user) + + plant_controller.add_plant(src) + + if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/scalpel)) + if(!seed) + user << "There is nothing to take a sample from." + return + seed.harvest(user,0,1) + health -= (rand(3,5)*10) + else + ..() + if(W.force) + health -= W.force + check_health() + +/obj/effect/plant/ex_act(severity) + switch(severity) + if(1.0) + die_off() + return + if(2.0) + if (prob(50)) + die_off() + return + if(3.0) + if (prob(5)) + die_off() + return + else + return + +/obj/effect/plant/proc/check_health() + if(health <= 0) + die_off() + +/obj/effect/plant/proc/is_mature() + return (health >= (max_health/3)) \ No newline at end of file diff --git a/code/modules/hydroponics/spreading/spreading_growth.dm b/code/modules/hydroponics/spreading/spreading_growth.dm new file mode 100644 index 00000000000..cdd06639a1c --- /dev/null +++ b/code/modules/hydroponics/spreading/spreading_growth.dm @@ -0,0 +1,106 @@ +#define NEIGHBOR_REFRESH_TIME 100 + +/obj/effect/plant/proc/get_cardinal_neighbors() + var/list/cardinal_neighbors = list() + for(var/check_dir in cardinal) + var/turf/simulated/T = get_step(get_turf(src), check_dir) + if(istype(T)) + cardinal_neighbors |= T + return cardinal_neighbors + +/obj/effect/plant/proc/update_neighbors() + // Update our list of valid neighboring turfs. + neighbors = list() + for(var/turf/simulated/floor in get_cardinal_neighbors()) + if(get_dist(parent, floor) > spread_distance) + continue + if((locate(/obj/effect/plant) in floor.contents) || (locate(/obj/effect/dead_plant) in floor.contents) ) + continue + if(floor.density) + if(!isnull(seed.chems["pacid"])) + spawn(rand(5,25)) floor.ex_act(3) + continue + if(!Adjacent(floor) || !floor.Enter(src)) + continue + neighbors |= floor + // Update all of our friends. + var/turf/T = get_turf(src) + for(var/obj/effect/plant/neighbor in range(1,src)) + neighbor.neighbors -= T + +/obj/effect/plant/process() + + // Something is very wrong, kill ourselves. + if(!seed) + die_off() + return 0 + + /* MOVED INTO code\game\objects\effects\effect_system.dm + for(var/obj/effect/effect/smoke/chem/smoke in view(1, src)) + if(smoke.reagents.has_reagent("plantbgone")) + die_off() + return + */ + + // Handle life. + var/turf/simulated/T = get_turf(src) + if(istype(T)) + health -= seed.handle_environment(T,T.return_air(),null,1) + if(health < max_health) + health += rand(3,5) + refresh_icon() + if(health > max_health) + health = max_health + else if(health == max_health && !plant) + plant = new(T,seed) + plant.dir = src.dir + plant.transform = src.transform + plant.age = seed.get_trait(TRAIT_MATURATION)-1 + plant.update_icon() + if(growth_type==0) //Vines do not become invisible. + invisibility = INVISIBILITY_MAXIMUM + else + plant.layer = layer + 0.1 + + if(buckled_mob) + seed.do_sting(buckled_mob,src) + if(seed.get_trait(TRAIT_CARNIVOROUS)) + seed.do_thorns(buckled_mob,src) + + if(world.time >= last_tick+NEIGHBOR_REFRESH_TIME) + last_tick = world.time + update_neighbors() + + if(is_mature() && neighbors.len && prob(spread_chance)) + for(var/i=1,i<=seed.get_trait(TRAIT_YIELD),i++) + if(prob(spread_chance)) + sleep(rand(3,5)) + if(!neighbors.len) + break + var/turf/target_turf = pick(neighbors) + var/obj/effect/plant/child = new(get_turf(src),seed,parent) + spawn(1) // This should do a little bit of animation. + child.loc = target_turf + child.update_icon() + // Update neighboring squares. + for(var/obj/effect/plant/neighbor in range(1,target_turf)) + neighbor.neighbors -= target_turf + + // We shouldn't have spawned if the controller doesn't exist. + check_health() + if(neighbors.len || health != max_health) + plant_controller.add_plant(src) + +/obj/effect/plant/proc/die_off() + // Kill off our plant. + if(plant) plant.die() + // This turf is clear now, let our buddies know. + for(var/turf/simulated/check_turf in get_cardinal_neighbors()) + if(!istype(check_turf)) + continue + for(var/obj/effect/plant/neighbor in check_turf.contents) + neighbor.neighbors |= check_turf + plant_controller.add_plant(neighbor) + spawn(1) if(src) del(src) + +#undef NEIGHBOR_REFRESH_TIME \ No newline at end of file diff --git a/code/modules/hydroponics/spreading/spreading_response.dm b/code/modules/hydroponics/spreading/spreading_response.dm new file mode 100644 index 00000000000..d175fdda221 --- /dev/null +++ b/code/modules/hydroponics/spreading/spreading_response.dm @@ -0,0 +1,78 @@ +/obj/effect/plant/HasProximity(var/atom/movable/AM) + + if(!is_mature() || seed.get_trait(TRAIT_SPREAD) != 2) + return + + var/mob/living/M = AM + if(!istype(M)) + return + + if(!buckled_mob && !M.buckled && !M.anchored && (M.small || prob(round(seed.get_trait(TRAIT_POTENCY)/2)))) + entangle(M) + +/obj/effect/plant/attack_hand(mob/user as mob) + // Todo, cause damage. + manual_unbuckle(user) + +/obj/effect/plant/proc/trodden_on(var/mob/living/victim) + if(!is_mature()) + return + var/mob/living/carbon/human/H = victim + if(istype(H) && H.shoes) + return + seed.do_thorns(victim,src) + seed.do_sting(victim,src,pick("r_foot","l_foot","r_leg","l_leg")) + +/obj/effect/plant/proc/unbuckle() + if(buckled_mob) + if(buckled_mob.buckled == src) + buckled_mob.buckled = null + buckled_mob.anchored = initial(buckled_mob.anchored) + buckled_mob.update_canmove() + buckled_mob = null + return + +/obj/effect/plant/proc/manual_unbuckle(mob/user as mob) + if(buckled_mob) + if(prob(seed ? min(max(0,100 - seed.get_trait(TRAIT_POTENCY)/2),100) : 50)) + if(buckled_mob.buckled == src) + if(buckled_mob != user) + buckled_mob.visible_message(\ + "[user.name] frees [buckled_mob.name] from \the [src].",\ + "[user.name] frees you from \the [src].",\ + "You hear shredding and ripping.") + else + buckled_mob.visible_message(\ + "[buckled_mob.name] struggles free of \the [src].",\ + "You untangle \the [src] from around yourself.",\ + "You hear shredding and ripping.") + unbuckle() + else + var/text = pick("rip","tear","pull") + user.visible_message(\ + "[user.name] [text]s at \the [src].",\ + "You [text] at \the [src].",\ + "You hear shredding and ripping.") + return + +/obj/effect/plant/proc/entangle(var/mob/living/victim) + + if(buckled_mob) + return + + if(!Adjacent(victim)) + return + + victim.buckled = src + victim.update_canmove() + buckled_mob = victim + if(!victim.anchored && !victim.buckled && victim.loc != get_turf(src)) + var/can_grab = 1 + if(istype(victim, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = victim + if(istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags & NOSLIP)) + can_grab = 0 + if(can_grab) + src.visible_message("Tendrils lash out from \the [src] and drag \the [victim] in!") + victim.loc = src.loc + victim << "Tendrils [pick("wind", "tangle", "tighten")] around you!" diff --git a/code/game/machinery/hydroponics.dm b/code/modules/hydroponics/trays/tray.dm similarity index 53% rename from code/game/machinery/hydroponics.dm rename to code/modules/hydroponics/trays/tray.dm index c58cd06fae9..d09a4674294 100644 --- a/code/game/machinery/hydroponics.dm +++ b/code/modules/hydroponics/trays/tray.dm @@ -1,14 +1,14 @@ -#define HYDRO_SPEED_MULTIPLIER 1 - /obj/machinery/portable_atmospherics/hydroponics name = "hydroponics tray" - icon = 'icons/obj/hydroponics.dmi' + icon = 'icons/obj/hydroponics_machines.dmi' icon_state = "hydrotray3" density = 1 anchored = 1 flags = OPENCONTAINER + volume = 100 - var/draw_warnings = 1 //Set to 0 to stop it from drawing the alert lights. + var/mechanical = 1 // Set to 0 to stop it from drawing the alert lights. + var/base_name = "tray" // Plant maintenance vars. var/waterlevel = 100 // Water level (max 100) @@ -16,17 +16,19 @@ var/nutrilevel = 10 // Nutrient level (max 10) var/maxnutri = 10 var/pestlevel = 0 // Pests (max 10) - var/weedlevel = 0 // Weeds (max 10)s + var/weedlevel = 0 // Weeds (max 10) // Tray state vars. var/dead = 0 // Is it dead? var/harvest = 0 // Is it ready to harvest? var/age = 0 // Current plant age + var/sampled = 0 // Have we taken a sample? // Harvest/mutation mods. var/yield_mod = 0 // Modifier to yield var/mutation_mod = 0 // Modifier to mutation chance var/toxins = 0 // Toxicity in the tray? + var/tray_light = 1 // Supplied lighting. // Mechanical concerns. var/health = 0 // Plant health. @@ -35,6 +37,8 @@ var/cycledelay = 150 // Delay per cycle. var/closed_system // If set, the tray will attempt to take atmos from a pipe. var/force_update // Set this to bypass the cycle time check. + var/obj/temp_chem_holder // Something to hold reagents during process_reagents() + var/labelled // Seed details/line data. var/datum/seed/seed = null // The currently planted seed @@ -46,12 +50,12 @@ // with cycle information under 'mechanical concerns' at some point. var/global/list/toxic_reagents = list( "charcoal" = -2, - "toxin" = 2, + "toxin" = 2, "fluorine" = 2.5, "chlorine" = 1.5, "sacid" = 1.5, "facid" = 3, - "atrazine" = 3, + "atrazine" = 3, "cryoxadone" = -3, "radium" = 2 ) @@ -76,7 +80,7 @@ "sugar" = 2, "sacid" = -2, "facid" = -4, - "atrazine" = -8, + "atrazine" = -8, "adminordrazine" = -5 ) var/global/list/pestkiller_reagents = list( @@ -89,7 +93,7 @@ "adminordrazine" = 1, "milk" = 0.9, "beer" = 0.7, - "flourine" = -0.5, + "fluorine" = -0.5, "chlorine" = -0.5, "phosphorus" = -0.5, "water" = 1, @@ -98,22 +102,23 @@ // Beneficial reagents also have values for modifying yield_mod and mut_mod (in that order). var/global/list/beneficial_reagents = list( - "beer" = list( -0.05, 0, 0 ), - "fluorine" = list( -2, 0, 0 ), - "chlorine" = list( -1, 0, 0 ), - "phosphorus" = list( -0.75, 0, 0 ), - "sodawater" = list( 0.1, 0, 0 ), - "sacid" = list( -1, 0, 0 ), - "facid" = list( -2, 0, 0 ), - "atrazine" = list( -2, 0, 0.2 ), - "cryoxadone" = list( 3, 0, 0 ), - "ammonia" = list( 0.5, 0, 0 ), - "diethylamine" = list( 1, 0, 0 ), - "nutriment" = list( 0.25, 0.15, 0 ), - "radium" = list( -1.5, 0, 0.2 ), - "adminordrazine" = list( 1, 1, 1 ), - "robustharvest" = list( 0, 0.2, 0 ), - "left4zed" = list( 0, 0, 0.2 ) + // "reagent" = list(health, yield_Mod, mut_mod), + "beer" = list( -0.05, 0, 0 ), + "fluorine" = list( -2, 0, 0 ), + "chlorine" = list( -1, 0, 0 ), + "phosphorus" = list( -0.75, 0, 0 ), + "sodawater" = list( 0.1, 0, 0 ), + "sacid" = list( -1, 0, 0 ), + "facid" = list( -2, 0, 0 ), + "atrazine" = list( -2, 0, 0.2), + "cryoxadone" = list( 3, 0, 0 ), + "ammonia" = list( 0.5, 0, 0 ), + "diethylamine" = list( 1, 0, 0 ), + "nutriment" = list( 0.25, 0.15, 0 ), + "radium" = list( -1.5, 0, 0.2), + "adminordrazine" = list( 1, 1, 1 ), + "robustharvest" = list( 0, 0.2, 0 ), + "left4zed" = list( 0, 0, 0.2) ) //--FalseIncarnate @@ -126,6 +131,31 @@ ) //--FalseIncarnate +/obj/machinery/portable_atmospherics/hydroponics/AltClick() + if(mechanical && !usr.stat && !usr.lying && Adjacent(usr)) + close_lid(usr) + return + return ..() + +/obj/machinery/portable_atmospherics/hydroponics/proc/attack_generic(var/mob/user) + if(istype(user,/mob/living/carbon/monkey/diona)) + var/mob/living/carbon/monkey/diona/nymph = user + + if(nymph.stat == DEAD || nymph.paralysis || nymph.weakened || nymph.stunned || nymph.restrained()) + return + + if(weedlevel > 0) + nymph.reagents.add_reagent("nutriment", weedlevel) + weedlevel = 0 + nymph.visible_message("[nymph] begins rooting through [src], ripping out weeds and eating them noisily.","You begin rooting through [src], ripping out weeds and eating them noisily.") + else if(nymph.nutrition > 100 && nutrilevel < 10) + nymph.nutrition -= ((10-nutrilevel)*5) + nutrilevel = 10 + nymph.visible_message("[nymph] secretes a trickle of green liquid, refilling [src].","You secrete a trickle of green liquid, refilling [src].") + else + nymph.visible_message("[nymph] rolls around in [src] for a bit.","You roll around in [src] for a bit.") + return + /obj/machinery/portable_atmospherics/hydroponics/New() ..() @@ -136,6 +166,9 @@ component_parts += new /obj/item/weapon/stock_parts/console_screen(src) RefreshParts() + temp_chem_holder = new() + temp_chem_holder.create_reagents(10) + create_reagents(200) connect() update_icon() @@ -163,7 +196,7 @@ /obj/machinery/portable_atmospherics/hydroponics/bullet_act(var/obj/item/projectile/Proj) //Don't act on seeds like dionaea that shouldn't change. - if(seed && seed.immutable > 0) + if(seed && seed.get_trait(TRAIT_IMMUTABLE) > 0) return //--FalseIncarnate @@ -186,162 +219,17 @@ else return 0 -/obj/machinery/portable_atmospherics/hydroponics/process() - - //Do this even if we're not ready for a plant cycle. - process_reagents() - - // Update values every cycle rather than every process() tick. - if(force_update) - force_update = 0 - else if(world.time < (lastcycle + cycledelay)) - return - lastcycle = world.time - - // Weeds like water and nutrients, there's a chance the weed population will increase. - // Bonus chance if the tray is unoccupied. - if(waterlevel > 10 && nutrilevel > 2 && prob(isnull(seed) ? 6 : 3)) - weedlevel += 1 * HYDRO_SPEED_MULTIPLIER - - // There's a chance for a weed explosion to happen if the weeds take over. - // Plants that are themselves weeds (weed_tolernace > 10) are unaffected. - if (weedlevel >= 10 && prob(10)) - if(!seed || weedlevel >= seed.weed_tolerance) - weed_invasion() - - // If there is no seed data (and hence nothing planted), - // or the plant is dead, process nothing further. - if(!seed || dead) - return - - // Advance plant age. - if(prob(25)) age += 1 * HYDRO_SPEED_MULTIPLIER - - //Highly mutable plants have a chance of mutating every tick. - if(seed.immutable == -1) - var/mut_prob = rand(1,100) - if(mut_prob <= 5) mutate(mut_prob == 1 ? 2 : 1) - - // Maintain tray nutrient and water levels. - if(seed.nutrient_consumption > 0 && nutrilevel > 0 && prob(25)) - nutrilevel -= max(0,seed.nutrient_consumption * HYDRO_SPEED_MULTIPLIER) - if(seed.water_consumption > 0 && waterlevel > 0 && prob(25)) - waterlevel -= max(0,seed.water_consumption * HYDRO_SPEED_MULTIPLIER) - - // Make sure the plant is not starving or thirsty. Adequate - // water and nutrients will cause a plant to become healthier. - var/healthmod = rand(1,3) * HYDRO_SPEED_MULTIPLIER - if(seed.requires_nutrients && prob(35)) - health += (nutrilevel < 2 ? -healthmod : healthmod) - if(seed.requires_water && prob(35)) - health += (waterlevel < 10 ? -healthmod : healthmod) - - // Check that pressure, heat and light are all within bounds. - // First, handle an open system or an unconnected closed system. - - var/turf/T = loc - var/datum/gas_mixture/environment - - // If we're closed, take from our internal sources. - if(closed_system && (connected_port || holding)) - environment = air_contents - - // If atmos input is not there, grab from turf. - if(!environment) - if(istype(T)) - environment = T.return_air() - - if(!environment) return - -/* - // Handle gas consumption. - if(seed.consume_gasses && seed.consume_gasses.len) - var/missing_gas = 0 - for(var/gas in seed.consume_gasses) - if(environment && environment.gas && environment.gas[gas] && \ - environment.gas[gas] >= seed.consume_gasses[gas]) - environment.adjust_gas(gas,-seed.consume_gasses[gas],1) - else - missing_gas++ - - if(missing_gas > 0) - health -= missing_gas * HYDRO_SPEED_MULTIPLIER - - // Process it. - var/pressure = environment.return_pressure() - if(pressure < seed.lowkpa_tolerance || pressure > seed.highkpa_tolerance) - health -= healthmod - - if(abs(environment.temperature - seed.ideal_heat) > seed.heat_tolerance) - health -= healthmod - - // Handle gas production. - if(seed.exude_gasses && seed.exude_gasses.len) - for(var/gas in seed.exude_gasses) - environment.adjust_gas(gas, max(1,round((seed.exude_gasses[gas]*seed.potency)/seed.exude_gasses.len))) - -*/ - - // Handle light requirements. - var/atom/movable/lighting_overlay/L = locate(/atom/movable/lighting_overlay) in T - if(L) - var/light_available - if(L) - light_available = max(0,min(10,L.lum_r + L.lum_g + L.lum_b)-5) - else - light_available = 5 - if(abs(light_available - seed.ideal_light) > seed.light_tolerance) - health -= healthmod - - // Toxin levels beyond the plant's tolerance cause damage, but - // toxins are sucked up each tick and slowly reduce over time. - if(toxins > 0) - var/toxin_uptake = max(1,round(toxins/10)) - if(toxins > seed.toxins_tolerance) - health -= toxin_uptake - toxins -= toxin_uptake - - // Check for pests and weeds. - // Some carnivorous plants happily eat pests. - if(pestlevel > 0) - if(seed.carnivorous) - health += HYDRO_SPEED_MULTIPLIER - pestlevel -= HYDRO_SPEED_MULTIPLIER - else if (pestlevel >= seed.pest_tolerance) - health -= HYDRO_SPEED_MULTIPLIER - - // Some plants thrive and live off of weeds. - if(weedlevel > 0) - if(seed.parasite) - health += HYDRO_SPEED_MULTIPLIER - weedlevel -= HYDRO_SPEED_MULTIPLIER - else if (weedlevel >= seed.weed_tolerance) - health -= HYDRO_SPEED_MULTIPLIER - - // Handle life and death. - // If the plant is too old, it loses health fast. - if(age > seed.lifespan) - health -= rand(3,5) * HYDRO_SPEED_MULTIPLIER - - // When the plant dies, weeds thrive and pests die off. - if(health <= 0) - dead = 1 - harvest = 0 - weedlevel += 1 * HYDRO_SPEED_MULTIPLIER - pestlevel = 0 - - // If enough time (in cycles, not ticks) has passed since the plant was harvested, we're ready to harvest again. - else if(seed.products && seed.products.len && age > seed.production && \ - (age - lastproduce) > seed.production && (!harvest && !dead)) - harvest = 1 - lastproduce = age - - if(prob(3)) // On each tick, there's a chance the pest population will increase - pestlevel += 1 * HYDRO_SPEED_MULTIPLIER - +/obj/machinery/portable_atmospherics/hydroponics/proc/check_health() + if(seed && !dead && health <= 0) + die() check_level_sanity() update_icon() - return + +/obj/machinery/portable_atmospherics/hydroponics/proc/die() + dead = 1 + harvest = 0 + weedlevel += 1 * HYDRO_SPEED_MULTIPLIER + pestlevel = 0 //Process reagents being input into the tray. /obj/machinery/portable_atmospherics/hydroponics/proc/process_reagents() @@ -351,8 +239,16 @@ if(reagents.total_volume <= 0) return - for(var/datum/reagent/R in reagents.reagent_list) +/* I have plans for this at a later date, so it's just being commented out for now --FalseIncarnate + reagents.trans_to(temp_chem_holder, min(reagents.total_volume,rand(1,3))) + + for(var/datum/reagent/R in temp_chem_holder.reagents.reagent_list) + + var/reagent_total = temp_chem_holder.reagents.get_reagent_amount(R.id) +*/ + + for(var/datum/reagent/R in reagents.reagent_list) var/reagent_total = reagents.get_reagent_amount(R.id) @@ -361,14 +257,14 @@ if(toxic_reagents[R.id]) toxins += toxic_reagents[R.id] * reagent_total if(weedkiller_reagents[R.id]) - weedlevel += weedkiller_reagents[R.id] * reagent_total + weedlevel -= weedkiller_reagents[R.id] * reagent_total if(pestkiller_reagents[R.id]) pestlevel += pestkiller_reagents[R.id] * reagent_total // Beneficial reagents have a few impacts along with health buffs. if(beneficial_reagents[R.id]) - health += beneficial_reagents[R.id][1] * reagent_total - yield_mod = min(100, yield_mod + (beneficial_reagents[R.id][2] * reagent_total)) + health += beneficial_reagents[R.id][1] * reagent_total + yield_mod = min(100, yield_mod + (beneficial_reagents[R.id][2] * reagent_total)) mutation_mod += beneficial_reagents[R.id][3] * reagent_total // Mutagen is distinct from the previous types and mostly has a chance of proccing a mutation. @@ -392,7 +288,7 @@ //--FalseIncarnate - // Handle nutrient refilling + // Handle nutrient refilling. if(nutrient_reagents[R.id]) nutrilevel += nutrient_reagents[R.id] * reagent_total @@ -403,42 +299,43 @@ water_added += water_input waterlevel += water_input + // Water dilutes toxin level. if(water_added > 0) toxins -= round(water_added/4) +// temp_chem_holder.reagents.clear_reagents() reagents.clear_reagents() - check_level_sanity() - update_icon() + check_health() //Harvests the product of a plant. /obj/machinery/portable_atmospherics/hydroponics/proc/harvest(var/mob/user) //Harvest the product of the plant, - if(!seed || !harvest || !user) + if(!seed || !harvest) return if(closed_system) - user << "You can't harvest from the plant while the lid is shut." + if(user) user << "You can't harvest from the plant while the lid is shut." return - seed.harvest(user,yield_mod) - //Increases harvest count for round-end score - //Currently per-plant (not per-item) harvested - // --FalseIncarnate - score_stuffharvested++ + if(user) + seed.harvest(user,yield_mod) + else + seed.harvest(get_turf(src),yield_mod) // Reset values. harvest = 0 lastproduce = age - if(!seed.harvest_repeat) + if(!seed.get_trait(TRAIT_HARVEST_REPEAT)) yield_mod = 0 seed = null dead = 0 age = 0 + sampled = 0 + mutation_mod = 0 - check_level_sanity() - update_icon() + check_health() return //Clears out a dead plant. @@ -451,101 +348,37 @@ seed = null dead = 0 - user << "You remove the dead plant from the [src]." - check_level_sanity() - update_icon() + + sampled = 0 + age = 0 + yield_mod = 0 + mutation_mod = 0 + + user << "You remove the dead plant." + check_health() return -//Refreshes the icon and sets the luminosity -/obj/machinery/portable_atmospherics/hydroponics/update_icon() - - overlays.Cut() - - // Updates the plant overlay. - if(!isnull(seed)) - - if(draw_warnings && health <= (seed.endurance / 2)) - overlays += "over_lowhealth3" - - if(dead) - overlays += "[seed.plant_icon]-dead" - else if(harvest) - overlays += "[seed.plant_icon]-harvest" - else if(age < seed.maturation) - - var/t_growthstate - if(age >= seed.maturation) - t_growthstate = seed.growth_stages - else - t_growthstate = round(seed.maturation / seed.growth_stages) - - overlays += "[seed.plant_icon]-grow[t_growthstate]" - lastproduce = age - else - overlays += "[seed.plant_icon]-grow[seed.growth_stages]" - - //Draw the cover. - if(closed_system) - overlays += "hydrocover" - - //Updated the various alert icons. - if(draw_warnings) - if(waterlevel <= 10) - overlays += "over_lowwater3" - if(nutrilevel <= 2) - overlays += "over_lownutri3" - if(weedlevel >= 5 || pestlevel >= 5 || toxins >= 40) - overlays += "over_alert3" - if(harvest) - overlays += "over_harvest3" - - // Update bioluminescence. - if(seed) - if(seed.biolum) - set_light(round(seed.potency/10)) - if(seed.biolum_colour) - light_color = seed.biolum_colour - else - light_color = null - return - - set_light(0) - return - - // If a weed growth is sufficient, this proc is called. +// If a weed growth is sufficient, this proc is called. /obj/machinery/portable_atmospherics/hydroponics/proc/weed_invasion() //Remove the seed if something is already planted. if(seed) seed = null - seed = seed_types[pick(list("reishi","nettles","amanita","mushrooms","plumphelmet","towercap","harebells","weeds"))] + seed = plant_controller.seeds[pick(list("reishi","nettles","amanita","mushrooms","plumphelmet","towercap","harebells","weeds"))] if(!seed) return //Weed does not exist, someone fucked up. dead = 0 age = 0 - health = seed.endurance + health = seed.get_trait(TRAIT_ENDURANCE) lastcycle = world.time harvest = 0 weedlevel = 0 pestlevel = 0 + sampled = 0 update_icon() - visible_message("\blue [src] has been overtaken by [seed.display_name].") + visible_message("[src] has been overtaken by [seed.display_name].") return -/obj/machinery/portable_atmospherics/hydroponics/proc/check_level_sanity() - //Make sure various values are sane. - if(seed) - health = max(0,min(seed.endurance,health)) - else - health = 0 - dead = 0 - - nutrilevel = max(0,min(nutrilevel,maxnutri)) - waterlevel = max(0,min(waterlevel,maxwater)) - pestlevel = max(0,min(pestlevel,10)) - weedlevel = max(0,min(weedlevel,10)) - toxins = max(0,min(toxins,10)) - /obj/machinery/portable_atmospherics/hydroponics/proc/mutate(var/severity) // No seed, no mutations. @@ -561,20 +394,19 @@ Tier 4 has a higher chance of causing a species shift (if possible), and will ALWAYS cause a stat mutation if it does not shift species Tier 4 also has a low chance to cause a SECOND stat mutation when it does not shift species All mutation chances are increased by the mutation_mod value. Mutation_mod is not transferred into seeds/harvests, and is reset when the plant dies - */ switch(severity) //Reagent Tiers if(1) //Tier 1 if(prob(20+mutation_mod)) //Low chance of stat mutation - if(!isnull(seed_types[seed.name])) + if(!isnull(plant_controller.seeds[seed.name])) seed = seed.diverge() seed.mutate(1,get_turf(src)) return if(2) //Tier 2 if(prob(60+mutation_mod)) //Higher chance of stat mutation - if(!isnull(seed_types[seed.name])) + if(!isnull(plant_controller.seeds[seed.name])) seed = seed.diverge() seed.mutate(1,get_turf(src)) return @@ -583,12 +415,12 @@ if(seed.mutants. && seed.mutants.len) //Check if current seed/plant has mutant species mutate_species() else //No mutant species, mutate stats instead - if(!isnull(seed_types[seed.name])) + if(!isnull(plant_controller.seeds[seed.name])) seed = seed.diverge() seed.mutate(1,get_turf(src)) return else //Failed to shift, mutate stats instead - if(!isnull(seed_types[seed.name])) + if(!isnull(plant_controller.seeds[seed.name])) seed = seed.diverge() seed.mutate(1,get_turf(src)) return @@ -597,38 +429,38 @@ if(seed.mutants. && seed.mutants.len) //Check if current seed/plant has mutant species mutate_species() else //No mutant species, mutate stats instead - if(!isnull(seed_types[seed.name])) + if(!isnull(plant_controller.seeds[seed.name])) seed = seed.diverge() seed.mutate(1,get_turf(src)) if(prob(20+mutation_mod)) //Low chance for second stat mutation - if(!isnull(seed_types[seed.name])) + if(!isnull(plant_controller.seeds[seed.name])) seed = seed.diverge() seed.mutate(1,get_turf(src)) return else //Failed to shift, mutate stats instead - if(!isnull(seed_types[seed.name])) + if(!isnull(plant_controller.seeds[seed.name])) seed = seed.diverge() seed.mutate(1,get_turf(src)) if(prob(20+mutation_mod)) //Low chance for second stat mutation - if(!isnull(seed_types[seed.name])) + if(!isnull(plant_controller.seeds[seed.name])) seed = seed.diverge() seed.mutate(1,get_turf(src)) return //Floral Somatoray Tiers if("F1") //Random Stat Tier if(prob(80+mutation_mod)) //EVEN Higher chance of stat mutation - if(!isnull(seed_types[seed.name])) + if(!isnull(plant_controller.seeds[seed.name])) seed = seed.diverge() seed.mutate(1,get_turf(src)) return if("F2") //Yield Tier if(prob(40+mutation_mod)) //Medium chance of Yield stat mutation - if(!isnull(seed_types[seed.name])) + if(!isnull(plant_controller.seeds[seed.name])) seed = seed.diverge() - if(seed.immutable <= 0 && seed.yield != -1) //Check if the plant can be mutated and has a yield to mutate - seed.yield = seed.yield + rand(-2, 2) //Randomly adjust yield - if(seed.yield < 0) //If yield would drop below 0 after adjustment, set to 0 to allow further attempts - seed.yield = 0 + if(seed.get_trait(TRAIT_IMMUTABLE) <= 0 && seed.get_trait(TRAIT_YIELD) != -1) //Check if the plant can be mutated and has a yield to mutate + seed.set_trait(TRAIT_YIELD, (seed.get_trait(TRAIT_YIELD) + rand(-2, 2))) //Randomly adjust yield + if(seed.get_trait(TRAIT_YIELD) < 0) //If yield would drop below 0 after adjustment, set to 0 to allow further attempts + seed.set_trait(TRAIT_YIELD, 0) return /* code references @@ -642,19 +474,57 @@ //--FalseIncarnate +/obj/machinery/portable_atmospherics/hydroponics/verb/remove_label() + + set name = "Remove Label" + set category = "Object" + set src in view(1) + + if(labelled) + usr << "You remove the label." + labelled = null + update_icon() + else + usr << "There is no label to remove." + return + +/obj/machinery/portable_atmospherics/hydroponics/verb/set_light() + set name = "Set Light" + set category = "Object" + set src in view(1) + + var/new_light = input("Specify a light level.") as null|anything in list(0,1,2,3,4,5,6,7,8,9,10) + if(new_light) + tray_light = new_light + usr << "You set the tray to a light level of [tray_light] lumens." + +/obj/machinery/portable_atmospherics/hydroponics/proc/check_level_sanity() + //Make sure various values are sane. + if(seed) + health = max(0,min(seed.get_trait(TRAIT_ENDURANCE),health)) + else + health = 0 + dead = 0 + + nutrilevel = max(0,min(nutrilevel,10)) + waterlevel = max(0,min(waterlevel,100)) + pestlevel = max(0,min(pestlevel,10)) + weedlevel = max(0,min(weedlevel,10)) + toxins = max(0,min(toxins,10)) + /obj/machinery/portable_atmospherics/hydroponics/proc/mutate_species() var/previous_plant = seed.display_name var/newseed = seed.get_mutant_variant() - if(newseed in seed_types) - seed = seed_types[newseed] + if(newseed in plant_controller.seeds) + seed = plant_controller.seeds[newseed] else return dead = 0 //mutate(1) age = 0 - health = seed.endurance + health = seed.get_trait(TRAIT_ENDURANCE) lastcycle = world.time harvest = 0 weedlevel = 0 @@ -664,7 +534,8 @@ return -/obj/machinery/portable_atmospherics/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob, params) + +/obj/machinery/portable_atmospherics/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob) if(exchange_parts(user, O)) return @@ -692,35 +563,32 @@ process_reagents() update_icon() - //Check if container is one of the botany sprays (defined in hydro_tools.dm) + //Check if container is one of the plantsprays (defined in tray_reagents.dm) else if(istype(O, /obj/item/weapon/plantspray)) - //Check if spray is pest-spray - if(istype(O, /obj/item/weapon/plantspray/pests)) - var/obj/item/weapon/plantspray/P = O - user.drop_item(O) - toxins += P.toxicity - pestlevel -= P.pest_kill_str - weedlevel -= P.weed_kill_str - user << "You spray [src] with [O]." - playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) - del(O) + var/obj/item/weapon/plantspray/P = O + user.drop_item(O) + toxins += P.toxicity + pestlevel -= P.pest_kill_str + weedlevel -= P.weed_kill_str + user << "You spray [src] with [O]." + playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) + del(O) - check_level_sanity() - update_icon() + check_level_sanity() + update_icon() - //Check if spray is weed-spray (un-obtainable, fixed for possible repurposing?) - else if(istype(O, /obj/item/weapon/plantspray/weeds)) - var/obj/item/weapon/plantspray/W = O - user.drop_item(O) - toxins += W.toxicity - pestlevel -= W.pest_kill_str - weedlevel -= W.weed_kill_str - user << "You spray [src] with [O]." - playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) - del(O) + //Check if spray is weedkiller (defined in tray_reagents.dm, un-obtainable currently) + else if(istype(O, /obj/item/weedkiller)) + var/obj/item/weedkiller/W = O + user.drop_item(O) + toxins += W.toxicity + weedlevel -= W.weed_kill_str + user << "You spray [src] with [O]." + playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) + del(O) - check_level_sanity() - update_icon() + check_level_sanity() + update_icon() //Check if container is any spray container else if (istype(O, /obj/item/weapon/reagent_containers/spray)) @@ -739,35 +607,47 @@ else user << "There's nothing in [src] to spray!" - else if(istype(O, /obj/item/weapon/screwdriver) && unwrenchable) //THIS NEED TO BE DONE DIFFERENTLY, SOMEONE REFACTOR THE TRAY CODE ALREADY - if(anchored) - if(anchored == 2) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - anchored = 1 - user << "You unscrew the [src]'s hoses." - panel_open = 0 + else if(istype(O, /obj/item/weapon/screwdriver) && unwrenchable) //THIS NEED TO BE DONE DIFFERENTLY, SOMEONE REFACTOR THE TRAY CODE ALREADY + if(anchored) + if(anchored == 2) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + anchored = 1 + user << "You unscrew the [src]'s hoses." + panel_open = 0 - else if(anchored == 1) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - anchored = 2 - user << "You screw in the [src]'s hoses." - panel_open = 1 + else if(anchored == 1) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) + anchored = 2 + user << "You screw in the [src]'s hoses." + panel_open = 1 - for(var/obj/machinery/portable_atmospherics/hydroponics/h in range(1,src)) - spawn() - h.update_icon() + for(var/obj/machinery/portable_atmospherics/hydroponics/h in range(1,src)) + spawn() + h.update_icon() - //Held item is not an open container, check to see if it can be used (this code was already here) --FalseIncarnate if(istype(O, /obj/item/weapon/wirecutters) || istype(O, /obj/item/weapon/scalpel)) if(!seed) user << "There is nothing to take a sample from in \the [src]." return - seed.harvest(user,yield_mod,1) - health -= (rand(1,5)*10) - check_level_sanity() + if(sampled) + user << "You have already sampled from this plant." + return + if(dead) + user << "The plant is dead." + return + + // Create a sample. + seed.harvest(user,yield_mod,1) + health -= (rand(3,5)*10) + + if(prob(30)) + sampled = 1 + + // Bookkeeping. + check_health() force_update = 1 process() @@ -781,14 +661,14 @@ if(seed) return ..() else - user << "There's no plant in the tray to inject." + user << "There's no plant to inject." return 1 else if(seed) //Leaving this in in case we want to extract from plants later. user << "You can't get any extract out of this plant." else - user << "There's nothing in the tray to draw something from." + user << "There's nothing to draw something from." return 1 else if (istype(O, /obj/item/seeds)) @@ -804,42 +684,28 @@ return user << "You plant the [S.seed.seed_name] [S.seed.seed_noun]." - - if(S.seed.spread == 1) - msg_admin_attack("[key_name(user)][isAntag(user) ? "(ANTAG)" : ""] has planted a creeper packet.") - var/obj/effect/plant_controller/creeper/PC = new(get_turf(src)) - if(PC) - PC.seed = S.seed - else if(S.seed.spread == 2) - msg_admin_attack("[key_name(user)][isAntag(user) ? "(ANTAG)" : ""] has planted a spreading vine packet.") - var/obj/effect/plant_controller/PC = new(get_turf(src)) - if(PC) - PC.seed = S.seed - else - seed = S.seed //Grab the seed datum. - dead = 0 - age = 1 - //Snowflakey, maybe move this to the seed datum - health = (istype(S, /obj/item/seeds/cutting) ? round(seed.endurance/rand(2,5)) : seed.endurance) - - lastcycle = world.time + seed = S.seed //Grab the seed datum. + dead = 0 + age = 1 + //Snowflakey, maybe move this to the seed datum + health = (istype(S, /obj/item/seeds/cutting) ? round(seed.get_trait(TRAIT_ENDURANCE)/rand(2,5)) : seed.get_trait(TRAIT_ENDURANCE)) + lastcycle = world.time del(O) - check_level_sanity() - update_icon() + check_health() else - user << "\red \The [src] already has seeds in it!" + user << "\The [src] already has seeds in it!" else if (istype(O, /obj/item/weapon/minihoe)) // The minihoe - //var/deweeding + if(weedlevel > 0) - user.visible_message("\red [user] starts uprooting the weeds.", "\red You remove the weeds from the [src].") + user.visible_message("[user] starts uprooting the weeds.", "You remove the weeds from the [src].") weedlevel = 0 update_icon() else - user << "\red This plot is completely devoid of weeds. It doesn't need uprooting." + user << "This plot is completely devoid of weeds. It doesn't need uprooting." else if (istype(O, /obj/item/weapon/storage/bag/plants)) @@ -851,7 +717,7 @@ return S.handle_item_insertion(G, 1) - else if(istype(O, /obj/item/weapon/wrench)) + else if(mechanical && istype(O, /obj/item/weapon/wrench)) //If there's a connector here, the portable_atmospherics setup can handle it. if(locate(/obj/machinery/atmospherics/portables_connector/) in loc) @@ -864,7 +730,7 @@ else if(istype(O, /obj/item/apiary)) if(seed) - user << "\red [src] is already occupied!" + user << "[src] is already occupied!" else user.drop_item() del(O) @@ -874,15 +740,18 @@ A.icon_state = src.icon_state A.hydrotray_type = src.type del(src) + else if(O && O.force && seed) + user.visible_message("\The [seed.display_name] has been attacked by [user] with \the [O]!") + if(!dead) + health -= O.force + check_health() return /obj/machinery/portable_atmospherics/hydroponics/attack_tk(mob/user as mob) - - if(harvest) - harvest(user) - - else if(dead) + if(dead) remove_dead(user) + else if(harvest) + harvest(user) /obj/machinery/portable_atmospherics/hydroponics/attack_hand(mob/user as mob) @@ -894,82 +763,70 @@ else if(dead) remove_dead(user) - else - if(seed && !dead) - usr << "[src] has \blue [seed.display_name] \black planted." - if(health <= (seed.endurance / 2)) - usr << "The plant looks \red unhealthy." +/obj/machinery/portable_atmospherics/hydroponics/examine() + + ..() + + if(!seed) + usr << "[src] is empty." + return + + usr << "[seed.display_name] are growing here." + + if(!Adjacent(usr)) + return + + usr << "Water: [round(waterlevel,0.1)]/100" + usr << "Nutrient: [round(nutrilevel,0.1)]/10" + + if(weedlevel >= 5) + usr << "\The [src] is infested with weeds!" + if(pestlevel >= 5) + usr << "\The [src] is infested with tiny worms!" + + if(dead) + usr << "The plant is dead." + else if(health <= (seed.get_trait(TRAIT_ENDURANCE)/ 2)) + usr << "The plant looks unhealthy." + + if(mechanical) + var/turf/T = loc + var/datum/gas_mixture/environment + + if(closed_system && (connected_port || holding)) + environment = air_contents + + if(!environment) + if(istype(T)) + environment = T.return_air() + + if(!environment) //We're in a crate or nullspace, bail out. + return + + var/light_string + if(closed_system && mechanical) + light_string = "that the internal lights are set to [tray_light] lumens" else - usr << "[src] is empty." - usr << "Water: [round(waterlevel,0.1)]/[maxwater]" - usr << "Nutrient: [round(nutrilevel,0.1)]/[maxnutri]" - if(weedlevel >= 5) - usr << "[src] is \red filled with weeds!" - if(pestlevel >= 5) - usr << "[src] is \red filled with tiny worms!" - - if(!istype(src,/obj/machinery/portable_atmospherics/hydroponics/soil)) - - var/turf/T = loc - var/datum/gas_mixture/environment - - if(closed_system && (connected_port || holding)) - environment = air_contents - - if(!environment) - if(istype(T)) - environment = T.return_air() - - if(!environment) //We're in a crate or nullspace, bail out. - return - var/atom/movable/lighting_overlay/L = locate(/atom/movable/lighting_overlay) in T var/light_available - var/light_string if(L) light_available = max(0,min(10,L.lum_r + L.lum_g + L.lum_b)-5) else light_available = 5 light_string = "a light level of [light_available] lumens" - usr << "The tray's sensor suite is reporting [light_string] and a temperature of [environment.temperature]K." + usr << "The tray's sensor suite is reporting [light_string] and a temperature of [environment.temperature]K." -/obj/machinery/portable_atmospherics/hydroponics/verb/close_lid() +/obj/machinery/portable_atmospherics/hydroponics/verb/close_lid_verb() set name = "Toggle Tray Lid" set category = "Object" set src in view(1) + close_lid(usr) - if(!usr || usr.stat || usr.restrained()) +/obj/machinery/portable_atmospherics/hydroponics/proc/close_lid(var/mob/living/user) + if(!user || user.stat || user.restrained()) return closed_system = !closed_system - usr << "You [closed_system ? "close" : "open"] the tray's lid." - if(closed_system) - flags &= ~OPENCONTAINER - else - flags |= OPENCONTAINER - + user << "You [closed_system ? "close" : "open"] the tray's lid." update_icon() - -/obj/machinery/portable_atmospherics/hydroponics/soil - name = "soil" - icon = 'icons/obj/hydroponics.dmi' - icon_state = "soil" - density = 0 - use_power = 0 - draw_warnings = 0 - -/obj/machinery/portable_atmospherics/hydroponics/soil/attackby(var/obj/item/O as obj, var/mob/user as mob, params) - if(istype(O, /obj/item/weapon/shovel)) - user << "You clear up [src]!" - del(src) - else if(istype(O,/obj/item/weapon/shovel) || istype(O,/obj/item/weapon/tank)) - return - else - ..() - -/obj/machinery/portable_atmospherics/hydroponics/soil/New() - ..() - verbs -= /obj/machinery/portable_atmospherics/hydroponics/verb/close_lid - -#undef HYDRO_SPEED_MULTIPLIER diff --git a/code/modules/hydroponics/trays/tray_apiary.dm b/code/modules/hydroponics/trays/tray_apiary.dm new file mode 100644 index 00000000000..f2098e7481c --- /dev/null +++ b/code/modules/hydroponics/trays/tray_apiary.dm @@ -0,0 +1,240 @@ +//http://www.youtube.com/watch?v=-1GadTfGFvU +//i could have done these as just an ordinary plant, but fuck it - there would have been too much snowflake code + +/obj/machinery/apiary + name = "apiary tray" + icon = 'icons/obj/hydroponics_machines.dmi' + icon_state = "hydrotray3" + density = 1 + anchored = 1 + var/nutrilevel = 0 + var/yieldmod = 1 + var/mut = 1 + var/toxic = 0 + var/dead = 0 + var/health = -1 + var/maxhealth = 100 + var/lastcycle = 0 + var/cycledelay = 100 + var/harvestable_honey = 0 + var/beezeez = 0 + var/swarming = 0 + + var/bees_in_hive = 0 + var/list/owned_bee_swarms = list() + var/hydrotray_type = /obj/machinery/portable_atmospherics/hydroponics + +//overwrite this after it's created if the apiary needs a custom machinery sprite +/obj/machinery/apiary/New() + ..() + overlays += image('icons/obj/apiary_bees_etc.dmi', icon_state="apiary") + +/obj/machinery/apiary/bullet_act(var/obj/item/projectile/Proj) //Works with the Somatoray to modify plant variables. + if(istype(Proj ,/obj/item/projectile/energy/floramut)) + mut++ + else if(istype(Proj ,/obj/item/projectile/energy/florayield)) + if(!yieldmod) + yieldmod += 1 + //world << "Yield increased by 1, from 0, to a total of [myseed.yield]" + else if (prob(1/(yieldmod * yieldmod) *100))//This formula gives you diminishing returns based on yield. 100% with 1 yield, decreasing to 25%, 11%, 6, 4, 2... + yieldmod += 1 + //world << "Yield increased by 1, to a total of [myseed.yield]" + else + ..() + return + +/obj/machinery/apiary/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(istype(O, /obj/item/queen_bee)) + if(health > 0) + user << "\red There is already a queen in there." + else + health = 10 + nutrilevel += 10 + user.drop_item() + del(O) + user << "\blue You carefully insert the queen into [src], she gets busy making a hive." + bees_in_hive = 0 + else if(istype(O, /obj/item/beezeez)) + beezeez += 100 + nutrilevel += 10 + user.drop_item() + if(health > 0) + user << "\blue You insert [O] into [src]. A relaxed humming appears to pick up." + else + user << "\blue You insert [O] into [src]. Now it just needs some bees." + del(O) + else if(istype(O, /obj/item/weapon/minihoe)) + if(health > 0) + user << "\red You begin to dislodge the apiary from the tray, the bees don't like that." + angry_swarm(user) + else + user << "\blue You begin to dislodge the dead apiary from the tray." + if(do_after(user, 50)) + new hydrotray_type(src.loc) + new /obj/item/apiary(src.loc) + user << "\red You dislodge the apiary from the tray." + del(src) + else if(istype(O, /obj/item/weapon/bee_net)) + var/obj/item/weapon/bee_net/N = O + if(N.caught_bees > 0) + user << "\blue You empty the bees into the apiary." + bees_in_hive += N.caught_bees + N.caught_bees = 0 + else + user << "\blue There are no more bees in the net." + else if(istype(O, /obj/item/weapon/reagent_containers/glass)) + var/obj/item/weapon/reagent_containers/glass/G = O + if(harvestable_honey > 0) + if(health > 0) + user << "\red You begin to harvest the honey. The bees don't seem to like it." + angry_swarm(user) + else + user << "\blue You begin to harvest the honey." + if(do_after(user,50)) + G.reagents.add_reagent("honey",harvestable_honey) + harvestable_honey = 0 + user << "\blue You successfully harvest the honey." + else + user << "\blue There is no honey left to harvest." + else + angry_swarm(user) + ..() + +/obj/machinery/apiary/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(air_group || (height==0)) return 1 + + if(istype(mover) && mover.checkpass(PASSTABLE)) + return 1 + else + return 0 + +/obj/machinery/apiary/process() + + if(swarming > 0) + swarming -= 1 + if(swarming <= 0) + for(var/mob/living/simple_animal/bee/B in src.loc) + bees_in_hive += B.strength + del(B) + else if(bees_in_hive < 10) + for(var/mob/living/simple_animal/bee/B in src.loc) + bees_in_hive += B.strength + del(B) + + if(world.time > (lastcycle + cycledelay)) + lastcycle = world.time + if(health < 0) + return + + //magical bee formula + if(beezeez > 0) + beezeez -= 1 + + nutrilevel += 2 + health += 1 + toxic = max(0, toxic - 1) + + //handle nutrients + nutrilevel -= bees_in_hive / 10 + owned_bee_swarms.len / 5 + if(nutrilevel > 0) + bees_in_hive += 1 * yieldmod + if(health < maxhealth) + health++ + else + //nutrilevel is less than 1, so we're effectively subtracting here + health += max(nutrilevel - 1, round(-health / 2)) + bees_in_hive += max(nutrilevel - 1, round(-bees_in_hive / 2)) + if(owned_bee_swarms.len) + var/mob/living/simple_animal/bee/B = pick(owned_bee_swarms) + B.target_turf = get_turf(src) + + //clear out some toxins + if(toxic > 0) + toxic -= 1 + health -= 1 + + if(health <= 0) + return + + //make a bit of honey + if(harvestable_honey < 50) + harvestable_honey += 0.5 + + //make some new bees + if(bees_in_hive >= 10 && prob(bees_in_hive * 10)) + var/mob/living/simple_animal/bee/B = new(get_turf(src), src) + owned_bee_swarms.Add(B) + B.mut = mut + B.toxic = toxic + bees_in_hive -= 1 + + //find some plants, harvest + for(var/obj/machinery/portable_atmospherics/hydroponics/H in view(7, src)) + if(H.seed && !H.dead && prob(owned_bee_swarms.len * 10)) + src.nutrilevel++ + H.nutrilevel++ + if(mut < H.mutation_mod - 1) + mut = H.mutation_mod - 1 + else if(mut > H.mutation_mod - 1) + H.mutation_mod = mut + + //flowers give us pollen (nutrients) +/* - All plants should be giving nutrients to the hive. + if(H.myseed.type == /obj/item/seeds/harebell || H.myseed.type == /obj/item/seeds/sunflowerseed) + src.nutrilevel++ + H.nutrilevel++ +*/ + //have a few beneficial effects on nearby plants + if(prob(10)) + H.lastcycle -= 5 + if(prob(10)) + H.seed.set_trait(TRAIT_ENDURANCE,max(H.seed.get_trait(TRAIT_ENDURANCE)*1.5,H.seed.get_trait(TRAIT_ENDURANCE)+1)) + if(H.toxins && prob(10)) + H.toxins = min(0, H.toxins - 1) + toxic++ + +/obj/machinery/apiary/proc/die() + if(owned_bee_swarms.len) + var/mob/living/simple_animal/bee/B = pick(owned_bee_swarms) + B.target_turf = get_turf(src) + B.strength -= 1 + if(B.strength <= 0) + del(B) + else if(B.strength <= 5) + B.icon_state = "bees[B.strength]" + bees_in_hive = 0 + health = 0 + +/obj/machinery/apiary/proc/angry_swarm(var/mob/M) + for(var/mob/living/simple_animal/bee/B in owned_bee_swarms) + B.feral = 25 + B.target_mob = M + + swarming = 25 + + while(bees_in_hive > 0) + var/spawn_strength = bees_in_hive + if(bees_in_hive >= 5) + spawn_strength = 6 + + var/mob/living/simple_animal/bee/B = new(get_turf(src), src) + B.target_mob = M + B.strength = spawn_strength + B.feral = 25 + B.mut = mut + B.toxic = toxic + bees_in_hive -= spawn_strength + +/obj/machinery/apiary/verb/harvest_honeycomb() + set src in oview(1) + set name = "Harvest honeycomb" + set category = "Object" + + while(health > 15) + health -= 15 + var/obj/item/weapon/reagent_containers/food/snacks/honeycomb/H = new(src.loc) + if(toxic > 0) + H.reagents.add_reagent("toxin", toxic) + + usr << "\blue You harvest the honeycomb from the hive. There is a wild buzzing!" + angry_swarm(usr) diff --git a/code/modules/hydroponics/trays/tray_process.dm b/code/modules/hydroponics/trays/tray_process.dm new file mode 100644 index 00000000000..d16ca75cc97 --- /dev/null +++ b/code/modules/hydroponics/trays/tray_process.dm @@ -0,0 +1,124 @@ +/obj/machinery/portable_atmospherics/hydroponics/process() + + /* MOVED INTO code\game\objects\effects\effect_system.dm + // Handle nearby smoke if any. + for(var/obj/effect/effect/smoke/chem/smoke in view(1, src)) + if(smoke.reagents.total_volume) + smoke.reagents.copy_to(src, 5) + */ + + //Do this even if we're not ready for a plant cycle. + process_reagents() + + // Update values every cycle rather than every process() tick. + if(force_update) + force_update = 0 + else if(world.time < (lastcycle + cycledelay)) + return + lastcycle = world.time + + // Weeds like water and nutrients, there's a chance the weed population will increase. + // Bonus chance if the tray is unoccupied. + if(waterlevel > 10 && nutrilevel > 2 && prob(isnull(seed) ? 5 : 1)) + weedlevel += 1 * HYDRO_SPEED_MULTIPLIER + + // There's a chance for a weed explosion to happen if the weeds take over. + // Plants that are themselves weeds (weed_tolerance > 10) are unaffected. + if (weedlevel >= 10 && prob(10)) + if(!seed || weedlevel >= seed.get_trait(TRAIT_WEED_TOLERANCE)) + weed_invasion() + + // If there is no seed data (and hence nothing planted), + // or the plant is dead, process nothing further. + if(!seed || dead) + if(mechanical) update_icon() //Harvesting would fail to set alert icons properly. + return + + // Advance plant age. + if(prob(30)) age += 1 * HYDRO_SPEED_MULTIPLIER + + //Highly mutable plants have a chance of mutating every tick. + if(seed.get_trait(TRAIT_IMMUTABLE) == -1) + var/mut_prob = rand(1,100) + if(mut_prob <= 5) mutate(mut_prob == 1 ? 2 : 1) + + // Maintain tray nutrient and water levels. + if(seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) > 0 && nutrilevel > 0 && prob(25)) + nutrilevel -= max(0,seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) * HYDRO_SPEED_MULTIPLIER) + if(seed.get_trait(TRAIT_WATER_CONSUMPTION) > 0 && waterlevel > 0 && prob(25)) + waterlevel -= max(0,seed.get_trait(TRAIT_WATER_CONSUMPTION) * HYDRO_SPEED_MULTIPLIER) + + // Make sure the plant is not starving or thirsty. Adequate + // water and nutrients will cause a plant to become healthier. + var/healthmod = rand(1,3) * HYDRO_SPEED_MULTIPLIER + if(seed.get_trait(TRAIT_REQUIRES_NUTRIENTS) && prob(35)) + health += (nutrilevel < 2 ? -healthmod : healthmod) + if(seed.get_trait(TRAIT_REQUIRES_WATER) && prob(35)) + health += (waterlevel < 10 ? -healthmod : healthmod) + + // Check that pressure, heat and light are all within bounds. + // First, handle an open system or an unconnected closed system. + var/turf/T = loc + var/datum/gas_mixture/environment + // If we're closed, take from our internal sources. + if(closed_system && (connected_port || holding)) + environment = air_contents + // If atmos input is not there, grab from turf. + if(!environment && istype(T)) environment = T.return_air() + if(!environment) return + + // Seed datum handles gasses, light and pressure. + if(mechanical && closed_system) + health -= seed.handle_environment(T,environment,tray_light) + else + health -= seed.handle_environment(T,environment) + + // If we're attached to a pipenet, then we should let the pipenet know we might have modified some gasses + if (closed_system && connected_port) + update_connected_network() + + // Toxin levels beyond the plant's tolerance cause damage, but + // toxins are sucked up each tick and slowly reduce over time. + if(toxins > 0) + var/toxin_uptake = max(1,round(toxins/10)) + if(toxins > seed.get_trait(TRAIT_TOXINS_TOLERANCE)) + health -= toxin_uptake + toxins -= toxin_uptake + + // Check for pests and weeds. + // Some carnivorous plants happily eat pests. + if(pestlevel > 0) + if(seed.get_trait(TRAIT_CARNIVOROUS)) + health += HYDRO_SPEED_MULTIPLIER + pestlevel -= HYDRO_SPEED_MULTIPLIER + else if (pestlevel >= seed.get_trait(TRAIT_PEST_TOLERANCE)) + health -= HYDRO_SPEED_MULTIPLIER + + // Some plants thrive and live off of weeds. + if(weedlevel > 0) + if(seed.get_trait(TRAIT_PARASITE)) + health += HYDRO_SPEED_MULTIPLIER + weedlevel -= HYDRO_SPEED_MULTIPLIER + else if (weedlevel >= seed.get_trait(TRAIT_WEED_TOLERANCE)) + health -= HYDRO_SPEED_MULTIPLIER + + // Handle life and death. + // When the plant dies, weeds thrive and pests die off. + check_health() + + // If enough time (in cycles, not ticks) has passed since the plant was harvested, we're ready to harvest again. + if((age > seed.get_trait(TRAIT_MATURATION)) && \ + ((age - lastproduce) > seed.get_trait(TRAIT_PRODUCTION)) && \ + (!harvest && !dead)) + harvest = 1 + lastproduce = age + + if(prob(3)) // On each tick, there's a chance the pest population will increase + pestlevel += 0.1 * HYDRO_SPEED_MULTIPLIER + + // Some seeds will self-harvest if you don't keep a lid on them. + if(seed && seed.can_self_harvest && harvest && !closed_system && prob(5)) + harvest() + + check_health() + return diff --git a/code/modules/hydroponics/trays/tray_reagents.dm b/code/modules/hydroponics/trays/tray_reagents.dm new file mode 100644 index 00000000000..5e5cb819b98 --- /dev/null +++ b/code/modules/hydroponics/trays/tray_reagents.dm @@ -0,0 +1,126 @@ + +/obj/item/weapon/plantspray + icon = 'icons/obj/hydroponics_machines.dmi' + item_state = "spray" + flags = OPENCONTAINER | NOBLUDGEON + slot_flags = SLOT_BELT + throwforce = 4 + w_class = 2.0 + throw_speed = 2 + throw_range = 10 + var/toxicity = 4 + var/pest_kill_str = 0 + var/weed_kill_str = 0 + +/obj/item/weapon/plantspray/weeds // -- Skie + + name = "weed-spray" + desc = "It's a toxic mixture, in spray form, to kill small weeds." + icon_state = "weedspray" + weed_kill_str = 6 + +/obj/item/weapon/plantspray/pests + name = "pest-spray" + desc = "It's some pest eliminator spray! Do not inhale!" + icon_state = "pestspray" + pest_kill_str = 6 + +/obj/item/weapon/plantspray/pests/old + name = "bottle of pestkiller" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle16" + +/obj/item/weapon/plantspray/pests/old/carbaryl + name = "bottle of carbaryl" + icon_state = "bottle16" + toxicity = 4 + pest_kill_str = 2 + +/obj/item/weapon/plantspray/pests/old/lindane + name = "bottle of lindane" + icon_state = "bottle18" + toxicity = 6 + pest_kill_str = 4 + +/obj/item/weapon/plantspray/pests/old/phosmet + name = "bottle of phosmet" + icon_state = "bottle15" + toxicity = 8 + pest_kill_str = 7 + + +// ************************************* +// Weedkiller defines for hydroponics +// ************************************* + +/obj/item/weedkiller + name = "bottle of weedkiller" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle16" + flags = OPENCONTAINER | NOBLUDGEON + var/toxicity = 0 + var/weed_kill_str = 0 + +/obj/item/weedkiller/triclopyr + name = "bottle of glyphosate" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle16" + toxicity = 4 + weed_kill_str = 2 + +/obj/item/weedkiller/lindane + name = "bottle of triclopyr" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle18" + toxicity = 6 + weed_kill_str = 4 + +/obj/item/weedkiller/D24 + name = "bottle of 2,4-D" + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle15" + toxicity = 8 + weed_kill_str = 7 + +// ************************************* +// Nutrient defines for hydroponics +// ************************************* + +/obj/item/weapon/reagent_containers/glass/fertilizer + name = "fertilizer bottle" + desc = "A small glass bottle. Can hold up to 10 units." + icon = 'icons/obj/chemical.dmi' + icon_state = "bottle16" + flags = OPENCONTAINER + possible_transfer_amounts = null + w_class = 2.0 + + var/fertilizer //Reagent contained, if any. + + //Like a shot glass! + amount_per_transfer_from_this = 10 + volume = 10 + +/obj/item/weapon/reagent_containers/glass/fertilizer/New() + ..() + + src.pixel_x = rand(-5.0, 5) + src.pixel_y = rand(-5.0, 5) + + if(fertilizer) + reagents.add_reagent(fertilizer,10) + +/obj/item/weapon/reagent_containers/glass/fertilizer/ez + name = "bottle of E-Z-Nutrient" + icon_state = "bottle16" + fertilizer = "eznutrient" + +/obj/item/weapon/reagent_containers/glass/fertilizer/l4z + name = "bottle of Left 4 Zed" + icon_state = "bottle18" + fertilizer = "left4zed" + +/obj/item/weapon/reagent_containers/glass/fertilizer/rh + name = "bottle of Robust Harvest" + icon_state = "bottle15" + fertilizer = "robustharvest" diff --git a/code/modules/hydroponics/trays/tray_soil.dm b/code/modules/hydroponics/trays/tray_soil.dm new file mode 100644 index 00000000000..ff8e3e23df0 --- /dev/null +++ b/code/modules/hydroponics/trays/tray_soil.dm @@ -0,0 +1,67 @@ +/obj/machinery/portable_atmospherics/hydroponics/soil + name = "soil" + icon_state = "soil" + density = 0 + use_power = 0 + mechanical = 0 + tray_light = 0 + +/obj/machinery/portable_atmospherics/hydroponics/soil/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(istype(O,/obj/item/weapon/tank)) + return + else + ..() + +/obj/machinery/portable_atmospherics/hydroponics/soil/New() + ..() + verbs -= /obj/machinery/portable_atmospherics/hydroponics/verb/close_lid_verb + verbs -= /obj/machinery/portable_atmospherics/hydroponics/verb/remove_label + verbs -= /obj/machinery/portable_atmospherics/hydroponics/verb/set_light + +/obj/machinery/portable_atmospherics/hydroponics/soil/CanPass() + return 1 + +// Holder for vine plants. +// Icons for plants are generated as overlays, so setting it to invisible wouldn't work. +// Hence using a blank icon. +/obj/machinery/portable_atmospherics/hydroponics/soil/invisible + name = "plant" + icon = 'icons/obj/seeds.dmi' + icon_state = "blank" + +/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/New(var/newloc,var/datum/seed/newseed) + ..() + seed = newseed + dead = 0 + age = 1 + health = seed.get_trait(TRAIT_ENDURANCE) + lastcycle = world.time + pixel_y = rand(-5,5) + check_health() + +/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/remove_dead() + ..() + del(src) + +/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/harvest() + ..() + if(!seed) // Repeat harvests are a thing. + del(src) + +/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/die() + del(src) + +/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/process() + if(!seed) + del(src) + return + else if(name=="plant") + name = seed.display_name + ..() + +/obj/machinery/portable_atmospherics/hydroponics/soil/invisible/Del() + // Check if we're masking a decal that needs to be visible again. + for(var/obj/effect/plant/plant in get_turf(src)) + if(plant.invisibility == INVISIBILITY_MAXIMUM) + plant.invisibility = initial(plant.invisibility) + ..() diff --git a/code/modules/hydroponics/hydro_tools.dm b/code/modules/hydroponics/trays/tray_tools.dm similarity index 53% rename from code/modules/hydroponics/hydro_tools.dm rename to code/modules/hydroponics/trays/tray_tools.dm index 70cf1f9cf4b..df21cfa90d6 100644 --- a/code/modules/hydroponics/hydro_tools.dm +++ b/code/modules/hydroponics/trays/tray_tools.dm @@ -9,8 +9,38 @@ icon = 'icons/obj/device.dmi' icon_state = "hydro" item_state = "analyzer" + var/form_title + var/last_data + +/obj/item/device/analyzer/plant_analyzer/proc/print_report_verb() + set name = "Print Plant Report" + set category = "Object" + set src = usr + + if(usr.stat || usr.restrained() || usr.lying) + return + print_report(usr) + +/obj/item/device/analyzer/plant_analyzer/Topic(href, href_list) + if(..()) + return + if(href_list["print"]) + print_report(usr) + +/obj/item/device/analyzer/plant_analyzer/proc/print_report(var/mob/living/user) + if(!last_data) + user << "There is no scan data to print." + return + var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(get_turf(src)) + P.name = "paper - [form_title]" + P.info = "[last_data]" + if(istype(user,/mob/living/carbon/human) && !(user.l_hand && user.r_hand)) + user.put_in_hands(P) + user.visible_message("\The [src] spits out a piece of paper.") + return /obj/item/device/analyzer/plant_analyzer/attack_self(mob/user as mob) + print_report(user) return 0 /obj/item/device/analyzer/plant_analyzer/afterattack(obj/target, mob/user, flag) @@ -29,16 +59,18 @@ var/tray_mutation_mod //mutation modifier of the tray //--FalseIncarnate - if(istype(target,/obj/item/weapon/reagent_containers/food/snacks/grown)) + if(istype(target,/obj/structure/table)) + return ..() + else if(istype(target,/obj/item/weapon/reagent_containers/food/snacks/grown)) var/obj/item/weapon/reagent_containers/food/snacks/grown/G = target - grown_seed = seed_types[G.plantname] + grown_seed = plant_controller.seeds[G.plantname] grown_reagents = G.reagents else if(istype(target,/obj/item/weapon/grown)) var/obj/item/weapon/grown/G = target - grown_seed = seed_types[G.plantname] + grown_seed = plant_controller.seeds[G.plantname] grown_reagents = G.reagents else if(istype(target,/obj/item/seeds)) @@ -66,21 +98,21 @@ grown_reagents = H.reagents if(!grown_seed) - user << "\red [src] can tell you nothing about [target]." + user << "[src] can tell you nothing about \the [target]." return - var/dat = "

Plant data for [target]

" - user.visible_message("\blue [user] runs the scanner over [target].") + form_title = "[grown_seed.seed_name] (#[grown_seed.uid])" + var/dat = "

Plant data for [form_title]

" + user.visible_message("[user] runs the scanner over \the [target].") dat += "

General Data

" dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" //--FalseIncarnate //Tray-specific stats like Age and Mutation Modifier, not shown if target was not a hydroponics tray or soil @@ -105,29 +137,26 @@ dat += "

Other Data

" - if(grown_seed.harvest_repeat) + if(grown_seed.get_trait(TRAIT_HARVEST_REPEAT)) dat += "This plant can be harvested repeatedly.
" - if(grown_seed.immutable == -1) + if(grown_seed.get_trait(TRAIT_IMMUTABLE) == -1) dat += "This plant is highly mutable.
" - else if(grown_seed.immutable > 0) + else if(grown_seed.get_trait(TRAIT_IMMUTABLE) > 0) dat += "This plant does not possess genetics that are alterable.
" - if(grown_seed.products && grown_seed.products.len) - dat += "The mature plant will produce [grown_seed.products.len == 1 ? "fruit" : "[grown_seed.products.len] varieties of fruit"].
" - - if(grown_seed.requires_nutrients) - if(grown_seed.nutrient_consumption < 0.05) + if(grown_seed.get_trait(TRAIT_REQUIRES_NUTRIENTS)) + if(grown_seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) < 0.05) dat += "It consumes a small amount of nutrient fluid.
" - else if(grown_seed.nutrient_consumption > 0.2) + else if(grown_seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) > 0.2) dat += "It requires a heavy supply of nutrient fluid.
" else dat += "It requires a supply of nutrient fluid.
" - if(grown_seed.requires_water) - if(grown_seed.water_consumption < 1) + if(grown_seed.get_trait(TRAIT_REQUIRES_WATER)) + if(grown_seed.get_trait(TRAIT_WATER_CONSUMPTION) < 1) dat += "It requires very little water.
" - else if(grown_seed.water_consumption > 5) + else if(grown_seed.get_trait(TRAIT_WATER_CONSUMPTION) > 5) dat += "It requires a large amount of water.
" else dat += "It requires a stable supply of water.
" @@ -135,120 +164,84 @@ if(grown_seed.mutants && grown_seed.mutants.len) dat += "It exhibits a high degree of potential subspecies shift.
" - dat += "It thrives in a temperature of [grown_seed.ideal_heat] Kelvin." + dat += "It thrives in a temperature of [grown_seed.get_trait(TRAIT_IDEAL_HEAT)] Kelvin." - if(grown_seed.lowkpa_tolerance < 20) + if(grown_seed.get_trait(TRAIT_LOWKPA_TOLERANCE) < 20) dat += "
It is well adapted to low pressure levels." - if(grown_seed.highkpa_tolerance > 220) + if(grown_seed.get_trait(TRAIT_HIGHKPA_TOLERANCE) > 220) dat += "
It is well adapted to high pressure levels." - if(grown_seed.heat_tolerance > 30) + if(grown_seed.get_trait(TRAIT_HEAT_TOLERANCE) > 30) dat += "
It is well adapted to a range of temperatures." - else if(grown_seed.heat_tolerance < 10) + else if(grown_seed.get_trait(TRAIT_HEAT_TOLERANCE) < 10) dat += "
It is very sensitive to temperature shifts." - dat += "
It thrives in a light level of [grown_seed.ideal_light] lumen[grown_seed.ideal_light == 1 ? "" : "s"]." + dat += "
It thrives in a light level of [grown_seed.get_trait(TRAIT_IDEAL_LIGHT)] lumen[grown_seed.get_trait(TRAIT_IDEAL_LIGHT) == 1 ? "" : "s"]." - if(grown_seed.light_tolerance > 10) + if(grown_seed.get_trait(TRAIT_LIGHT_TOLERANCE) > 10) dat += "
It is well adapted to a range of light levels." - else if(grown_seed.light_tolerance < 3) + else if(grown_seed.get_trait(TRAIT_LIGHT_TOLERANCE) < 3) dat += "
It is very sensitive to light level shifts." - if(grown_seed.toxins_tolerance < 3) + if(grown_seed.get_trait(TRAIT_TOXINS_TOLERANCE) < 3) dat += "
It is highly sensitive to toxins." - else if(grown_seed.toxins_tolerance > 6) + else if(grown_seed.get_trait(TRAIT_TOXINS_TOLERANCE) > 6) dat += "
It is remarkably resistant to toxins." - if(grown_seed.pest_tolerance < 3) + if(grown_seed.get_trait(TRAIT_PEST_TOLERANCE) < 3) dat += "
It is highly sensitive to pests." - else if(grown_seed.pest_tolerance > 6) + else if(grown_seed.get_trait(TRAIT_PEST_TOLERANCE) > 6) dat += "
It is remarkably resistant to pests." - if(grown_seed.weed_tolerance < 3) + if(grown_seed.get_trait(TRAIT_WEED_TOLERANCE) < 3) dat += "
It is highly sensitive to weeds." - else if(grown_seed.weed_tolerance > 6) + else if(grown_seed.get_trait(TRAIT_WEED_TOLERANCE) > 6) dat += "
It is remarkably resistant to weeds." - switch(grown_seed.spread) + switch(grown_seed.get_trait(TRAIT_SPREAD)) if(1) - dat += "
It is capable of growing beyond the confines of a tray." + dat += "
It is able to be planted outside of a tray." if(2) dat += "
It is a robust and vigorous vine that will spread rapidly." - switch(grown_seed.carnivorous) + switch(grown_seed.get_trait(TRAIT_CARNIVOROUS)) if(1) dat += "
It is carniovorous and will eat tray pests for sustenance." if(2) dat += "
It is carnivorous and poses a significant threat to living things around it." - if(grown_seed.parasite) + if(grown_seed.get_trait(TRAIT_PARASITE)) dat += "
It is capable of parisitizing and gaining sustenance from tray weeds." - if(grown_seed.alter_temp) - dat += "
It will periodically alter the local temperature by [grown_seed.alter_temp] degrees Kelvin." + if(grown_seed.get_trait(TRAIT_ALTER_TEMP)) + dat += "
It will periodically alter the local temperature by [grown_seed.get_trait(TRAIT_ALTER_TEMP)] degrees Kelvin." - if(grown_seed.biolum) - dat += "
It is [grown_seed.biolum_colour ? "bio-luminescent" : "bio-luminescent"]." - if(grown_seed.flowers) - dat += "
It has [grown_seed.flower_colour ? "flowers" : "flowers"]." + if(grown_seed.get_trait(TRAIT_BIOLUM)) + dat += "
It is [grown_seed.get_trait(TRAIT_BIOLUM_COLOUR) ? "bio-luminescent" : "bio-luminescent"]." + + if(grown_seed.get_trait(TRAIT_PRODUCES_POWER)) + dat += "
The fruit will function as a battery if prepared appropriately." + + if(grown_seed.get_trait(TRAIT_STINGS)) + dat += "
The fruit is covered in stinging spines." + + if(grown_seed.get_trait(TRAIT_JUICY) == 1) + dat += "
The fruit is soft-skinned and juicy." + else if(grown_seed.get_trait(TRAIT_JUICY) == 2) + dat += "
The fruit is excessively juicy." + + if(grown_seed.get_trait(TRAIT_EXPLOSIVE)) + dat += "
The fruit is internally unstable." + + if(grown_seed.get_trait(TRAIT_TELEPORTING)) + dat += "
The fruit is temporal/spatially unstable." if(dat) + last_data = dat + dat += "

\[print report\]" user << browse(dat,"window=plant_analyzer") return -// ************************************* -// Hydroponics Tools -// ************************************* - -/obj/item/weapon/plantspray - icon = 'icons/obj/hydroponics.dmi' - item_state = "spray" - flags = OPENCONTAINER | NOBLUDGEON - slot_flags = SLOT_BELT - throwforce = 4 - w_class = 2.0 - throw_speed = 2 - throw_range = 10 - var/toxicity = 4 - var/pest_kill_str = 0 - var/weed_kill_str = 0 - -/obj/item/weapon/plantspray/weeds // -- Skie - - name = "weed-spray" - desc = "It's a toxic mixture, in spray form, to kill small weeds." - icon_state = "weedspray" - weed_kill_str = 2 - -/obj/item/weapon/plantspray/pests - name = "pest-spray" - desc = "It's some pest eliminator spray! Do not inhale!" - icon_state = "pestspray" - pest_kill_str = 2 - -/obj/item/weapon/plantspray/pests/old - name = "bottle of pestkiller" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle16" - -/obj/item/weapon/plantspray/pests/old/carbaryl - name = "bottle of carbaryl" - icon_state = "bottle16" - toxicity = 4 - pest_kill_str = 2 - -/obj/item/weapon/plantspray/pests/old/lindane - name = "bottle of lindane" - icon_state = "bottle18" - toxicity = 6 - pest_kill_str = 4 - -/obj/item/weapon/plantspray/pests/old/phosmet - name = "bottle of phosmet" - icon_state = "bottle15" - toxicity = 8 - pest_kill_str = 7 - /obj/item/weapon/minihoe // -- Numbers name = "mini hoe" desc = "It's used for removing weeds or scratching your back." @@ -259,85 +252,9 @@ force = 5.0 throwforce = 7.0 w_class = 2.0 + m_amt = 50 attack_verb = list("slashed", "sliced", "cut", "clawed") - -// ************************************* -// Weedkiller defines for hydroponics -// ************************************* - -/obj/item/weedkiller - name = "bottle of weedkiller" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle16" - var/toxicity = 0 - var/weed_kill_str = 0 - -/obj/item/weedkiller/triclopyr - name = "bottle of glyphosate" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle16" - toxicity = 4 - weed_kill_str = 2 - -/obj/item/weedkiller/lindane - name = "bottle of triclopyr" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle18" - toxicity = 6 - weed_kill_str = 4 - -/obj/item/weedkiller/D24 - name = "bottle of 2,4-D" - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle15" - toxicity = 8 - weed_kill_str = 7 - - -// ************************************* -// Nutrient defines for hydroponics -// ************************************* - -/obj/item/weapon/reagent_containers/glass/fertilizer - name = "fertilizer bottle" - desc = "A small glass bottle. Can hold up to 10 units." - icon = 'icons/obj/chemical.dmi' - icon_state = "bottle16" - flags = OPENCONTAINER - possible_transfer_amounts = null - w_class = 2.0 - - var/fertilizer //Reagent contained, if any. - - //Like a shot glass! - amount_per_transfer_from_this = 10 - volume = 10 - -/obj/item/weapon/reagent_containers/glass/fertilizer/New() - ..() - - src.pixel_x = rand(-5.0, 5) - src.pixel_y = rand(-5.0, 5) - - if(fertilizer) - reagents.add_reagent(fertilizer,10) - -/obj/item/weapon/reagent_containers/glass/fertilizer/ez - name = "bottle of E-Z-Nutrient" - icon_state = "bottle16" - fertilizer = "eznutrient" - -/obj/item/weapon/reagent_containers/glass/fertilizer/l4z - name = "bottle of Left 4 Zed" - icon_state = "bottle18" - fertilizer = "left4zed" - -/obj/item/weapon/reagent_containers/glass/fertilizer/rh - name = "bottle of Robust Harvest" - icon_state = "bottle15" - fertilizer = "robustharvest" - //Hatchets and things to kill kudzu /obj/item/weapon/hatchet name = "hatchet" @@ -368,6 +285,15 @@ icon_state = "unathiknife" attack_verb = list("ripped", "torn", "cut") +/obj/item/weapon/hatchet/tacknife + name = "tactical knife" + desc = "You'd be killing loads of people if this was Medal of Valor: Heroes of Nyx." + icon = 'icons/obj/weapons.dmi' + icon_state = "tacknife" + item_state = "knife" + attack_verb = list("stabbed", "chopped", "cut") + + /obj/item/weapon/scythe icon_state = "scythe0" name = "scythe" @@ -384,8 +310,8 @@ /obj/item/weapon/scythe/afterattack(atom/A, mob/user as mob, proximity) if(!proximity) return - if(istype(A, /obj/effect/plantsegment)) - for(var/obj/effect/plantsegment/B in orange(A,1)) + if(istype(A, /obj/effect/plant)) + for(var/obj/effect/plant/B in orange(A,1)) if(prob(80)) - del B + B.die_off(1) del A \ No newline at end of file diff --git a/code/modules/hydroponics/trays/tray_update_icons.dm b/code/modules/hydroponics/trays/tray_update_icons.dm new file mode 100644 index 00000000000..61e19632ea1 --- /dev/null +++ b/code/modules/hydroponics/trays/tray_update_icons.dm @@ -0,0 +1,84 @@ +//Refreshes the icon and sets the luminosity +/obj/machinery/portable_atmospherics/hydroponics/update_icon() + // Update name. + if(seed) + if(mechanical) + name = "[base_name] (#[seed.uid])" + else + name = "[seed.seed_name]" + else + name = initial(name) + + if(labelled) + name += " ([labelled])" + + overlays.Cut() + // Updates the plant overlay. + if(!isnull(seed)) + + if(mechanical && health <= (seed.get_trait(TRAIT_ENDURANCE) / 2)) + overlays += "over_lowhealth3" + + if(dead) + var/ikey = "[seed.get_trait(TRAIT_PLANT_ICON)]-dead" + var/image/dead_overlay = plant_controller.plant_icon_cache["[ikey]"] + if(!dead_overlay) + dead_overlay = image('icons/obj/hydroponics_growing.dmi', "[ikey]") + dead_overlay.color = DEAD_PLANT_COLOUR + overlays |= dead_overlay + else + if(!seed.growth_stages) + seed.update_growth_stages() + if(!seed.growth_stages) + world << "Seed type [seed.get_trait(TRAIT_PLANT_ICON)] cannot find a growth stage value." + return + var/overlay_stage = 1 + if(age >= seed.get_trait(TRAIT_MATURATION)) + overlay_stage = seed.growth_stages + else + var/maturation = round(seed.get_trait(TRAIT_MATURATION)/seed.growth_stages) + overlay_stage = maturation ? max(1,round(age/maturation)) : 1 + var/ikey = "[seed.get_trait(TRAIT_PLANT_ICON)]-[overlay_stage]" + var/image/plant_overlay = plant_controller.plant_icon_cache["[ikey]-[seed.get_trait(TRAIT_PLANT_COLOUR)]"] + if(!plant_overlay) + plant_overlay = image('icons/obj/hydroponics_growing.dmi', "[ikey]") + plant_overlay.color = seed.get_trait(TRAIT_PLANT_COLOUR) + plant_controller.plant_icon_cache["[ikey]-[seed.get_trait(TRAIT_PLANT_COLOUR)]"] = plant_overlay + overlays |= plant_overlay + + if(harvest && overlay_stage == seed.growth_stages) + ikey = "[seed.get_trait(TRAIT_PRODUCT_ICON)]" + var/image/harvest_overlay = plant_controller.plant_icon_cache["product-[ikey]-[seed.get_trait(TRAIT_PLANT_COLOUR)]"] + if(!harvest_overlay) + harvest_overlay = image('icons/obj/hydroponics_products.dmi', "[ikey]") + harvest_overlay.color = seed.get_trait(TRAIT_PRODUCT_COLOUR) + plant_controller.plant_icon_cache["product-[ikey]-[seed.get_trait(TRAIT_PRODUCT_COLOUR)]"] = harvest_overlay + overlays |= harvest_overlay + + //Draw the cover. + if(closed_system) + overlays += "hydrocover" + + //Updated the various alert icons. + if(mechanical) + if(waterlevel <= 10) + overlays += "over_lowwater3" + if(nutrilevel <= 2) + overlays += "over_lownutri3" + if(weedlevel >= 5 || pestlevel >= 5 || toxins >= 40) + overlays += "over_alert3" + if(harvest) + overlays += "over_harvest3" + + // Update bioluminescence. + if(seed) + if(seed.get_trait(TRAIT_BIOLUM)) + SetLuminosity(round(seed.get_trait(TRAIT_POTENCY)/10)) + if(seed.get_trait(TRAIT_BIOLUM_COLOUR)) + l_color = seed.get_trait(TRAIT_BIOLUM_COLOUR) + else + l_color = null + return + + SetLuminosity(0) + return \ No newline at end of file diff --git a/code/modules/hydroponics/vines.dm b/code/modules/hydroponics/vines.dm deleted file mode 100644 index 90375ec98cc..00000000000 --- a/code/modules/hydroponics/vines.dm +++ /dev/null @@ -1,387 +0,0 @@ -// SPACE VINES (Note that this code is very similar to Biomass code) -/obj/effect/plantsegment - name = "space vines" - desc = "An extremely expansionistic species of vine." - icon = 'icons/effects/spacevines.dmi' - icon_state = "Light1" - anchored = 1 - density = 0 - layer = 5 - pass_flags = PASSTABLE | PASSGRILLE - - // Vars used by vines with seed data. - var/age = 0 - var/lastproduce = 0 - var/harvest = 0 - var/list/chems - var/plant_damage_noun = "Thorns" - var/limited_growth = 0 - - // Life vars/ - var/energy = 0 - var/obj/effect/plant_controller/master = null - var/mob/living/buckled_mob - var/datum/seed/seed - -/obj/effect/plantsegment/New() - return - -/obj/effect/plantsegment/Del() - if(master) - master.vines -= src - master.growth_queue -= src - ..() - -/obj/effect/plantsegment/attackby(obj/item/weapon/W as obj, mob/user as mob, params) - if (!W || !user || !W.type) return - switch(W.type) - if(/obj/item/weapon/circular_saw) del src - if(/obj/item/weapon/kitchen/utensil/knife) del src - if(/obj/item/weapon/scalpel) del src - if(/obj/item/weapon/twohanded/fireaxe) del src - if(/obj/item/weapon/hatchet) del src - if(/obj/item/weapon/melee/energy) del src - - // Less effective weapons - if(/obj/item/weapon/wirecutters) - if(prob(25)) del src - if(/obj/item/weapon/shard) - if(prob(25)) del src - - // Weapons with subtypes - else - if(istype(W, /obj/item/weapon/melee/energy/sword)) del src - else if(istype(W, /obj/item/weapon/weldingtool)) - var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0, user)) del src - else - manual_unbuckle(user) - return - // Plant-b-gone damage is handled in its entry in chemistry-reagents.dm - ..() - - -/obj/effect/plantsegment/attack_hand(mob/user as mob) - - if(user.a_intent == "help" && seed && harvest) - seed.harvest(user,1) - harvest = 0 - lastproduce = age - update() - return - - manual_unbuckle(user) - - -/obj/effect/plantsegment/attack_paw(mob/user as mob) - manual_unbuckle(user) - -/obj/effect/plantsegment/proc/unbuckle() - if(buckled_mob) - if(buckled_mob.buckled == src) //this is probably unneccesary, but it doesn't hurt - buckled_mob.buckled = null - buckled_mob.anchored = initial(buckled_mob.anchored) - buckled_mob.update_canmove() - buckled_mob = null - return - -/obj/effect/plantsegment/proc/manual_unbuckle(mob/user as mob) - if(buckled_mob) - if(prob(seed ? min(max(0,100 - seed.potency),100) : 50)) - if(buckled_mob.buckled == src) - if(buckled_mob != user) - buckled_mob.visible_message(\ - "[user.name] frees [buckled_mob.name] from [src].",\ - "[user.name] frees you from [src].",\ - "You hear shredding and ripping.") - else - buckled_mob.visible_message(\ - "[buckled_mob.name] struggles free of [src].",\ - "You untangle [src] from around yourself.",\ - "You hear shredding and ripping.") - unbuckle() - else - var/text = pick("rips","tears","pulls") - user.visible_message(\ - "[user.name] [text] at [src].",\ - "You [text] at [src].",\ - "You hear shredding and ripping.") - return - -/obj/effect/plantsegment/proc/grow() - - if(!energy) - src.icon_state = pick("Med1", "Med2", "Med3") - energy = 1 - - //Low-lying creepers do not block vision or grow thickly. - if(limited_growth) - energy = 2 - return - - src.opacity = 1 - layer = 5 - else if(!limited_growth) - src.icon_state = pick("Hvy1", "Hvy2", "Hvy3") - energy = 2 - -/obj/effect/plantsegment/proc/entangle_mob() - - if(limited_growth) - return - - if(prob(seed ? seed.potency : 25)) - - if(!buckled_mob) - var/mob/living/carbon/V = locate() in src.loc - if(V && (V.stat != DEAD) && (V.buckled != src)) // If mob exists and is not dead or captured. - V.buckled = src - V.loc = src.loc - V.update_canmove() - src.buckled_mob = V - V << "The vines [pick("wind", "tangle", "tighten")] around you!" - - // FEED ME, SEYMOUR. - if(buckled_mob && seed && (buckled_mob.stat != DEAD)) //Don't bother with a dead mob. - - var/mob/living/M = buckled_mob - if(!istype(M)) return - var/mob/living/carbon/human/H = buckled_mob - - // Drink some blood/cause some brute. - if(seed.carnivorous == 2) - buckled_mob << "\The [src] pierces your flesh greedily!" - - var/damage = rand(round(seed.potency/2),seed.potency) - if(!istype(H)) - H.adjustBruteLoss(damage) - return - - var/obj/item/organ/external/affecting = H.get_organ(pick("l_foot","r_foot","l_leg","r_leg","l_hand","r_hand","l_arm", "r_arm","head","chest","groin")) - - if(affecting) - affecting.take_damage(damage, 0) - if(affecting.parent) - affecting.parent.add_autopsy_data("[plant_damage_noun]", damage) - else - H.adjustBruteLoss(damage) - - H.UpdateDamageIcon() - H.updatehealth() - - // Inject some chems. - if(seed.chems && seed.chems.len && istype(H)) - H << "You feel something seeping into your skin!" - for(var/rid in seed.chems) - var/injecting = min(5,max(1,seed.potency/5)) - H.reagents.add_reagent(rid,injecting) - -/obj/effect/plantsegment/proc/update() - if(!seed) return - - // Update bioluminescence. - if(seed.biolum) - set_light(1+round(seed.potency/10)) - if(seed.biolum_colour) - light_color = seed.biolum_colour - else - light_color = null - return - else - set_light(0) - - // Update flower/product overlay. - overlays.Cut() - if(age >= seed.maturation) - if(prob(20) && seed.products && seed.products.len && !harvest && ((age-lastproduce) > seed.production)) - harvest = 1 - lastproduce = age - - if(harvest) - var/image/fruit_overlay = image('icons/obj/hydroponics.dmi',"") - if(seed.product_colour) - fruit_overlay.color = seed.product_colour - overlays += fruit_overlay - - if(seed.flowers) - var/image/flower_overlay = image('icons/obj/hydroponics.dmi',"[seed.flower_icon]") - if(seed.flower_colour) - flower_overlay.color = seed.flower_colour - overlays += flower_overlay - -/obj/effect/plantsegment/proc/spread() - var/direction = pick(cardinal) - var/step = get_step(src,direction) - if(istype(step,/turf/simulated/floor)) - var/turf/simulated/floor/F = step - if(!locate(/obj/effect/plantsegment,F)) - if(F.Enter(src)) - if(master) - master.spawn_piece( F ) - -// Explosion damage. -/obj/effect/plantsegment/ex_act(severity) - switch(severity) - if(1.0) - die() - return - if(2.0) - if (prob(90)) - die() - return - if(3.0) - if (prob(50)) - die() - return - return - -// Hotspots kill vines. -/obj/effect/plantsegment/fire_act(null, temp, volume) - del src - -/obj/effect/plantsegment/proc/die() - if(seed && harvest) - seed.harvest(src,1) - del(src) - -/obj/effect/plantsegment/proc/life() - - if(!seed) - return - - if(prob(30)) - age++ - - var/turf/T = loc - var/datum/gas_mixture/environment - if(T) environment = T.return_air() - - if(!environment) - return - - var/pressure = environment.return_pressure() - if(pressure < seed.lowkpa_tolerance || pressure > seed.highkpa_tolerance) - die() - return - - if(abs(environment.temperature - seed.ideal_heat) > seed.heat_tolerance) - die() - return - - var/area/A = T.loc - if(A) - var/atom/movable/lighting_overlay/L = locate(/atom/movable/lighting_overlay) in T - var/light_available - if(L) - light_available = max(0,min(10,L.lum_r + L.lum_g + L.lum_b)-5) - else - light_available = 5 - if(abs(light_available - seed.ideal_light) > seed.light_tolerance) - die() - return - -/obj/effect/plant_controller - - //What this does is that instead of having the grow minimum of 1, required to start growing, the minimum will be 0, - //meaning if you get the spacevines' size to something less than 20 plots, it won't grow anymore. - - var/list/obj/effect/plantsegment/vines = list() - var/list/growth_queue = list() - var/reached_collapse_size - var/reached_slowdown_size - var/datum/seed/seed - - var/collapse_limit = 250 - var/slowdown_limit = 30 - var/limited_growth = 0 - -/obj/effect/plant_controller/creeper - collapse_limit = 6 - slowdown_limit = 3 - limited_growth = 1 - -/obj/effect/plant_controller/New() - if(!istype(src.loc,/turf/simulated/floor)) - del(src) - - spawn(0) - spawn_piece(src.loc) - - processing_objects.Add(src) - -/obj/effect/plant_controller/Del() - processing_objects.Remove(src) - ..() - -/obj/effect/plant_controller/proc/spawn_piece(var/turf/location) - var/obj/effect/plantsegment/SV = new(location) - SV.limited_growth = src.limited_growth - growth_queue += SV - vines += SV - SV.master = src - if(seed) - SV.seed = seed - SV.name = "[seed.seed_name] vines" - SV.update() - -/obj/effect/plant_controller/process() - - // Space vines exterminated. Remove the controller - if(!vines) - del(src) - return - - // Sanity check. - if(!growth_queue) - del(src) - return - - // Check if we're too big for our own good. - if(vines.len >= (seed ? seed.potency * collapse_limit : 250) && !reached_collapse_size) - reached_collapse_size = 1 - if(vines.len >= (seed ? seed.potency * slowdown_limit : 30) && !reached_slowdown_size ) - reached_slowdown_size = 1 - - var/length = 0 - if(reached_collapse_size) - length = 0 - else if(reached_slowdown_size) - if(prob(seed ? seed.potency : 25)) - length = 1 - else - length = 0 - else - length = 1 - - length = min(30, max(length, vines.len/5)) - - // Update as many pieces of vine as we're allowed to. - // Append updated vines to the end of the growth queue. - var/i = 0 - var/list/obj/effect/plantsegment/queue_end = list() - for(var/obj/effect/plantsegment/SV in growth_queue) - i++ - queue_end += SV - growth_queue -= SV - - SV.life() - - if(SV.energy < 2) //If tile isn't fully grown - var/chance - if(seed) - chance = limited_growth ? round(seed.potency/2,1) : seed.potency - else - chance = 20 - - if(prob(chance)) - SV.grow() - - else if(!seed || !limited_growth) //If tile is fully grown and not just a creeper. - SV.entangle_mob() - - SV.update() - SV.spread() - if(i >= length) - break - - growth_queue = growth_queue + queue_end \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 6e5dcdc3dea..a2e7be0928d 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -152,6 +152,10 @@ bodytemperature += BODYTEMP_HEATING_MAX //If you're on fire, you heat up! return +/mob/living/carbon/alien/proc/handle_wetness() + if(mob_master.current_cycle%20==2) //dry off a bit once every 20 ticks or so + wetlevel = max(wetlevel - 1,0) + return /mob/living/carbon/alien/IsAdvancedToolUser() return has_fine_manipulation diff --git a/code/modules/mob/living/carbon/alien/humanoid/life.dm b/code/modules/mob/living/carbon/alien/humanoid/life.dm index eda8df77ee7..9ecf410a4d3 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/life.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/life.dm @@ -53,6 +53,9 @@ //Handle being on fire handle_fire() + //Decrease wetness over time + handle_wetness() + //Status updates, death etc. handle_regular_status_updates() update_canmove() diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 683228e97e8..5da86e83455 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -92,7 +92,6 @@ mob/living return return - /mob/living/carbon/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null) if(status_flags & GODMODE) //godmode return 0 diff --git a/code/modules/mob/living/carbon/carbon_defenses.dm b/code/modules/mob/living/carbon/carbon_defenses.dm index fddbd0d3cda..ab1c27ca2ee 100644 --- a/code/modules/mob/living/carbon/carbon_defenses.dm +++ b/code/modules/mob/living/carbon/carbon_defenses.dm @@ -14,4 +14,9 @@ visible_message("[src] catches [I]!") throw_mode_off() return + ..() + +/mob/living/carbon/water_act(volume, temperature, source) + if(volume > 10) //anything over 10 volume will make the mob wetter. + wetlevel = min(wetlevel + 1,5) ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index f9b61a3bd10..b6852c8a8dc 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -20,4 +20,5 @@ var/pulse = PULSE_NORM //current pulse level - var/heart_attack = 0 \ No newline at end of file + var/heart_attack = 0 + var/wetlevel = 0 //how wet the mob is \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index fac498d9219..00ec9e67181 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -231,6 +231,18 @@ if(fire_stacks < 0) msg += "[t_He] looks a little soaked.\n" + switch(wetlevel) + if(1) + msg += "[t_He] looks a bit damp.\n" + if(2) + msg += "[t_He] looks a little bit wet.\n" + if(3) + msg += "[t_He] looks wet.\n" + if(4) + msg += "[t_He] looks very wet.\n" + if(5) + msg += "[t_He] looks absolutely soaked.\n" + if(nutrition < 100) msg += "[t_He] [t_is] severely malnourished.\n" else if(nutrition >= 500) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 9d58b19f77f..3da342387ea 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -488,11 +488,16 @@ emp_act ..() return - + /mob/living/carbon/human/experience_pressure_difference(pressure_difference, direction) if(shoes) if(istype(shoes,/obj/item/clothing/shoes/magboots)) //TODO: Make a not-shit shoe var system to negate airflow. var/obj/item/clothing/shoes/magboots/MB = shoes if(MB.magpulse) return 0 - ..() \ No newline at end of file + ..() + +/mob/living/carbon/human/water_act(volume, temperature, source) + ..() + if(temperature >= 330) bodytemperature = bodytemperature + (temperature - bodytemperature) + if(temperature <= 280) bodytemperature = bodytemperature - (bodytemperature - temperature) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 48aa5fee4d4..3b2f984d6cc 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -108,6 +108,9 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc //Check if we're on fire handle_fire() + //Decrease wetness over time + handle_wetness() + //stuff in the stomach handle_stomach() @@ -547,6 +550,10 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc return //END FIRE CODE + proc/handle_wetness() + if(mob_master.current_cycle%20==2) //dry off a bit once every 20 ticks or so + wetlevel = max(wetlevel - 1,0) + return /* proc/adjust_body_temperature(current, loc_temp, boost) diff --git a/code/modules/mob/living/carbon/metroid/examine.dm b/code/modules/mob/living/carbon/metroid/examine.dm index f8fc23ad2e9..38087b35795 100644 --- a/code/modules/mob/living/carbon/metroid/examine.dm +++ b/code/modules/mob/living/carbon/metroid/examine.dm @@ -32,6 +32,20 @@ if(10) msg += "It is radiating with massive levels of electrical activity!\n" + msg += "" + switch(wetlevel) + if(1) + msg += "It looks a bit damp.\n" + if(2) + msg += "It looks a little bit wet.\n" + if(3) + msg += "It looks wet.\n" + if(4) + msg += "It looks very wet.\n" + if(5) + msg += "It looks absolutely soaked.\n" + msg += "" + msg += "*---------*" usr << msg return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/metroid/life.dm b/code/modules/mob/living/carbon/metroid/life.dm index 8b11c8a1b2f..afcb48726bd 100644 --- a/code/modules/mob/living/carbon/metroid/life.dm +++ b/code/modules/mob/living/carbon/metroid/life.dm @@ -42,6 +42,8 @@ handle_regular_status_updates() // Status updates, death etc. + handle_wetness() + /mob/living/carbon/slime/proc/AIprocess() // the master AI process if(AIproc || stat == DEAD || client) return @@ -285,6 +287,11 @@ else Evolve() +/mob/living/carbon/slime/proc/handle_wetness() + if(mob_master.current_cycle%20==2) //dry off a bit once every 20 ticks or so + wetlevel = max(wetlevel - 1,0) + return + /mob/living/carbon/slime/proc/handle_targets() if(Tempstun) if(!Victim) // not while they're eating! diff --git a/code/modules/mob/living/carbon/monkey/examine.dm b/code/modules/mob/living/carbon/monkey/examine.dm index 5cbb5c6c7ce..9c9d0ef5082 100644 --- a/code/modules/mob/living/carbon/monkey/examine.dm +++ b/code/modules/mob/living/carbon/monkey/examine.dm @@ -40,6 +40,20 @@ msg += "It isn't responding to anything around it; it seems to be asleep.\n" msg += "" + msg += "" + switch(wetlevel) + if(1) + msg += "It looks a bit damp.\n" + if(2) + msg += "It looks a little bit wet.\n" + if(3) + msg += "It looks wet.\n" + if(4) + msg += "It looks very wet.\n" + if(5) + msg += "It looks absolutely soaked.\n" + msg += "" + if (src.digitalcamo) msg += "It is repulsively uncanny!\n" diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index e2d7a25adfa..4c648244f61 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -62,6 +62,9 @@ //Check if we're on fire handle_fire() + //Decrease wetness over time + handle_wetness() + //Status updates, death etc. handle_regular_status_updates() update_canmove() @@ -661,4 +664,9 @@ return adjustFireLoss(6) return - //END FIRE CODE \ No newline at end of file + //END FIRE CODE + + proc/handle_wetness() + if(mob_master.current_cycle%20==2) //dry off a bit once every 20 ticks or so + wetlevel = max(wetlevel - 1,0) + return diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index e1715187d33..1af04f7de9a 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -238,6 +238,10 @@ //Mobs on Fire end +/mob/living/water_act(volume, temperature) + if(volume >= 20) fire_stacks -= 0.5 + if(volume >= 50) fire_stacks -= 1 + //This is called when the mob is thrown into a dense turf /mob/living/proc/turf_collision(var/turf/T, var/speed) src.take_organ_damage(speed*5) diff --git a/code/modules/mob/living/silicon/ai/laws.dm b/code/modules/mob/living/silicon/ai/laws.dm index 8e8ceb33c3f..c8670539eae 100755 --- a/code/modules/mob/living/silicon/ai/laws.dm +++ b/code/modules/mob/living/silicon/ai/laws.dm @@ -67,6 +67,7 @@ if("Engineering") prefix = ":e " if("Security") prefix = ":s " if("Supply") prefix = ":u " + if("Service") prefix = ":z " if("Binary") prefix = ":b " if("Holopad") prefix = ":h " else prefix = "" @@ -158,4 +159,4 @@ list += {"
Channel: [src.lawchannel]
"} list += {"State Laws"} - usr << browse(list, "window=laws") \ No newline at end of file + usr << browse(list, "window=laws") diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index 20c1259b857..dfeef3b004e 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -46,8 +46,8 @@ if(udder && prob(5)) udder.add_reagent("milk", rand(5, 10)) - if(locate(/obj/effect/plantsegment) in loc) - var/obj/effect/plantsegment/SV = locate(/obj/effect/plantsegment) in loc + if(locate(/obj/effect/plant) in loc) + var/obj/effect/plant/SV = locate(/obj/effect/plant) in loc del(SV) if(prob(10)) say("Nom") @@ -56,7 +56,7 @@ for(var/direction in shuffle(list(1,2,4,8,5,6,9,10))) var/step = get_step(src, direction) if(step) - if(locate(/obj/effect/plantsegment) in step) + if(locate(/obj/effect/plant) in step) Move(step) /mob/living/simple_animal/hostile/retaliate/goat/Retaliate() @@ -66,8 +66,8 @@ /mob/living/simple_animal/hostile/retaliate/goat/Move() ..() if(!stat) - if(locate(/obj/effect/plantsegment) in loc) - var/obj/effect/plantsegment/SV = locate(/obj/effect/plantsegment) in loc + if(locate(/obj/effect/plant) in loc) + var/obj/effect/plant/SV = locate(/obj/effect/plant) in loc del(SV) if(prob(10)) say("Nom") @@ -231,15 +231,19 @@ var/global/chicken_count = 0 chicken_count -= 1 /mob/living/simple_animal/chicken/attackby(var/obj/item/O as obj, var/mob/user as mob, params) - if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown/wheat)) //feedin' dem chickens - if(!stat && eggsleft < 8) - user.visible_message("\blue [user] feeds [O] to [name]! It clucks happily.","\blue You feed [O] to [name]! It clucks happily.") - user.drop_item() - del(O) - eggsleft += rand(1, 4) - //world << eggsleft + if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown)) //feedin' dem chickens + var/obj/item/weapon/reagent_containers/food/snacks/grown/G = O + if(G.seed.kitchen_tag == "wheat") + if(!stat && eggsleft < 8) + user.visible_message("\blue [user] feeds [O] to [name]! It clucks happily.","\blue You feed [O] to [name]! It clucks happily.") + user.drop_item() + del(O) + eggsleft += rand(1, 4) + //world << eggsleft + else + user << "\blue [name] doesn't seem hungry!" else - user << "\blue [name] doesn't seem hungry!" + user << "\blue [name] doesn't seem interested in [O]!" else ..() diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index 289c388b17b..b3ee7bb18a5 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -1008,19 +1008,8 @@ /obj/item/stack/sheet/mineral/clown = list("banana" = 20), /obj/item/stack/sheet/mineral/silver = list("silver" = 20), /obj/item/stack/sheet/mineral/gold = list("gold" = 20), - /obj/item/weapon/grown/nettle = list("sacid" = 0), - /obj/item/weapon/grown/deathnettle = list("facid" = 0), /obj/item/weapon/grown/novaflower = list("capsaicin" = 0), - //Blender Stuff - /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans = list("soymilk" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato = list("ketchup" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/corn = list("cornoil" = 0), - ///obj/item/weapon/reagent_containers/food/snacks/grown/wheat = list("flour" = -5), - /obj/item/weapon/reagent_containers/food/snacks/grown/ricestalk = list("rice" = -5), - /obj/item/weapon/reagent_containers/food/snacks/grown/cherries = list("cherryjelly" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/plastellium = list("plasticide" = 5), - //archaeology! /obj/item/weapon/rocksliver = list("ground_rock" = 50), @@ -1032,20 +1021,33 @@ /obj/item/weapon/reagent_containers/food = list() ) - var/list/juice_items = list ( + var/list/blend_tags = list ( + "nettle" = list("sacid" = 0), + "deathnettle" = list("facid" = 0), + "soybeans" = list("soymilk" = 0), + "tomato" = list("ketchup" = 0), + ///obj/item/weapon/reagent_containers/food/snacks/grown/wheat = list("flour" = -5), + "ricestalk" = list("rice" = -5), + "cherries" = list("cherryjelly" = 0), + "plastellium" = list("plasticide" = 5), + ) - //Juicer Stuff - /obj/item/weapon/reagent_containers/food/snacks/grown/tomato = list("tomatojuice" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/carrot = list("carrotjuice" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/berries = list("berryjuice" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/banana = list("banana" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/potato = list("potato" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/lemon = list("lemonjuice" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/orange = list("orangejuice" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/lime = list("limejuice" = 0), + var/list/juice_items = list ( /obj/item/weapon/reagent_containers/food/snacks/watermelonslice = list("watermelonjuice" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/poisonberries = list("poisonberryjuice" = 0), - /obj/item/weapon/reagent_containers/food/snacks/grown/grapes = list("grapejuice" = 0), + ) + + var/list/juice_tags = list ( + "tomato" = list("tomatojuice" = 0), + "carrot" = list("carrotjuice" = 0), + "berries" = list("berryjuice" = 0), + "banana" = list("banana" = 0), + "potato" = list("potato" = 0), + "lemon" = list("lemonjuice" = 0), + "orange" = list("orangejuice" = 0), + "lime" = list("limejuice" = 0), + "poisonberries" = list("poisonberryjuice" = 0), + "grapes" = list("grapejuice" = 0), + "corn" = list("cornoil" = 0), ) @@ -1223,10 +1225,20 @@ return blend_items[i] /obj/machinery/reagentgrinder/proc/get_allowed_juice_by_id(var/obj/item/weapon/reagent_containers/food/snacks/O) - for(var/i in juice_items) + for(var/i in juice_tags) if(istype(O, i)) return juice_items[i] +/obj/machinery/reagentgrinder/proc/get_allowed_snack_by_tag(var/obj/item/weapon/reagent_containers/food/snacks/grown/O) + for(var/i in blend_tags) + if(O.seed.kitchen_tag == i) + return blend_tags[i] + +/obj/machinery/reagentgrinder/proc/get_allowed_juice_by_tag(var/obj/item/weapon/reagent_containers/food/snacks/grown/O) + for(var/i in juice_tags) + if(O.seed.kitchen_tag == i) + return juice_tags[i] + /obj/machinery/reagentgrinder/proc/get_grownweapon_amount(var/obj/item/weapon/grown/O) if (!istype(O)) return 5 @@ -1263,7 +1275,11 @@ if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) break - var/allowed = get_allowed_juice_by_id(O) + var/allowed = null + if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown)) + allowed = get_allowed_juice_by_tag(O) + else + allowed = get_allowed_juice_by_id(O) if(isnull(allowed)) break @@ -1296,7 +1312,11 @@ if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume) break - var/allowed = get_allowed_snack_by_id(O) + var/allowed = null + if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown)) + allowed = get_allowed_snack_by_tag(O) + else + allowed = get_allowed_snack_by_id(O) if(isnull(allowed)) break diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm index f36b16e8f2a..fc2c8567525 100644 --- a/code/modules/reagents/Chemistry-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents.dm @@ -202,6 +202,16 @@ datum return */ + // Ported from Bay as part of the Botany Update + // Allows you to make planks from any plant that has this reagent in it. + // Also vines with this reagent are considered dense. + woodpulp + name = "Wood Pulp" + id = "woodpulp" + description = "A mass of wood fibers." + reagent_state = LIQUID + color = "#B97A57" + water name = "Water" id = "water" diff --git a/code/modules/reagents/newchem/toxins.dm b/code/modules/reagents/newchem/toxins.dm index b2779e42e4c..9cfa220198b 100644 --- a/code/modules/reagents/newchem/toxins.dm +++ b/code/modules/reagents/newchem/toxins.dm @@ -585,7 +585,7 @@ datum/reagent/atrazine/reaction_obj(var/obj/O, var/volume) alien_weeds.healthcheck() else if(istype(O,/obj/effect/glowshroom)) //even a small amount is enough to kill it del(O) - else if(istype(O,/obj/effect/plantsegment)) + else if(istype(O,/obj/effect/plant)) if(prob(50)) del(O) //Kills kudzu too. // Damage that is done to growing plants is separately at code/game/machinery/hydroponics at obj/item/hydroponics diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm index 8cc0229c548..6d332a5cbc1 100644 --- a/code/modules/reagents/reagent_containers/food/snacks.dm +++ b/code/modules/reagents/reagent_containers/food/snacks.dm @@ -1722,6 +1722,9 @@ M.gib() ..() + water_act(volume, temperature) + if(volume >= 5) return Expand() + proc/Expand() for(var/mob/M in viewers(src,7)) M << "\red \The [src] expands!" diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index ab00accccca..37d524c689c 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -46,7 +46,7 @@ category = list("Medical") /datum/design/healthanalyzer - name = "Health Analyzer Upgrade" + name = "Health Analyzer" desc = "A hand-held body scanner able to distinguish vital signs of the subject." id = "healthanalyzer" req_tech = list("biotech" = 2, "magnets" = 2) diff --git a/code/setup.dm b/code/setup.dm index ba72060d9f1..7d32ffa0679 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -964,6 +964,8 @@ var/list/hit_appends = list("-OOF", "-ACK", "-UGH", "-HRNK", "-HURGH", "-GLORF") #define STATUS_DISABLED 0 // RED Visability #define STATUS_CLOSE -1 // Close the interface +#define HYDRO_SPEED_MULTIPLIER 1 + #define NANO_IGNORE_DISTANCE 1 //Click cooldowns, in tenths of a second @@ -975,4 +977,4 @@ var/list/hit_appends = list("-OOF", "-ACK", "-UGH", "-HRNK", "-HURGH", "-GLORF") #define CLICK_CD_POINT 10 #define CLICK_CD_RESIST 20 -#define CLAMP01(x) max(0, min(1, x)) \ No newline at end of file +#define CLAMP01(x) max(0, min(1, x)) diff --git a/code/world.dm b/code/world.dm index e890c6164eb..0ed1f72ced8 100644 --- a/code/world.dm +++ b/code/world.dm @@ -41,6 +41,7 @@ sleep_offline = 1 + plant_controller = new() // Create robolimbs for chargen. populate_robolimb_list() diff --git a/icons/obj/cigarettes.dmi b/icons/obj/cigarettes.dmi index 89f3d1bdac8..7b6275972c0 100644 Binary files a/icons/obj/cigarettes.dmi and b/icons/obj/cigarettes.dmi differ diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi index 7df20eeb250..09247ec05ea 100644 Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ diff --git a/icons/obj/hydroponics_growing.dmi b/icons/obj/hydroponics_growing.dmi new file mode 100644 index 00000000000..5b4fc62baa6 Binary files /dev/null and b/icons/obj/hydroponics_growing.dmi differ diff --git a/icons/obj/hydroponics_machines.dmi b/icons/obj/hydroponics_machines.dmi new file mode 100644 index 00000000000..3373d03152f Binary files /dev/null and b/icons/obj/hydroponics_machines.dmi differ diff --git a/icons/obj/hydroponics_products.dmi b/icons/obj/hydroponics_products.dmi new file mode 100644 index 00000000000..b02a15b309a Binary files /dev/null and b/icons/obj/hydroponics_products.dmi differ diff --git a/icons/obj/hydroponics_vines.dmi b/icons/obj/hydroponics_vines.dmi new file mode 100644 index 00000000000..2bad94b350d Binary files /dev/null and b/icons/obj/hydroponics_vines.dmi differ diff --git a/icons/obj/seeds.dmi b/icons/obj/seeds.dmi index 5c2cbe7868b..530683ef9bf 100644 Binary files a/icons/obj/seeds.dmi and b/icons/obj/seeds.dmi differ diff --git a/icons/obj/seeds_OLD.dmi b/icons/obj/seeds_OLD.dmi new file mode 100644 index 00000000000..98eb6e2292b Binary files /dev/null and b/icons/obj/seeds_OLD.dmi differ diff --git a/paradise.dme b/paradise.dme index d15a1e00d3e..883255595e1 100644 --- a/paradise.dme +++ b/paradise.dme @@ -371,7 +371,6 @@ #include "code\game\machinery\guestpass.dm" #include "code\game\machinery\hologram.dm" #include "code\game\machinery\holosign.dm" -#include "code\game\machinery\hydroponics.dm" #include "code\game\machinery\igniter.dm" #include "code\game\machinery\iv_drip.dm" #include "code\game\machinery\lightswitch.dm" @@ -1085,12 +1084,9 @@ #include "code\modules\food\recipes_oven.dm" #include "code\modules\genetics\side_effects.dm" #include "code\modules\hydroponics\grown_inedible.dm" -#include "code\modules\hydroponics\hydro_tools.dm" #include "code\modules\hydroponics\seed_datums.dm" #include "code\modules\hydroponics\seed_machines.dm" #include "code\modules\hydroponics\seed_mobs.dm" -#include "code\modules\hydroponics\seeds.dm" -#include "code\modules\hydroponics\vines.dm" #include "code\modules\jungle\falsewall.dm" #include "code\modules\jungle\jungle.dm" #include "code\modules\jungle\jungle_animals.dm"
Endurance[grown_seed.endurance]
Yield[grown_seed.yield]
Lifespan[grown_seed.lifespan]
Maturation time[grown_seed.maturation]
Production time[grown_seed.production]
Potency[grown_seed.potency]
Endurance[grown_seed.get_trait(TRAIT_ENDURANCE)]
Yield[grown_seed.get_trait(TRAIT_YIELD)]
Maturation time[grown_seed.get_trait(TRAIT_MATURATION)]
Production time[grown_seed.get_trait(TRAIT_PRODUCTION)]
Potency[grown_seed.get_trait(TRAIT_POTENCY)]