mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-19 19:13:30 +01:00
Merge remote-tracking branch 'upstream/master' into LightShit
Conflicts: code/modules/hydroponics/trays/tray.dm code/modules/hydroponics/vines.dm
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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 << "<span class='danger'>Plant controller does not exist and [src] requires it. Aborting.</span>"
|
||||
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 << "<span class='danger'>Plant controller does not exist and [src] requires it. Aborting.</span>"
|
||||
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 << "<span class='notice'>You slipped on the [name]!</span>"
|
||||
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 << "<span class='notice'>You add some cable to the [src.name] and slide it inside the battery casing.</span>"
|
||||
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("<span class='notice'>You carve a face into [src]!</span>", 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("<span class='notice'>You make planks out of \the [src]!</span>", 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()]\]<font color='red'> Attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
|
||||
M.attack_log += "\[[time_stamp()]\]<font color='orange'> Attacked by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])</font>"
|
||||
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("<span class='danger'>[M] has been [pick(attack_verb)] with [src] by [user]!</span>")
|
||||
else
|
||||
user.visible_message("<span class='danger'>[M] has been attacked with [src] by [user]!</span>")
|
||||
|
||||
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 << "<span class='danger'>\The [src] has fallen to bits.</span>"
|
||||
//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("<span class='danger'>\The [user] squashes \the [src]!</span>")
|
||||
seed.thrown_at(src,user)
|
||||
sleep(-1)
|
||||
if(src) del(src)
|
||||
return
|
||||
|
||||
if(seed.kitchen_tag == "grass")
|
||||
user.show_message("<span class='notice'>You make a grass tile out of \the [src]!</span>", 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 << "<span class='notice'>You plant the [src.name].</span>"
|
||||
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 << "<span class='notice'>You mash the leaves into a poultice.</span>"
|
||||
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 << "<span class='notice'>You mash the petals into a poultice.</span>"
|
||||
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))
|
||||
@@ -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("<span class='notice'>You make planks out of \the [src]!</span>", 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 << "<font color='green'><b> [user] smacks you with a sunflower!</font><font color='yellow'><b>FLOWER POWER<b></font>"
|
||||
user << "<font color='green'> Your sunflower's </font><font color='yellow'><b>FLOWER POWER</b></font><font color='green'> strikes [M]</font>"
|
||||
|
||||
/obj/item/weapon/grown/nettle // -- Skie
|
||||
plantname = "nettle"
|
||||
desc = "It's probably <B>not</B> 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 <b>[user] is eating some of the [src.name]! It looks like \he's trying to commit suicide.</b>"
|
||||
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()]\] <font color='orange'>Had the [src.name] used on them by [user.name] ([user.ckey])</font>")
|
||||
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Used the [src.name] on [M.name] ([M.ckey])</font>")
|
||||
msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] used the [src.name] on [M.name] ([M.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)")
|
||||
|
||||
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 << "<span class='notice'>You use [W] to fashion a pipe out of the corn cob!</span>"
|
||||
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
|
||||
|
||||
@@ -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"
|
||||
@@ -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 << "<span class='danger'>\The [fruit]'s thorns pierce your [affecting.name] greedily!</span>"
|
||||
else
|
||||
target << "<span class='danger'>\The [fruit]'s thorns pierce your flesh greedily!</span>"
|
||||
damage = get_trait(TRAIT_POTENCY)/2
|
||||
else
|
||||
if(affecting)
|
||||
target << "<span class='danger'>\The [fruit]'s thorns dig deeply into your [affecting.name]!</span>"
|
||||
else
|
||||
target << "<span class='danger'>\The [fruit]'s thorns dig deeply into your flesh!</span>"
|
||||
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 << "<span class='danger'>You are stung by \the [fruit]!</span>"
|
||||
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("<span class='danger'>The [thrown.name] explodes!</span>")
|
||||
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("<span class='danger'>The [thrown.name] splatters against [target]!</span>")
|
||||
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("<span class='notice'>\The [display_name] quivers!</span>")
|
||||
|
||||
//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<total_mutations;i++)
|
||||
switch(rand(0,11))
|
||||
if(0) //Plant cancer!
|
||||
set_trait(TRAIT_ENDURANCE,get_trait(TRAIT_ENDURANCE)-rand(10,20),null,0)
|
||||
source_turf.visible_message("<span class='danger'>\The [display_name] withers rapidly!</span>")
|
||||
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("<span class='notice'>\The [display_name] shudders hungrily.</span>")
|
||||
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("<span class='notice'>\The [display_name] spasms visibly, shifting in the tray.</span>")
|
||||
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("<span class='notice'>\The [display_name] begins to glow!</span>")
|
||||
if(prob(degree*2))
|
||||
set_trait(TRAIT_BIOLUM_COLOUR,"#[get_random_colour(0,75,190)]")
|
||||
source_turf.visible_message("<span class='notice'>\The [display_name]'s glow </span><font color='[get_trait(TRAIT_BIOLUM_COLOUR)]'>changes colour</font>!")
|
||||
else
|
||||
source_turf.visible_message("<span class='notice'>\The [display_name]'s glow dims...</span>")
|
||||
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 << "<span class='danger'>You fail to harvest anything useful.</span>"
|
||||
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;i<total_yield;i++)
|
||||
var/obj/item/product
|
||||
if(has_mob_product)
|
||||
product = new has_mob_product(get_turf(user),name)
|
||||
else
|
||||
product = new /obj/item/weapon/reagent_containers/food/snacks/grown(get_turf(user),name)
|
||||
if(get_trait(TRAIT_PRODUCT_COLOUR))
|
||||
product.color = get_trait(TRAIT_PRODUCT_COLOUR)
|
||||
if(istype(product,/obj/item/weapon/reagent_containers/food))
|
||||
var/obj/item/weapon/reagent_containers/food/food = product
|
||||
food.filling_color = get_trait(TRAIT_PRODUCT_COLOUR)
|
||||
|
||||
if(mysterious)
|
||||
product.name += "?"
|
||||
product.desc += " On second thought, something about this one looks strange."
|
||||
|
||||
if(get_trait(TRAIT_BIOLUM))
|
||||
if(get_trait(TRAIT_BIOLUM_COLOUR))
|
||||
product.l_color = get_trait(TRAIT_BIOLUM_COLOUR)
|
||||
product.SetLuminosity(get_trait(TRAIT_BIOLUM))
|
||||
|
||||
//Handle spawning in living, mobile products (like dionaea).
|
||||
if(istype(product,/mob/living))
|
||||
product.visible_message("<span class='notice'>The pod disgorges [product]!</span>")
|
||||
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
|
||||
@@ -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]<ikey))
|
||||
plant_sprites[base] = ikey
|
||||
|
||||
for(var/icostate in icon_states('icons/obj/hydroponics_products.dmi'))
|
||||
var/split = findtext(icostate,"-")
|
||||
if(split)
|
||||
plant_product_sprites |= copytext(icostate,1,split)
|
||||
|
||||
// Populate the global seed datum list.
|
||||
for(var/type in typesof(/datum/seed)-/datum/seed)
|
||||
var/datum/seed/S = new type
|
||||
seeds[S.name] = S
|
||||
S.uid = "[seeds.len]"
|
||||
S.roundstart = 1
|
||||
|
||||
// Make sure any seed packets that were mapped in are updated
|
||||
// correctly (since the seed datums did not exist a tick ago).
|
||||
for(var/obj/item/seeds/S in world)
|
||||
S.update_seed()
|
||||
|
||||
//Might as well mask the gene types while we're at it.
|
||||
var/list/used_masks = list()
|
||||
var/list/plant_traits = ALL_GENES
|
||||
while(plant_traits && plant_traits.len)
|
||||
var/gene_tag = pick(plant_traits)
|
||||
var/gene_mask = "[uppertext(num2hex(rand(0,255)))]"
|
||||
|
||||
while(gene_mask in used_masks)
|
||||
gene_mask = "[uppertext(num2hex(rand(0,255)))]"
|
||||
|
||||
used_masks += gene_mask
|
||||
plant_traits -= gene_tag
|
||||
gene_tag_masks[gene_tag] = gene_mask
|
||||
|
||||
// Proc for creating a random seed type.
|
||||
/datum/controller/plants/proc/create_random_seed(var/survive_on_station)
|
||||
var/datum/seed/seed = new()
|
||||
seed.randomize()
|
||||
seed.uid = plant_controller.seeds.len + 1
|
||||
seed.name = "[seed.uid]"
|
||||
seeds[seed.name] = seed
|
||||
|
||||
if(survive_on_station)
|
||||
if(seed.consume_gasses)
|
||||
seed.consume_gasses["plasma"] = null
|
||||
seed.consume_gasses["carbon_dioxide"] = null
|
||||
if(seed.chems && !isnull(seed.chems["pacid"]))
|
||||
seed.chems["pacid"] = null // Eating through the hull will make these plants completely inviable, albeit very dangerous.
|
||||
seed.chems -= null // Setting to null does not actually remove the entry, which is weird.
|
||||
seed.set_trait(TRAIT_IDEAL_HEAT,293)
|
||||
seed.set_trait(TRAIT_HEAT_TOLERANCE,20)
|
||||
seed.set_trait(TRAIT_IDEAL_LIGHT,8)
|
||||
seed.set_trait(TRAIT_LIGHT_TOLERANCE,5)
|
||||
seed.set_trait(TRAIT_LOWKPA_TOLERANCE,25)
|
||||
seed.set_trait(TRAIT_HIGHKPA_TOLERANCE,200)
|
||||
return seed
|
||||
|
||||
/datum/controller/plants/proc/process()
|
||||
processing = 1
|
||||
spawn(0)
|
||||
set background = 1
|
||||
var/processed = 0
|
||||
while(1)
|
||||
if(!processing)
|
||||
sleep(plant_tick_time)
|
||||
else
|
||||
processed = 0
|
||||
if(plant_queue.len)
|
||||
var/target_to_process = min(plant_queue.len,plants_per_tick)
|
||||
for(var/x=0;x<target_to_process;x++)
|
||||
if(!plant_queue.len)
|
||||
break
|
||||
var/obj/effect/plant/plant = pick(plant_queue)
|
||||
plant_queue -= plant
|
||||
if(!istype(plant))
|
||||
continue
|
||||
plant.process()
|
||||
processed++
|
||||
sleep(1) // Stagger processing out so previous tick can resolve (overlapping plant segments etc)
|
||||
sleep(max(1,(plant_tick_time-processed)))
|
||||
|
||||
/datum/controller/plants/proc/add_plant(var/obj/effect/plant/plant)
|
||||
plant_queue |= plant
|
||||
|
||||
/datum/controller/plants/proc/remove_plant(var/obj/effect/plant/plant)
|
||||
plant_queue -= plant
|
||||
+834
-1164
File diff suppressed because it is too large
Load Diff
@@ -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 << "<span class='notice'>You [open ? "open" : "close"] the maintenance panel.</span>"
|
||||
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)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
@@ -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 <b>[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("<span class='danger'>[host] is malformed and unable to survive. It expires pitifully, leaving behind some seeds.</span>")
|
||||
|
||||
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 <B>You awaken slowly, stirring into sluggish motion as the air caresses you.</B>"
|
||||
|
||||
// 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 << "<B>You are [host], one of a race of drifting interstellar plantlike creatures that sometimes share their seeds with human traders.</B>"
|
||||
host << "<B>Too much darkness will send you into shock and starve you, but light will help you heal.</B>"
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 = "<center><h1>Seed storage contents</h1></center>"
|
||||
if (piles.len == 0)
|
||||
dat += "<font color='red'>No seeds</font>"
|
||||
else
|
||||
dat += "<table style='text-align:center;border-style:solid;border-width:1px;padding:4px'><tr><td>Name</td>"
|
||||
dat += "<td>Variety</td>"
|
||||
if ("stats" in scanner)
|
||||
dat += "<td>E</td><td>Y</td><td>M</td><td>Pr</td><td>Pt</td><td>Harvest</td>"
|
||||
if ("temperature" in scanner)
|
||||
dat += "<td>Temp</td>"
|
||||
if ("light" in scanner)
|
||||
dat += "<td>Light</td>"
|
||||
if ("soil" in scanner)
|
||||
dat += "<td>Nutri</td><td>Water</td>"
|
||||
dat += "<td>Notes</td><td>Amount</td><td></td></tr>"
|
||||
for (var/datum/seed_pile/S in piles)
|
||||
var/datum/seed/seed = S.seed_type
|
||||
if(!seed)
|
||||
continue
|
||||
dat += "<tr>"
|
||||
dat += "<td>[seed.seed_name]</td>"
|
||||
dat += "<td>#[seed.uid]</td>"
|
||||
if ("stats" in scanner)
|
||||
dat += "<td>[seed.get_trait(TRAIT_ENDURANCE)]</td><td>[seed.get_trait(TRAIT_YIELD)]</td><td>[seed.get_trait(TRAIT_MATURATION)]</td><td>[seed.get_trait(TRAIT_PRODUCTION)]</td><td>[seed.get_trait(TRAIT_POTENCY)]</td>"
|
||||
if(seed.get_trait(TRAIT_HARVEST_REPEAT))
|
||||
dat += "<td>Multiple</td>"
|
||||
else
|
||||
dat += "<td>Single</td>"
|
||||
if ("temperature" in scanner)
|
||||
dat += "<td>[seed.get_trait(TRAIT_IDEAL_HEAT)] K</td>"
|
||||
if ("light" in scanner)
|
||||
dat += "<td>[seed.get_trait(TRAIT_IDEAL_LIGHT)] L</td>"
|
||||
if ("soil" in scanner)
|
||||
if(seed.get_trait(TRAIT_REQUIRES_NUTRIENTS))
|
||||
if(seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) < 0.05)
|
||||
dat += "<td>Low</td>"
|
||||
else if(seed.get_trait(TRAIT_REQUIRES_NUTRIENTS) > 0.2)
|
||||
dat += "<td>High</td>"
|
||||
else
|
||||
dat += "<td>Norm</td>"
|
||||
else
|
||||
dat += "<td>No</td>"
|
||||
if(seed.get_trait(TRAIT_REQUIRES_WATER))
|
||||
if(seed.get_trait(TRAIT_WATER_CONSUMPTION) < 1)
|
||||
dat += "<td>Low</td>"
|
||||
else if(seed.get_trait(TRAIT_WATER_CONSUMPTION) > 5)
|
||||
dat += "<td>High</td>"
|
||||
else
|
||||
dat += "<td>Norm</td>"
|
||||
else
|
||||
dat += "<td>No</td>"
|
||||
|
||||
dat += "<td>"
|
||||
switch(seed.get_trait(TRAIT_CARNIVOROUS))
|
||||
if(1)
|
||||
dat += "CARN "
|
||||
if(2)
|
||||
dat += "<font color='red'>CARN </font>"
|
||||
switch(seed.get_trait(TRAIT_SPREAD))
|
||||
if(1)
|
||||
dat += "VINE "
|
||||
if(2)
|
||||
dat += "<font color='red'>VINE </font>"
|
||||
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 += "</td>"
|
||||
dat += "<td>[S.amount]</td>"
|
||||
dat += "<td><a href='byond://?src=\ref[src];task=vend;id=[S.ID]'>Vend</a> <a href='byond://?src=\ref[src];task=purge;id=[S.ID]'>Purge</a></td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
|
||||
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 << "<span class='notice'>There are no seeds in \the [O.name].</span>"
|
||||
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
|
||||
@@ -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("<span class='notice'>Event: Spacevines spawned at [T.loc] ([T.x],[T.y],[T.z])</span>")
|
||||
|
||||
/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 << "<span class='danger'>Plant controller does not exist and [src] requires it. Aborting.</span>"
|
||||
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))
|
||||
@@ -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
|
||||
@@ -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(\
|
||||
"<span class='notice'>[user.name] frees [buckled_mob.name] from \the [src].</span>",\
|
||||
"<span class='notice'>[user.name] frees you from \the [src].</span>",\
|
||||
"<span class='warning'>You hear shredding and ripping.</span>")
|
||||
else
|
||||
buckled_mob.visible_message(\
|
||||
"<span class='notice'>[buckled_mob.name] struggles free of \the [src].</span>",\
|
||||
"<span class='notice'>You untangle \the [src] from around yourself.</span>",\
|
||||
"<span class='warning'>You hear shredding and ripping.</span>")
|
||||
unbuckle()
|
||||
else
|
||||
var/text = pick("rip","tear","pull")
|
||||
user.visible_message(\
|
||||
"<span class='notice'>[user.name] [text]s at \the [src].</span>",\
|
||||
"<span class='notice'>You [text] at \the [src].</span>",\
|
||||
"<span class='warning'>You hear shredding and ripping.</span>")
|
||||
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("<span class='danger'>Tendrils lash out from \the [src] and drag \the [victim] in!</span>")
|
||||
victim.loc = src.loc
|
||||
victim << "<span class='danger'>Tendrils [pick("wind", "tangle", "tighten")] around you!</span>"
|
||||
@@ -0,0 +1,832 @@
|
||||
/obj/machinery/portable_atmospherics/hydroponics
|
||||
name = "hydroponics tray"
|
||||
icon = 'icons/obj/hydroponics_machines.dmi'
|
||||
icon_state = "hydrotray3"
|
||||
density = 1
|
||||
anchored = 1
|
||||
flags = OPENCONTAINER
|
||||
volume = 100
|
||||
|
||||
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)
|
||||
var/maxwater = 100
|
||||
var/nutrilevel = 10 // Nutrient level (max 10)
|
||||
var/maxnutri = 10
|
||||
var/pestlevel = 0 // Pests (max 10)
|
||||
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.
|
||||
var/lastproduce = 0 // Last time tray was harvested
|
||||
var/lastcycle = 0 // Cycle timing/tracking var.
|
||||
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
|
||||
|
||||
// Construction
|
||||
var/unwrenchable = 1
|
||||
|
||||
// Reagent information for process(), consider moving this to a controller along
|
||||
// with cycle information under 'mechanical concerns' at some point.
|
||||
var/global/list/toxic_reagents = list(
|
||||
"charcoal" = -2,
|
||||
"toxin" = 2,
|
||||
"fluorine" = 2.5,
|
||||
"chlorine" = 1.5,
|
||||
"sacid" = 1.5,
|
||||
"facid" = 3,
|
||||
"atrazine" = 3,
|
||||
"cryoxadone" = -3,
|
||||
"radium" = 2
|
||||
)
|
||||
var/global/list/nutrient_reagents = list(
|
||||
"milk" = 0.1,
|
||||
"beer" = 0.25,
|
||||
"phosphorus" = 0.1,
|
||||
"sugar" = 0.1,
|
||||
"sodawater" = 0.1,
|
||||
"ammonia" = 1,
|
||||
"diethylamine" = 2,
|
||||
"nutriment" = 1,
|
||||
"adminordrazine" = 1,
|
||||
"eznutrient" = 1,
|
||||
"robustharvest" = 1,
|
||||
"left4zed" = 1
|
||||
)
|
||||
var/global/list/weedkiller_reagents = list(
|
||||
"fluorine" = -4,
|
||||
"chlorine" = -3,
|
||||
"phosphorus" = -2,
|
||||
"sugar" = 2,
|
||||
"sacid" = -2,
|
||||
"facid" = -4,
|
||||
"atrazine" = -8,
|
||||
"adminordrazine" = -5
|
||||
)
|
||||
var/global/list/pestkiller_reagents = list(
|
||||
"sugar" = 2,
|
||||
"diethylamine" = -2,
|
||||
"adminordrazine" = -5
|
||||
)
|
||||
var/global/list/water_reagents = list(
|
||||
"water" = 1,
|
||||
"adminordrazine" = 1,
|
||||
"milk" = 0.9,
|
||||
"beer" = 0.7,
|
||||
"fluorine" = -0.5,
|
||||
"chlorine" = -0.5,
|
||||
"phosphorus" = -0.5,
|
||||
"water" = 1,
|
||||
"sodawater" = 1,
|
||||
)
|
||||
|
||||
// Beneficial reagents also have values for modifying yield_mod and mut_mod (in that order).
|
||||
var/global/list/beneficial_reagents = list(
|
||||
// "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
|
||||
// Mutagen list specifies reagent_min_value and reagent_step
|
||||
// Reagent_min_value (value 1) is the minimum number of units needed to begin mutations
|
||||
// Reagent_step (value 2) is the number of units between each mutation threshold
|
||||
var/global/list/mutagenic_reagents = list(
|
||||
"radium" = list(10,10),
|
||||
"mutagen" = list(1,5)
|
||||
)
|
||||
//--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("<font color='blue'><b>[nymph]</b> begins rooting through [src], ripping out weeds and eating them noisily.</font>","<font color='blue'>You begin rooting through [src], ripping out weeds and eating them noisily.</font>")
|
||||
else if(nymph.nutrition > 100 && nutrilevel < 10)
|
||||
nymph.nutrition -= ((10-nutrilevel)*5)
|
||||
nutrilevel = 10
|
||||
nymph.visible_message("<font color='blue'><b>[nymph]</b> secretes a trickle of green liquid, refilling [src].</font>","<font color='blue'>You secrete a trickle of green liquid, refilling [src].</font>")
|
||||
else
|
||||
nymph.visible_message("<font color='blue'><b>[nymph]</b> rolls around in [src] for a bit.</font>","<font color='blue'>You roll around in [src] for a bit.</font>")
|
||||
return
|
||||
|
||||
/obj/machinery/portable_atmospherics/hydroponics/New()
|
||||
..()
|
||||
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/weapon/circuitboard/hydroponics(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
|
||||
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()
|
||||
if(closed_system)
|
||||
flags &= ~OPENCONTAINER
|
||||
|
||||
/obj/machinery/portable_atmospherics/hydroponics/upgraded/New()
|
||||
..()
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/weapon/circuitboard/hydroponics(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin/super(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin/super(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/portable_atmospherics/hydroponics/RefreshParts()
|
||||
var/tmp_capacity = 0
|
||||
for (var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
|
||||
tmp_capacity += M.rating
|
||||
maxwater = tmp_capacity * 50 // Up to 300
|
||||
maxnutri = tmp_capacity * 5 // Up to 30
|
||||
//waterlevel = maxwater
|
||||
//nutrilevel = 3
|
||||
|
||||
/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.get_trait(TRAIT_IMMUTABLE) > 0)
|
||||
return
|
||||
|
||||
//--FalseIncarnate
|
||||
//Override for somatoray projectiles, updated to work with new mutation rework
|
||||
if(istype(Proj ,/obj/item/projectile/energy/floramut))
|
||||
mutate("F1")
|
||||
return
|
||||
else if(istype(Proj ,/obj/item/projectile/energy/florayield))
|
||||
mutate("F2")
|
||||
return
|
||||
//--FalseIncarnate
|
||||
|
||||
..()
|
||||
|
||||
/obj/machinery/portable_atmospherics/hydroponics/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/portable_atmospherics/hydroponics/proc/check_health()
|
||||
if(seed && !dead && health <= 0)
|
||||
die()
|
||||
check_level_sanity()
|
||||
update_icon()
|
||||
|
||||
/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()
|
||||
|
||||
if(!reagents) return
|
||||
|
||||
if(reagents.total_volume <= 0)
|
||||
return
|
||||
|
||||
/* 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)
|
||||
|
||||
if(seed && !dead)
|
||||
//Handle some general level adjustments.
|
||||
if(toxic_reagents[R.id])
|
||||
toxins += toxic_reagents[R.id] * reagent_total
|
||||
if(weedkiller_reagents[R.id])
|
||||
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))
|
||||
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.
|
||||
|
||||
//--FalseIncarnate
|
||||
// Mutation rework, will now use "thresholds" for proccing types of mutations and their respective chances.
|
||||
// This should make it easier to avoid species shifts when trying to only affect stats like potency.
|
||||
// Additionally, the chance of mutations will vary depending on the amount of mutagenic reagents added.
|
||||
if(mutagenic_reagents[R.id])
|
||||
var/reagent_min_value = mutagenic_reagents[R.id][1] //10 for radium, 1 for unstable mutagen
|
||||
var/reagent_step = mutagenic_reagents[R.id][2] //10 for radium, 5 for unstable mutagen
|
||||
|
||||
if(reagent_total >= reagent_min_value + (3 * reagent_step)) //31+ for radium, 16+ for unstable mutagen
|
||||
mutate(4)
|
||||
else if(reagent_total >= reagent_min_value + (2 * reagent_step)) //21-30 for radium, 11-15 for unstable mutagen
|
||||
mutate(3)
|
||||
else if(reagent_total >= reagent_min_value + reagent_step) //11-20 for radium, 6-10 for unstable mutagen
|
||||
mutate(2)
|
||||
else if(reagent_total >= reagent_min_value) //1-10 for radium, 1-5 for unstable mutagen
|
||||
mutate(1)
|
||||
|
||||
//--FalseIncarnate
|
||||
|
||||
// Handle nutrient refilling.
|
||||
if(nutrient_reagents[R.id])
|
||||
nutrilevel += nutrient_reagents[R.id] * reagent_total
|
||||
|
||||
// Handle water and water refilling.
|
||||
var/water_added = 0
|
||||
if(water_reagents[R.id])
|
||||
var/water_input = water_reagents[R.id] * reagent_total
|
||||
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_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)
|
||||
return
|
||||
|
||||
if(closed_system)
|
||||
if(user) user << "You can't harvest from the plant while the lid is shut."
|
||||
return
|
||||
|
||||
if(user)
|
||||
seed.harvest(user,yield_mod)
|
||||
else
|
||||
seed.harvest(get_turf(src),yield_mod)
|
||||
|
||||
// Reset values.
|
||||
harvest = 0
|
||||
lastproduce = age
|
||||
|
||||
if(!seed.get_trait(TRAIT_HARVEST_REPEAT))
|
||||
yield_mod = 0
|
||||
seed = null
|
||||
dead = 0
|
||||
age = 0
|
||||
sampled = 0
|
||||
mutation_mod = 0
|
||||
|
||||
check_health()
|
||||
return
|
||||
|
||||
//Clears out a dead plant.
|
||||
/obj/machinery/portable_atmospherics/hydroponics/proc/remove_dead(var/mob/user)
|
||||
if(!user || !dead) return
|
||||
|
||||
if(closed_system)
|
||||
user << "You can't remove the dead plant while the lid is shut."
|
||||
return
|
||||
|
||||
seed = null
|
||||
dead = 0
|
||||
|
||||
sampled = 0
|
||||
age = 0
|
||||
yield_mod = 0
|
||||
mutation_mod = 0
|
||||
|
||||
user << "You remove the dead plant."
|
||||
check_health()
|
||||
return
|
||||
|
||||
// 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 = 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.get_trait(TRAIT_ENDURANCE)
|
||||
lastcycle = world.time
|
||||
harvest = 0
|
||||
weedlevel = 0
|
||||
pestlevel = 0
|
||||
sampled = 0
|
||||
update_icon()
|
||||
visible_message("<span class='notice'>[src] has been overtaken by [seed.display_name].</span>")
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/portable_atmospherics/hydroponics/proc/mutate(var/severity)
|
||||
|
||||
// No seed, no mutations.
|
||||
if(!seed)
|
||||
return
|
||||
|
||||
/*
|
||||
--FalseIncarnate
|
||||
New mutation system, now uses "Mutation Tiers" to adjust the chances of mutations
|
||||
Tier 1 has a low chance of causing a stat mutation
|
||||
Tier 2 has a higher chance of causing a stat mutation
|
||||
Tier 3 has a low chance of causing a species shift (if possible), and will ALWAYS cause a stat mutation if it does not shift species
|
||||
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(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(plant_controller.seeds[seed.name]))
|
||||
seed = seed.diverge()
|
||||
seed.mutate(1,get_turf(src))
|
||||
return
|
||||
if(3) //Tier 3
|
||||
if(prob(20+mutation_mod)) //Low chance of species shift mutation
|
||||
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(plant_controller.seeds[seed.name]))
|
||||
seed = seed.diverge()
|
||||
seed.mutate(1,get_turf(src))
|
||||
return
|
||||
else //Failed to shift, mutate stats instead
|
||||
if(!isnull(plant_controller.seeds[seed.name]))
|
||||
seed = seed.diverge()
|
||||
seed.mutate(1,get_turf(src))
|
||||
return
|
||||
if(4) //Tier 4
|
||||
if(prob(60+mutation_mod)) //Higher chance of species shift mutation
|
||||
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(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(plant_controller.seeds[seed.name]))
|
||||
seed = seed.diverge()
|
||||
seed.mutate(1,get_turf(src))
|
||||
return
|
||||
else //Failed to shift, mutate stats instead
|
||||
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(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(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(plant_controller.seeds[seed.name]))
|
||||
seed = seed.diverge()
|
||||
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
|
||||
// We need to make sure we're not modifying one of the global seed datums.
|
||||
// If it's not in the global list, then no products of the line have been
|
||||
// harvested yet and it's safe to assume it's restricted to this tray.
|
||||
if(!isnull(seed_types[seed.name]))
|
||||
seed = seed.diverge()
|
||||
seed.mutate(severity,get_turf(src))
|
||||
*/
|
||||
|
||||
//--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 plant_controller.seeds)
|
||||
seed = plant_controller.seeds[newseed]
|
||||
else
|
||||
return
|
||||
|
||||
dead = 0
|
||||
//mutate(1)
|
||||
age = 0
|
||||
health = seed.get_trait(TRAIT_ENDURANCE)
|
||||
lastcycle = world.time
|
||||
harvest = 0
|
||||
weedlevel = 0
|
||||
|
||||
update_icon()
|
||||
visible_message("\red The \blue [previous_plant] \red has suddenly mutated into \blue [seed.display_name]!")
|
||||
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/portable_atmospherics/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
if(exchange_parts(user, O))
|
||||
return
|
||||
|
||||
if(istype(O, /obj/item/weapon/crowbar))
|
||||
if(anchored==2)
|
||||
user << "Unscrew the hoses first!"
|
||||
return
|
||||
default_deconstruction_crowbar(O, 1)
|
||||
|
||||
//--FalseIncarnate
|
||||
//Check if held item is an open container
|
||||
if (O.is_open_container())
|
||||
//Check if container is of the "glass" subtype (includes buckets, beakers, vials)
|
||||
if(istype(O, /obj/item/weapon/reagent_containers/glass))
|
||||
var/obj/item/weapon/reagent_containers/glass/C = O
|
||||
//Check if container is empty
|
||||
if(!C.reagents.total_volume)
|
||||
user << "\red [C] is empty."
|
||||
return
|
||||
//Container not empty, transfer contents to tray
|
||||
var/trans = C.reagents.trans_to(src, C.amount_per_transfer_from_this)
|
||||
user << "\blue You transfer [trans] units of the solution to [src]."
|
||||
|
||||
check_level_sanity()
|
||||
process_reagents()
|
||||
update_icon()
|
||||
|
||||
//Check if container is one of the plantsprays (defined in tray_reagents.dm)
|
||||
else if(istype(O, /obj/item/weapon/plantspray))
|
||||
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 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 if container is any spray container
|
||||
else if (istype(O, /obj/item/weapon/reagent_containers/spray))
|
||||
var/obj/item/weapon/reagent_containers/spray/S = O
|
||||
//Check if there is a plant in the tray
|
||||
if(seed)
|
||||
if(!S.reagents.total_volume)
|
||||
user << "\red [S] is empty."
|
||||
return
|
||||
//Container not empty, transfer contents to tray
|
||||
S.reagents.trans_to(src, S.amount_per_transfer_from_this)
|
||||
visible_message("\red <B>\The [src] has been sprayed with \the [O][(user ? " by [user]." : ".")]")
|
||||
playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6)
|
||||
check_level_sanity()
|
||||
update_icon()
|
||||
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(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()
|
||||
|
||||
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
|
||||
|
||||
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()
|
||||
|
||||
return
|
||||
|
||||
else if(istype(O, /obj/item/weapon/reagent_containers/syringe))
|
||||
|
||||
var/obj/item/weapon/reagent_containers/syringe/S = O
|
||||
|
||||
if (S.mode == 1)
|
||||
if(seed)
|
||||
return ..()
|
||||
else
|
||||
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 to draw something from."
|
||||
return 1
|
||||
|
||||
else if (istype(O, /obj/item/seeds))
|
||||
|
||||
if(!seed)
|
||||
|
||||
var/obj/item/seeds/S = O
|
||||
user.drop_item(O)
|
||||
|
||||
if(!S.seed)
|
||||
user << "The packet seems to be empty. You throw it away."
|
||||
del(O)
|
||||
return
|
||||
|
||||
user << "You plant the [S.seed.seed_name] [S.seed.seed_noun]."
|
||||
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_health()
|
||||
|
||||
else
|
||||
user << "<span class='danger'>\The [src] already has seeds in it!</span>"
|
||||
|
||||
else if (istype(O, /obj/item/weapon/minihoe)) // The minihoe
|
||||
|
||||
if(weedlevel > 0)
|
||||
user.visible_message("<span class='danger'>[user] starts uprooting the weeds.</span>", "<span class='danger'>You remove the weeds from the [src].</span>")
|
||||
weedlevel = 0
|
||||
update_icon()
|
||||
else
|
||||
user << "<span class='danger'>This plot is completely devoid of weeds. It doesn't need uprooting.</span>"
|
||||
|
||||
else if (istype(O, /obj/item/weapon/storage/bag/plants))
|
||||
|
||||
attack_hand(user)
|
||||
|
||||
var/obj/item/weapon/storage/bag/plants/S = O
|
||||
for (var/obj/item/weapon/reagent_containers/food/snacks/grown/G in locate(user.x,user.y,user.z))
|
||||
if(!S.can_be_inserted(G))
|
||||
return
|
||||
S.handle_item_insertion(G, 1)
|
||||
|
||||
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)
|
||||
return ..()
|
||||
|
||||
playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
anchored = !anchored
|
||||
user << "You [anchored ? "wrench" : "unwrench"] \the [src]."
|
||||
|
||||
else if(istype(O, /obj/item/apiary))
|
||||
|
||||
if(seed)
|
||||
user << "<span class='danger'>[src] is already occupied!</span>"
|
||||
else
|
||||
user.drop_item()
|
||||
del(O)
|
||||
|
||||
var/obj/machinery/apiary/A = new(src.loc)
|
||||
A.icon = src.icon
|
||||
A.icon_state = src.icon_state
|
||||
A.hydrotray_type = src.type
|
||||
del(src)
|
||||
else if(O && O.force && seed)
|
||||
user.visible_message("<span class='danger'>\The [seed.display_name] has been attacked by [user] with \the [O]!</span>")
|
||||
if(!dead)
|
||||
health -= O.force
|
||||
check_health()
|
||||
return
|
||||
|
||||
/obj/machinery/portable_atmospherics/hydroponics/attack_tk(mob/user as mob)
|
||||
if(dead)
|
||||
remove_dead(user)
|
||||
else if(harvest)
|
||||
harvest(user)
|
||||
|
||||
/obj/machinery/portable_atmospherics/hydroponics/attack_hand(mob/user as mob)
|
||||
|
||||
if(istype(usr,/mob/living/silicon))
|
||||
return
|
||||
|
||||
if(harvest)
|
||||
harvest(user)
|
||||
else if(dead)
|
||||
remove_dead(user)
|
||||
|
||||
/obj/machinery/portable_atmospherics/hydroponics/examine()
|
||||
|
||||
..()
|
||||
|
||||
if(!seed)
|
||||
usr << "[src] is empty."
|
||||
return
|
||||
|
||||
usr << "<span class='notice'>[seed.display_name]</span> are growing here.</span>"
|
||||
|
||||
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 <span class='danger'>infested with weeds</span>!"
|
||||
if(pestlevel >= 5)
|
||||
usr << "\The [src] is <span class='danger'>infested with tiny worms</span>!"
|
||||
|
||||
if(dead)
|
||||
usr << "<span class='danger'>The plant is dead.</span>"
|
||||
else if(health <= (seed.get_trait(TRAIT_ENDURANCE)/ 2))
|
||||
usr << "The plant looks <span class='danger'>unhealthy</span>."
|
||||
|
||||
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
|
||||
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
|
||||
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."
|
||||
|
||||
/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)
|
||||
|
||||
/obj/machinery/portable_atmospherics/hydroponics/proc/close_lid(var/mob/living/user)
|
||||
if(!user || user.stat || user.restrained())
|
||||
return
|
||||
|
||||
closed_system = !closed_system
|
||||
user << "You [closed_system ? "close" : "open"] the tray's lid."
|
||||
update_icon()
|
||||
@@ -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 <b>You begin to dislodge the apiary from the tray, the bees don't like that.</b>"
|
||||
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)
|
||||
@@ -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
|
||||
@@ -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! <I>Do not inhale!</I>"
|
||||
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"
|
||||
@@ -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)
|
||||
..()
|
||||
+107
-181
@@ -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 << "<span class='danger'>[src] can tell you nothing about \the [target].</span>"
|
||||
return
|
||||
|
||||
var/dat = "<h3>Plant data for [target]</h3>"
|
||||
user.visible_message("\blue [user] runs the scanner over [target].")
|
||||
form_title = "[grown_seed.seed_name] (#[grown_seed.uid])"
|
||||
var/dat = "<h3>Plant data for [form_title]</h3>"
|
||||
user.visible_message("<span class='notice'>[user] runs the scanner over \the [target].</span>")
|
||||
|
||||
dat += "<h2>General Data</h2>"
|
||||
|
||||
dat += "<table>"
|
||||
dat += "<tr><td><b>Endurance</b></td><td>[grown_seed.endurance]</td></tr>"
|
||||
dat += "<tr><td><b>Yield</b></td><td>[grown_seed.yield]</td></tr>"
|
||||
dat += "<tr><td><b>Lifespan</b></td><td>[grown_seed.lifespan]</td></tr>"
|
||||
dat += "<tr><td><b>Maturation time</b></td><td>[grown_seed.maturation]</td></tr>"
|
||||
dat += "<tr><td><b>Production time</b></td><td>[grown_seed.production]</td></tr>"
|
||||
dat += "<tr><td><b>Potency</b></td><td>[grown_seed.potency]</td></tr>"
|
||||
dat += "<tr><td><b>Endurance</b></td><td>[grown_seed.get_trait(TRAIT_ENDURANCE)]</td></tr>"
|
||||
dat += "<tr><td><b>Yield</b></td><td>[grown_seed.get_trait(TRAIT_YIELD)]</td></tr>"
|
||||
dat += "<tr><td><b>Maturation time</b></td><td>[grown_seed.get_trait(TRAIT_MATURATION)]</td></tr>"
|
||||
dat += "<tr><td><b>Production time</b></td><td>[grown_seed.get_trait(TRAIT_PRODUCTION)]</td></tr>"
|
||||
dat += "<tr><td><b>Potency</b></td><td>[grown_seed.get_trait(TRAIT_POTENCY)]</td></tr>"
|
||||
|
||||
//--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 += "<h2>Other Data</h2>"
|
||||
|
||||
if(grown_seed.harvest_repeat)
|
||||
if(grown_seed.get_trait(TRAIT_HARVEST_REPEAT))
|
||||
dat += "This plant can be harvested repeatedly.<br>"
|
||||
|
||||
if(grown_seed.immutable == -1)
|
||||
if(grown_seed.get_trait(TRAIT_IMMUTABLE) == -1)
|
||||
dat += "This plant is highly mutable.<br>"
|
||||
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.<br>"
|
||||
|
||||
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"].<br>"
|
||||
|
||||
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.<br>"
|
||||
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.<br>"
|
||||
else
|
||||
dat += "It requires a supply of nutrient fluid.<br>"
|
||||
|
||||
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.<br>"
|
||||
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.<br>"
|
||||
else
|
||||
dat += "It requires a stable supply of water.<br>"
|
||||
@@ -135,120 +164,84 @@
|
||||
if(grown_seed.mutants && grown_seed.mutants.len)
|
||||
dat += "It exhibits a high degree of potential subspecies shift.<br>"
|
||||
|
||||
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 += "<br>It is well adapted to low pressure levels."
|
||||
if(grown_seed.highkpa_tolerance > 220)
|
||||
if(grown_seed.get_trait(TRAIT_HIGHKPA_TOLERANCE) > 220)
|
||||
dat += "<br>It is well adapted to high pressure levels."
|
||||
|
||||
if(grown_seed.heat_tolerance > 30)
|
||||
if(grown_seed.get_trait(TRAIT_HEAT_TOLERANCE) > 30)
|
||||
dat += "<br>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 += "<br>It is very sensitive to temperature shifts."
|
||||
|
||||
dat += "<br>It thrives in a light level of [grown_seed.ideal_light] lumen[grown_seed.ideal_light == 1 ? "" : "s"]."
|
||||
dat += "<br>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 += "<br>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 += "<br>It is very sensitive to light level shifts."
|
||||
|
||||
if(grown_seed.toxins_tolerance < 3)
|
||||
if(grown_seed.get_trait(TRAIT_TOXINS_TOLERANCE) < 3)
|
||||
dat += "<br>It is highly sensitive to toxins."
|
||||
else if(grown_seed.toxins_tolerance > 6)
|
||||
else if(grown_seed.get_trait(TRAIT_TOXINS_TOLERANCE) > 6)
|
||||
dat += "<br>It is remarkably resistant to toxins."
|
||||
|
||||
if(grown_seed.pest_tolerance < 3)
|
||||
if(grown_seed.get_trait(TRAIT_PEST_TOLERANCE) < 3)
|
||||
dat += "<br>It is highly sensitive to pests."
|
||||
else if(grown_seed.pest_tolerance > 6)
|
||||
else if(grown_seed.get_trait(TRAIT_PEST_TOLERANCE) > 6)
|
||||
dat += "<br>It is remarkably resistant to pests."
|
||||
|
||||
if(grown_seed.weed_tolerance < 3)
|
||||
if(grown_seed.get_trait(TRAIT_WEED_TOLERANCE) < 3)
|
||||
dat += "<br>It is highly sensitive to weeds."
|
||||
else if(grown_seed.weed_tolerance > 6)
|
||||
else if(grown_seed.get_trait(TRAIT_WEED_TOLERANCE) > 6)
|
||||
dat += "<br>It is remarkably resistant to weeds."
|
||||
|
||||
switch(grown_seed.spread)
|
||||
switch(grown_seed.get_trait(TRAIT_SPREAD))
|
||||
if(1)
|
||||
dat += "<br>It is capable of growing beyond the confines of a tray."
|
||||
dat += "<br>It is able to be planted outside of a tray."
|
||||
if(2)
|
||||
dat += "<br>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 += "<br>It is carniovorous and will eat tray pests for sustenance."
|
||||
if(2)
|
||||
dat += "<br>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 += "<br>It is capable of parisitizing and gaining sustenance from tray weeds."
|
||||
if(grown_seed.alter_temp)
|
||||
dat += "<br>It will periodically alter the local temperature by [grown_seed.alter_temp] degrees Kelvin."
|
||||
if(grown_seed.get_trait(TRAIT_ALTER_TEMP))
|
||||
dat += "<br>It will periodically alter the local temperature by [grown_seed.get_trait(TRAIT_ALTER_TEMP)] degrees Kelvin."
|
||||
|
||||
if(grown_seed.biolum)
|
||||
dat += "<br>It is [grown_seed.biolum_colour ? "<font color='[grown_seed.biolum_colour]'>bio-luminescent</font>" : "bio-luminescent"]."
|
||||
if(grown_seed.flowers)
|
||||
dat += "<br>It has [grown_seed.flower_colour ? "<font color='[grown_seed.flower_colour]'>flowers</font>" : "flowers"]."
|
||||
if(grown_seed.get_trait(TRAIT_BIOLUM))
|
||||
dat += "<br>It is [grown_seed.get_trait(TRAIT_BIOLUM_COLOUR) ? "<font color='[grown_seed.get_trait(TRAIT_BIOLUM_COLOUR)]'>bio-luminescent</font>" : "bio-luminescent"]."
|
||||
|
||||
if(grown_seed.get_trait(TRAIT_PRODUCES_POWER))
|
||||
dat += "<br>The fruit will function as a battery if prepared appropriately."
|
||||
|
||||
if(grown_seed.get_trait(TRAIT_STINGS))
|
||||
dat += "<br>The fruit is covered in stinging spines."
|
||||
|
||||
if(grown_seed.get_trait(TRAIT_JUICY) == 1)
|
||||
dat += "<br>The fruit is soft-skinned and juicy."
|
||||
else if(grown_seed.get_trait(TRAIT_JUICY) == 2)
|
||||
dat += "<br>The fruit is excessively juicy."
|
||||
|
||||
if(grown_seed.get_trait(TRAIT_EXPLOSIVE))
|
||||
dat += "<br>The fruit is internally unstable."
|
||||
|
||||
if(grown_seed.get_trait(TRAIT_TELEPORTING))
|
||||
dat += "<br>The fruit is temporal/spatially unstable."
|
||||
|
||||
if(dat)
|
||||
last_data = dat
|
||||
dat += "<br><br>\[<a href='?src=\ref[src];print=1'>print report</a>\]"
|
||||
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! <I>Do not inhale!</I>"
|
||||
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
|
||||
@@ -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 << "<span class='danger'>Seed type [seed.get_trait(TRAIT_PLANT_ICON)] cannot find a growth stage value.</span>"
|
||||
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
|
||||
@@ -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(\
|
||||
"<span class='notice'>[user.name] frees [buckled_mob.name] from [src].</span>",\
|
||||
"<span class='notice'>[user.name] frees you from [src].</span>",\
|
||||
"<span class='warning'>You hear shredding and ripping.</span>")
|
||||
else
|
||||
buckled_mob.visible_message(\
|
||||
"<span class='notice'>[buckled_mob.name] struggles free of [src].</span>",\
|
||||
"<span class='notice'>You untangle [src] from around yourself.</span>",\
|
||||
"<span class='warning'>You hear shredding and ripping.</span>")
|
||||
unbuckle()
|
||||
else
|
||||
var/text = pick("rips","tears","pulls")
|
||||
user.visible_message(\
|
||||
"<span class='notice'>[user.name] [text] at [src].</span>",\
|
||||
"<span class='notice'>You [text] at [src].</span>",\
|
||||
"<span class='warning'>You hear shredding and ripping.</span>")
|
||||
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 << "<span class='danger'>The vines [pick("wind", "tangle", "tighten")] around you!</span>"
|
||||
|
||||
// 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 << "<span class='danger'>\The [src] pierces your flesh greedily!</span>"
|
||||
|
||||
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 << "<span class='danger'>You feel something seeping into your skin!</span>"
|
||||
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
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -14,4 +14,9 @@
|
||||
visible_message("<span class='warning'>[src] catches [I]!</span>")
|
||||
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)
|
||||
..()
|
||||
@@ -20,4 +20,5 @@
|
||||
|
||||
var/pulse = PULSE_NORM //current pulse level
|
||||
|
||||
var/heart_attack = 0
|
||||
var/heart_attack = 0
|
||||
var/wetlevel = 0 //how wet the mob is
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
..()
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/water_act(volume, temperature, source)
|
||||
..()
|
||||
if(temperature >= 330) bodytemperature = bodytemperature + (temperature - bodytemperature)
|
||||
if(temperature <= 280) bodytemperature = bodytemperature - (bodytemperature - temperature)
|
||||
@@ -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)
|
||||
|
||||
@@ -32,6 +32,20 @@
|
||||
if(10)
|
||||
msg += "<span class='warning'><B>It is radiating with massive levels of electrical activity!</B></span>\n"
|
||||
|
||||
msg += "<span class='warning'>"
|
||||
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 += "</span>"
|
||||
|
||||
msg += "*---------*</span>"
|
||||
usr << msg
|
||||
return
|
||||
@@ -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!
|
||||
|
||||
@@ -40,6 +40,20 @@
|
||||
msg += "It isn't responding to anything around it; it seems to be asleep.\n"
|
||||
msg += "</span>"
|
||||
|
||||
msg += "<span class='warning'>"
|
||||
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 += "</span>"
|
||||
|
||||
if (src.digitalcamo)
|
||||
msg += "It is repulsively uncanny!\n"
|
||||
|
||||
|
||||
@@ -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
|
||||
//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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 += {"<br><A href='byond://?src=\ref[src];lawr=1'>Channel: [src.lawchannel]</A><br>"}
|
||||
list += {"<A href='byond://?src=\ref[src];laws=1'>State Laws</A>"}
|
||||
|
||||
usr << browse(list, "window=laws")
|
||||
usr << browse(list, "window=laws")
|
||||
|
||||
@@ -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
|
||||
..()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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!"
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user