diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm
index 73f9d265..a43f956c 100644
--- a/code/game/objects/items/cigs_lighters.dm
+++ b/code/game/objects/items/cigs_lighters.dm
@@ -861,3 +861,201 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(reagents && reagents.total_volume)
hand_reagents()
+
+///////////////
+/////BONGS/////
+///////////////
+
+/obj/item/bong
+ name = "bong"
+ desc = "A water bong used for smoking dried plants."
+ icon = 'icons/obj/bongs.dmi'
+ icon_state = null
+ item_state = null
+ w_class = WEIGHT_CLASS_NORMAL
+ light_color = "#FFCC66"
+ var/icon_off = "bong"
+ var/icon_on = "bong_lit"
+ var/chem_volume = 100
+ var/last_used_time //for cooldown
+ var/firecharges = 0 //used for counting how many hits can be taken before the flame goes out
+ var/list/list_reagents = list() //For the base reagents bongs could get
+
+
+/obj/item/bong/Initialize()
+ . = ..()
+ create_reagents(chem_volume, NO_REACT) // so it doesn't react until you light it
+ reagents.add_reagent_list(list_reagents)
+ icon_state = icon_off
+
+/obj/item/bong/attackby(obj/item/O, mob/user, params)
+ . = ..()
+ //If we're using a dried plant..
+ if(istype(O,/obj/item/reagent_containers/food/snacks))
+ var/obj/item/reagent_containers/food/snacks/DP = O
+ if (DP.dry)
+ //Nothing if our bong is full
+ if (reagents.holder_full())
+ user.show_message("The bowl is full!", 1)
+ return
+
+ //Transfer reagents and remove the plant
+ user.show_message("You stuff the [DP] into the [src]'s bowl.", 1)
+ DP.reagents.trans_to(src, 100)
+ qdel(DP)
+ return
+ else
+ user.show_message("[DP] must be dried first!", 1)
+ return
+
+ if (O.heat > 500)
+ if (reagents && reagents.total_volume) //if there's stuff in the bong
+ var/lighting_text = O.ignition_effect(src, user)
+ if(lighting_text)
+ //Logic regarding igniting it on
+ if (firecharges == 0)
+ user.show_message("You light the [src] with the [O]!", 1)
+ bongturnon()
+ else
+ user.show_message("You rekindle [src]'s flame with the [O]!", 1)
+
+ firecharges = 1
+ return
+ else
+ user.show_message("There's nothing to light up in the bowl.", 1)
+ return
+
+/obj/item/bong/CtrlShiftClick(mob/user) //empty reagents on alt click
+ if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ return
+
+ if (reagents && reagents.total_volume)
+ user.show_message("You empty the [src].", 1)
+ reagents.clear_reagents()
+ if(firecharges)
+ firecharges = 0
+ bongturnoff()
+ else
+ user.show_message("The [src] is already empty.", 1)
+
+/obj/item/bong/AltClick(mob/user)
+ if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
+ return
+
+ if(firecharges)
+ firecharges = 0
+ bongturnoff()
+ user.show_message("You quench the flame.", 1)
+
+/obj/item/bong/examine(mob/user)
+ ..()
+ if(!reagents.total_volume)
+ to_chat(user, "The bowl is empty.")
+ else if (reagents.total_volume > 80)
+ to_chat(user, "The bowl is filled to the brim.")
+ else if (reagents.total_volume > 40)
+ to_chat(user, "The bowl has plenty weed in it.")
+ else
+ to_chat(user, "The bowl has some weed in it.")
+
+ to_chat(user, "Ctrl+Shift-click to empty.")
+ to_chat(user, "Alt-click to extinguish.")
+
+/obj/item/bong/ignition_effect(atom/A, mob/user)
+ if(firecharges)
+ . = "[user] lights [A] off of the [src]."
+ else
+ . = ""
+
+/obj/item/bong/attack(mob/living/carbon/M, mob/living/carbon/user, obj/target)
+ //if it's lit up, some stuff in the bowl and the user is a target, and we're not on cooldown
+ if (!reagents)
+ return
+
+ if (M ==! user)
+ return
+
+ if(user.is_mouth_covered(head_only = 1))
+ to_chat(user, "Remove your headgear first.")
+ return
+
+ if(user.is_mouth_covered(mask_only = 1))
+ to_chat(user, "Remove your mask first.")
+ return
+
+ if (!reagents.total_volume)
+ to_chat(user, "There's nothing in the bowl.")
+ return
+
+ if (!firecharges)
+ to_chat(user, "You have to light it up first.")
+ return
+
+ if (last_used_time + 30 < world.time)
+ var/hit_strength
+ var/noise
+ var/hittext = ""
+ //if the intent is help then you take a small hit, else a big one
+ if (user.a_intent == INTENT_HARM)
+ hit_strength = 2
+ noise = 100
+ hittext = "big hit"
+ else
+ hit_strength = 1
+ noise = 70
+ hittext = "hit"
+ //bubbling sound
+ playsound(user.loc,'sound/effects/bonghit.ogg', noise, 1)
+
+ last_used_time = world.time
+
+ //message
+ user.visible_message("[user] begins to take a "+ hittext +" from the [src]!", \
+ "You begin to take a "+ hittext +" from [src].")
+
+ //we take a hit here, after an uninterrupted delay
+ if(do_after(user, 25, target = user))
+ if (reagents && reagents.total_volume)
+ var/fraction = 12 * hit_strength
+
+ var/datum/effect_system/smoke_spread/chem/smoke_machine/s = new
+ s.set_up(reagents, hit_strength, 18, user.loc)
+ s.start()
+
+ reagents.reaction(user, INGEST, fraction)
+ if(!reagents.trans_to(user, fraction))
+ reagents.remove_any(fraction)
+
+ if (hit_strength == 2 && prob(15))
+ user.emote("cough")
+ user.adjustOxyLoss(15)
+
+ //playsound(user.loc, 'sound/effects/smoke.ogg', 10, 1, -3)
+
+ user.visible_message("[user] takes a "+ hittext +" from the [src]!", \
+ "You take a "+ hittext +" from [src].")
+
+ firecharges = firecharges - 1
+ if (firecharges == 0)
+ bongturnoff()
+ if (!reagents.total_volume)
+ firecharges = 0
+ bongturnoff()
+
+
+
+/obj/item/bong/proc/bongturnon()
+ icon_state = icon_on
+ set_light(3, 0.8)
+
+/obj/item/bong/proc/bongturnoff()
+ icon_state = icon_off
+ set_light(0, 0.0)
+
+
+
+/obj/item/bong/coconut
+ name = "coconut bong"
+ icon_off = "coconut_bong"
+ icon_on = "coconut_bong_lit"
+ desc = "A water bong used for smoking dried plants. This one's made out of a coconut and some bamboo"
\ No newline at end of file
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 068468b7..6736c0dd 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -235,6 +235,34 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
/obj/item/stack/sheet/mineral/wood/fifty
amount = 50
+/*
+ * Bamboo
+ */
+
+GLOBAL_LIST_INIT(bamboo_recipes, list ( \
+ new/datum/stack_recipe("punji sticks trap", /obj/structure/punji_sticks, 10, time = 160, one_per_turf = TRUE, on_floor = TRUE), \
+ new/datum/stack_recipe("blow gun", /obj/item/gun/syringe/blowgun, 10, time = 70), \
+ ))
+
+/obj/item/stack/sheet/mineral/bamboo
+ name = "bamboo cuttings"
+ desc = "Finely cut bamboo sticks."
+ singular_name = "cut bamboo"
+ icon_state = "sheet-bamboo"
+ item_state = "sheet-bamboo"
+ icon = 'icons/obj/stack_objects.dmi'
+ sheettype = "bamboo"
+ throwforce = 15
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 0)
+ resistance_flags = FLAMMABLE
+ merge_type = /obj/item/stack/sheet/mineral/bamboo
+ grind_results = list("carbon" = 5)
+
+/obj/item/stack/sheet/mineral/bamboo/Initialize(mapload, new_amount, merge = TRUE)
+ recipes = GLOB.bamboo_recipes
+ return ..()
+
+
/*
* Cloth
*/
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index b98c4f79..6d010369 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -73,6 +73,15 @@
turf_type = /turf/open/floor/grass
resistance_flags = FLAMMABLE
+//Fairygrass
+/obj/item/stack/tile/fairygrass
+ name = "fairygrass tile"
+ singular_name = "fairygrass floor tile"
+ desc = "A patch of odd, glowing blue grass."
+ icon_state = "tile_fairygrass"
+ item_state = "tile-fairygrass"
+ turf_type = /turf/open/floor/grass/fairy
+ resistance_flags = FLAMMABLE
//Wood
/obj/item/stack/tile/wood
diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm
index ed6e2790..0128eeda 100644
--- a/code/game/turfs/simulated/floor/fancy_floor.dm
+++ b/code/game/turfs/simulated/floor/fancy_floor.dm
@@ -96,6 +96,15 @@
if(..())
return
+/turf/open/floor/grass/fairy //like grass but fae-er
+ name = "fairygrass patch"
+ desc = "Something about this grass makes you want to frolic. Or get high."
+ icon_state = "fairygrass"
+ floor_tile = /obj/item/stack/tile/fairygrass
+ light_range = 2
+ light_power = 0.50
+ light_color = "#33CCFF"
+
/turf/open/floor/grass/snow
gender = PLURAL
name = "snow"
diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm
index 1b923389..7fe2b758 100644
--- a/code/modules/crafting/recipes.dm
+++ b/code/modules/crafting/recipes.dm
@@ -976,3 +976,11 @@
time = 60
always_availible = TRUE
category = CAT_CLOTHING
+
+/datum/crafting_recipe/coconut_bong
+ name = "Coconut Bong"
+ result = /obj/item/bong/coconut
+ reqs = list(/obj/item/stack/sheet/mineral/bamboo = 2,
+ /obj/item/reagent_containers/food/snacks/grown/coconut = 1)
+ time = 70
+ category = CAT_MISC
\ No newline at end of file
diff --git a/code/modules/hydroponics/gene_modder.dm b/code/modules/hydroponics/gene_modder.dm
index 39b1908c..8695bf2c 100644
--- a/code/modules/hydroponics/gene_modder.dm
+++ b/code/modules/hydroponics/gene_modder.dm
@@ -240,7 +240,7 @@
dat += ""
else
dat += "No trait-related genes detected in sample.
"
- if(can_insert && istype(disk.gene, /datum/plant_gene/trait))
+ if(can_insert && istype(disk.gene, /datum/plant_gene/trait) && !seed.is_gene_forbidden(disk.gene))
dat += "Insert: [disk.gene.get_name()]"
dat += ""
else
diff --git a/code/modules/hydroponics/grown/berries.dm b/code/modules/hydroponics/grown/berries.dm
index e9ad49ee..a16ce949 100644
--- a/code/modules/hydroponics/grown/berries.dm
+++ b/code/modules/hydroponics/grown/berries.dm
@@ -90,7 +90,7 @@
lifespan = 30
endurance = 25
mutatelist = list()
- genes = list(/datum/plant_gene/trait/glow/berry , /datum/plant_gene/trait/noreact, /datum/plant_gene/trait/repeated_harvest)
+ genes = list(/datum/plant_gene/trait/glow/white , /datum/plant_gene/trait/noreact, /datum/plant_gene/trait/repeated_harvest)
reagents_add = list("uranium" = 0.25, "iodine" = 0.2, "vitamin" = 0.04, "nutriment" = 0.1)
rarity = 20
@@ -121,8 +121,9 @@
growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
icon_grow = "cherry-grow"
icon_dead = "cherry-dead"
+ icon_harvest = "cherry-harvest"
genes = list(/datum/plant_gene/trait/repeated_harvest)
- mutatelist = list(/obj/item/seeds/cherry/blue)
+ mutatelist = list(/obj/item/seeds/cherry/blue, /obj/item/seeds/cherry/bulb)
reagents_add = list("nutriment" = 0.07, "sugar" = 0.07)
/obj/item/reagent_containers/food/snacks/grown/cherries
@@ -162,6 +163,31 @@
tastes = list("blue cherry" = 1)
wine_power = 50
+//Cherry Bulbs
+/obj/item/seeds/cherry/bulb
+ name = "pack of cherry bulb pits"
+ desc = "The glowy kind of cherries."
+ icon_state = "seed-cherrybulb"
+ species = "cherrybulb"
+ plantname = "Cherry Bulb Tree"
+ product = /obj/item/reagent_containers/food/snacks/grown/cherrybulbs
+ genes = list(/datum/plant_gene/trait/repeated_harvest, /datum/plant_gene/trait/glow/pink)
+ mutatelist = list()
+ reagents_add = list("nutriment" = 0.07, "sugar" = 0.07)
+ rarity = 10
+
+/obj/item/reagent_containers/food/snacks/grown/cherrybulbs
+ seed = /obj/item/seeds/cherry/bulb
+ name = "cherry bulbs"
+ desc = "They're like little Space Christmas lights!"
+ icon_state = "cherry_bulb"
+ filling_color = "#FF0000"
+ bitesize_mod = 2
+ foodtype = FRUIT
+ grind_results = list(/datum/reagent/consumable/cherryjelly = 0)
+ tastes = list("cherry" = 1)
+ wine_power = 50
+
// Grapes
/obj/item/seeds/grape
name = "pack of grape seeds"
@@ -224,6 +250,10 @@
species = "strawberry"
plantname = "Strawberry Vine"
product = /obj/item/reagent_containers/food/snacks/grown/strawberry
+ growthstages = 6
+ growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
+ icon_grow = "strawberry-grow"
+ icon_dead = "berry-dead"
reagents_add = list("vitamin" = 0.07, "nutriment" = 0.1, "sugar" = 0.2)
mutatelist = list()
diff --git a/code/modules/hydroponics/grown/citrus.dm b/code/modules/hydroponics/grown/citrus.dm
index 97b30aec..5209c090 100644
--- a/code/modules/hydroponics/grown/citrus.dm
+++ b/code/modules/hydroponics/grown/citrus.dm
@@ -49,7 +49,7 @@
icon_grow = "lime-grow"
icon_dead = "lime-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
- mutatelist = list(/obj/item/seeds/lime)
+ mutatelist = list(/obj/item/seeds/lime, /obj/item/seeds/orange_3d)
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.05)
/obj/item/reagent_containers/food/snacks/grown/citrus/orange
@@ -61,6 +61,42 @@
juice_results = list("orangejuice" = 0)
distill_reagent = "triple_sec"
+//3D Orange
+/obj/item/seeds/orange_3d
+ name = "pack of extradimensional orange seeds"
+ desc = "Polygonal seeds."
+ icon_state = "seed-orange"
+ species = "orange"
+ plantname = "Extradimensional Orange Tree"
+ product = /obj/item/reagent_containers/food/snacks/grown/citrus/orange
+ lifespan = 60
+ endurance = 50
+ yield = 5
+ potency = 20
+ growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
+ icon_grow = "lime-grow"
+ icon_dead = "lime-dead"
+ genes = list(/datum/plant_gene/trait/repeated_harvest)
+ reagents_add = list("vitamin" = 0.04, "nutriment" = 0.05, "haloperidol" = 0.15)
+
+/obj/item/reagent_containers/food/snacks/grown/citrus/orange_3d
+ seed = /obj/item/seeds/orange
+ name = "extradminesional orange"
+ desc = "You can hardly wrap your head around this thing."
+ icon_state = "orang"
+ filling_color = "#FFA500"
+ juice_results = list("orangejuice" = 0)
+ distill_reagent = "triple_sec"
+ tastes = list("polygons" = 1, "oranges" = 1)
+
+/obj/item/reagent_containers/food/snacks/grown/citrus/orange_3d/pickup(mob/user)
+ . = ..()
+ icon_state = "orange"
+
+/obj/item/reagent_containers/food/snacks/grown/citrus/orange_3d/dropped(mob/user)
+ . = ..()
+ icon_state = "orang"
+
// Lemon
/obj/item/seeds/lemon
name = "pack of lemon seeds"
diff --git a/code/modules/hydroponics/grown/flowers.dm b/code/modules/hydroponics/grown/flowers.dm
index 9661f38d..705c7562 100644
--- a/code/modules/hydroponics/grown/flowers.dm
+++ b/code/modules/hydroponics/grown/flowers.dm
@@ -183,6 +183,7 @@
icon_grow = "moonflower-grow"
icon_dead = "sunflower-dead"
product = /obj/item/reagent_containers/food/snacks/grown/moonflower
+ genes = list(/datum/plant_gene/trait/glow/purple)
mutatelist = list()
reagents_add = list("moonshine" = 0.2, "vitamin" = 0.02, "nutriment" = 0.02)
rarity = 15
@@ -293,8 +294,8 @@
/obj/item/seeds/bee_balm/honey
name = "pack of Honey Balm seeds"
desc = "These seeds grow into Honey Balms."
- icon_state = "seed-bee_balmalt"
- species = "seed-bee_balm_alt"
+ icon_state = "seed-bee_balm_alt"
+ species = "bee_balmalt"
plantname = "Honey Balm Pods"
product = /obj/item/reagent_containers/food/snacks/grown/bee_balm/honey
endurance = 1
diff --git a/code/modules/hydroponics/grown/grass_carpet.dm b/code/modules/hydroponics/grown/grass_carpet.dm
index 1a1c2ac0..08ce71ad 100644
--- a/code/modules/hydroponics/grown/grass_carpet.dm
+++ b/code/modules/hydroponics/grown/grass_carpet.dm
@@ -15,7 +15,7 @@
icon_grow = "grass-grow"
icon_dead = "grass-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
- mutatelist = list(/obj/item/seeds/grass/carpet)
+ mutatelist = list(/obj/item/seeds/grass/carpet, /obj/item/seeds/grass/fairy)
reagents_add = list("nutriment" = 0.02, "hydrogen" = 0.05)
/obj/item/reagent_containers/food/snacks/grown/grass
@@ -40,6 +40,27 @@
new stacktype(user.drop_location(), grassAmt)
qdel(src)
+//Fairygrass
+/obj/item/seeds/grass/fairy
+ name = "pack of fairygrass seeds"
+ desc = "These seeds grow into a more mystical grass."
+ icon_state = "seed-fairygrass"
+ species = "fairygrass"
+ plantname = "Fairygrass"
+ product = /obj/item/reagent_containers/food/snacks/grown/grass/fairy
+ icon_grow = "fairygrass-grow"
+ icon_dead = "fairygrass-dead"
+ genes = list(/datum/plant_gene/trait/repeated_harvest, /datum/plant_gene/trait/glow/blue)
+ reagents_add = list("nutriment" = 0.02, "hydrogen" = 0.05, "space_drugs" = 0.15)
+
+/obj/item/reagent_containers/food/snacks/grown/grass/fairy
+ seed = /obj/item/seeds/grass/fairy
+ name = "fairygrass"
+ desc = "Blue, glowing, and smells fainly of mushrooms."
+ icon_state = "fairygrassclump"
+ filling_color = "#3399ff"
+ stacktype = /obj/item/stack/tile/fairygrass
+
// Carpet
/obj/item/seeds/grass/carpet
name = "pack of carpet seeds"
diff --git a/code/modules/hydroponics/grown/melon.dm b/code/modules/hydroponics/grown/melon.dm
index 29691c32..f74a763b 100644
--- a/code/modules/hydroponics/grown/melon.dm
+++ b/code/modules/hydroponics/grown/melon.dm
@@ -44,6 +44,7 @@
species = "holymelon"
plantname = "Holy Melon Vines"
product = /obj/item/reagent_containers/food/snacks/grown/holymelon
+ genes = list(/datum/plant_gene/trait/glow/yellow)
mutatelist = list()
reagents_add = list("holywater" = 0.2, "vitamin" = 0.04, "nutriment" = 0.1)
rarity = 20
diff --git a/code/modules/hydroponics/grown/misc.dm b/code/modules/hydroponics/grown/misc.dm
index 641a5edc..879f71cd 100644
--- a/code/modules/hydroponics/grown/misc.dm
+++ b/code/modules/hydroponics/grown/misc.dm
@@ -142,6 +142,7 @@
yield = 4
growthstages = 3
reagents_add = list("sugar" = 0.25)
+ mutatelist = list(/obj/item/seeds/bamboo)
/obj/item/reagent_containers/food/snacks/grown/sugarcane
seed = /obj/item/seeds/sugarcane
@@ -239,3 +240,282 @@
product = /obj/item/reagent_containers/food/snacks/grown/ash_flora/cactus_fruit
growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
growthstages = 2
+
+// Coconut
+/obj/item/seeds/coconut
+ name = "pack of coconut seeds"
+ desc = "They're seeds that grow into coconut palm trees."
+ icon_state = "seed-coconut"
+ species = "coconut"
+ plantname = "Coconut Palm Tree"
+ product = /obj/item/reagent_containers/food/snacks/grown/coconut
+ lifespan = 50
+ endurance = 30
+ potency = 35
+ growing_icon = 'icons/obj/hydroponics/growing.dmi'
+ icon_dead = "coconut-dead"
+ genes = list(/datum/plant_gene/trait/repeated_harvest)
+ forbiddengenes = list(/datum/plant_gene/trait/squash, /datum/plant_gene/trait/stinging)
+ reagents_add = list("coconutmilk" = 0.3)
+
+/obj/item/reagent_containers/food/snacks/grown/coconut
+ seed = /obj/item/seeds/coconut
+ name = "coconut"
+ desc = "Hard shell of a nut containing delicious milk inside. Perhaps try using something sharp?"
+ icon_state = "coconut"
+ item_state = "coconut"
+ possible_transfer_amounts = list(5, 10, 15, 20, 25, 30, 50)
+ spillable = FALSE
+ resistance_flags = ACID_PROOF
+ volume = 150 //so it won't cut reagents despite having the capacity for them
+ w_class = WEIGHT_CLASS_SMALL
+ force = 5
+ throwforce = 5
+ hitsound = 'sound/weapons/klonk.ogg'
+ attack_verb = list("klonked", "donked", "bonked")
+ var/opened = FALSE
+ var/carved = FALSE
+ var/chopped = FALSE
+ var/straw = FALSE
+ var/fused = FALSE
+ var/fusedactive = FALSE
+ var/defused = FALSE
+
+/obj/item/reagent_containers/food/snacks/grown/coconut/Initialize(mapload, obj/item/seeds/new_seed)
+ . = ..()
+ var/newvolume
+ newvolume = 50 + round(seed.potency,10)
+ if (seed.get_gene(/datum/plant_gene/trait/maxchem))
+ newvolume = newvolume + 50
+ volume = newvolume
+ reagents.maximum_volume = newvolume
+ reagents.update_total()
+
+ transform *= TRANSFORM_USING_VARIABLE(40, 100) + 0.5 //temporary fix for size?
+
+/obj/item/reagent_containers/food/snacks/grown/coconut/attack_self(mob/user)
+ if (opened == TRUE)
+ if(possible_transfer_amounts.len)
+ var/i=0
+ for(var/A in possible_transfer_amounts)
+ i++
+ if(A == amount_per_transfer_from_this)
+ if(i[src]'s transfer amount is now [amount_per_transfer_from_this] units.")
+ return
+
+/obj/item/reagent_containers/food/snacks/grown/coconut/attackby(obj/item/W, mob/user, params)
+ //DEFUSING NADE LOGIC
+ if (W.tool_behaviour == TOOL_WIRECUTTER && fused == TRUE)
+ user.show_message("You cut the fuse!", 1)
+ playsound(user, W.hitsound, 50, 1, -1)
+ icon_state = "coconut_carved"
+ desc = "A coconut. This one's got a hole in it."
+ name = "coconut"
+ defused = TRUE
+ fused = FALSE
+ fusedactive = FALSE
+ if(!seed.get_gene(/datum/plant_gene/trait/glow))
+ set_light(0, 0.0)
+ return
+ //IGNITING NADE LOGIC
+ if(fusedactive == FALSE && fused == TRUE)
+ var/lighting_text = W.ignition_effect(src, user)
+ if(lighting_text)
+ user.visible_message("[user] ignites [src]'s fuse!", "You ignite the [src]'s fuse!")
+ fusedactive = TRUE
+ defused = FALSE
+ playsound(src, 'sound/effects/fuse.ogg', 100, 0)
+ message_admins("[ADMIN_LOOKUPFLW(user)] ignited a coconut bomb for detonation at [ADMIN_VERBOSEJMP(user)] "+ pretty_string_from_reagent_list(reagents.reagent_list))
+ log_game("[key_name(user)] primed a coconut grenade for detonation at [AREACOORD(user)].")
+ addtimer(CALLBACK(src, .proc/prime), 5 SECONDS)
+ icon_state = "coconut_grenade_active"
+ desc = "RUN!"
+ if(!seed.get_gene(/datum/plant_gene/trait/glow))
+ light_color = "#FFCC66" //for the fuse
+ set_light(3, 0.8)
+ return
+
+ //ADDING A FUSE, NADE LOGIC
+ if (istype(W,/obj/item/stack/sheet/cloth) || istype(W,/obj/item/stack/sheet/durathread))
+ if (carved == TRUE && straw == FALSE && fused == FALSE)
+ user.show_message("You add a fuse to the coconut!", 1)
+ W.use(1)
+ fused = TRUE
+ icon_state = "coconut_grenade"
+ desc = "A makeshift bomb made out of a coconut. You estimate the fuse is long enough for 5 seconds."
+ name = "coconut bomb"
+ return
+ //ADDING STRAW LOGIC
+ if (istype(W,/obj/item/stack/sheet/mineral/bamboo) && opened == TRUE && straw == FALSE && fused == FALSE)
+ user.show_message("You add a bamboo straw to the coconut!", 1)
+ straw = TRUE
+ W.use(1)
+ icon_state += "_straw"
+ desc = "You can already feel like you're on a tropical vacation."
+ //OPENING THE NUT LOGIC
+ if (carved == FALSE && chopped == FALSE)
+ if(W.tool_behaviour == TOOL_SCREWDRIVER)
+ user.show_message("You make a hole in the coconut!", 1)
+ carved = TRUE
+ opened = TRUE
+ reagent_flags = OPENCONTAINER
+ ENABLE_BITFIELD(reagents.reagents_holder_flags, OPENCONTAINER)
+ icon_state = "coconut_carved"
+ desc = "A coconut. This one's got a hole in it."
+ playsound(user, W.hitsound, 50, 1, -1)
+ return
+ else if(W.sharpness)
+ user.show_message("You slice the coconut open!", 1)
+ chopped = TRUE
+ opened = TRUE
+ reagent_flags = OPENCONTAINER
+ ENABLE_BITFIELD(reagents.reagents_holder_flags, OPENCONTAINER)
+ spillable = TRUE
+ icon_state = "coconut_chopped"
+ desc = "A coconut. This one's sliced open, with all its delicious contents for your eyes to savour."
+ playsound(user, W.hitsound, 50, 1, -1)
+ return
+
+/obj/item/reagent_containers/food/snacks/grown/coconut/attack(mob/living/M, mob/user, obj/target)
+ if(M && user.a_intent == INTENT_HARM && spillable == FALSE)
+ var/obj/item/bodypart/affecting = user.zone_selected //Find what the player is aiming at
+ if (affecting == BODY_ZONE_HEAD && prob(15))
+ //smash the nut open
+ var/armor_block = min(90, M.run_armor_check(affecting, "melee", null, null,armour_penetration)) // For normal attack damage
+ M.apply_damage(force, BRUTE, affecting, armor_block)
+
+ //Sound
+ playsound(user, hitsound, 100, 1, -1)
+
+ //Attack logs
+ log_combat(user, M, "attacked", src)
+
+ //Display an attack message.
+ if(M != user)
+ M.visible_message("[user] has cracked open a [src.name] on [M]'s head!", \
+ "[user] has cracked open a [src.name] on [M]'s head!")
+ else
+ user.visible_message("[M] cracks open a [src.name] on their [M.p_them()] head!", \
+ "[M] cracks open a [src.name] on [M.p_their()] head!")
+
+ //The coconut breaks open so splash its reagents
+ spillable = TRUE
+ SplashReagents(M)
+
+ //Lastly we remove the nut
+ qdel(src)
+ else
+ . = ..()
+ return
+
+ if(fusedactive)
+ return
+
+ if(opened == FALSE)
+ return
+
+ if(!canconsume(M, user))
+ return
+
+ if(!reagents || !reagents.total_volume)
+ to_chat(user, "[src] is empty!")
+ return
+
+ if(istype(M))
+ if(user.a_intent == INTENT_HARM && spillable == TRUE)
+ var/R
+ M.visible_message("[user] splashes the contents of [src] onto [M]!", \
+ "[user] splashes the contents of [src] onto [M]!")
+ if(reagents)
+ for(var/datum/reagent/A in reagents.reagent_list)
+ R += A.id + " ("
+ R += num2text(A.volume) + "),"
+ if(isturf(target) && reagents.reagent_list.len && thrownby)
+ log_combat(thrownby, target, "splashed (thrown) [english_list(reagents.reagent_list)]")
+ message_admins("[ADMIN_LOOKUPFLW(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] at [ADMIN_VERBOSEJMP(target)].")
+ reagents.reaction(M, TOUCH)
+ log_combat(user, M, "splashed", R)
+ reagents.clear_reagents()
+ else
+ if(M != user)
+ M.visible_message("[user] attempts to feed something to [M].", \
+ "[user] attempts to feed something to you.")
+ if(!do_mob(user, M))
+ return
+ if(!reagents || !reagents.total_volume)
+ return // The drink might be empty after the delay, such as by spam-feeding
+ M.visible_message("[user] feeds something to [M].", "[user] feeds something to you.")
+ log_combat(user, M, "fed", reagents.log_list())
+ else
+ to_chat(user, "You swallow a gulp of [src].")
+ var/fraction = min(5/reagents.total_volume, 1)
+ reagents.reaction(M, INGEST, fraction)
+ addtimer(CALLBACK(reagents, /datum/reagents.proc/trans_to, M, 5), 5)
+ playsound(M.loc,'sound/items/drink.ogg', rand(10,50), 1)
+
+/obj/item/reagent_containers/food/snacks/grown/coconut/afterattack(obj/target, mob/user, proximity)
+ . = ..()
+ if(fusedactive)
+ return
+
+ if((!proximity) || !check_allowed_items(target,target_self=1))
+ return
+
+ if(target.is_refillable()) //Something like a glass. Player probably wants to transfer TO it.
+ if(!reagents.total_volume)
+ to_chat(user, "[src] is empty!")
+ return
+
+ if(target.reagents.holder_full())
+ to_chat(user, "[target] is full.")
+ return
+
+ var/trans = reagents.trans_to(target, amount_per_transfer_from_this)
+ to_chat(user, "You transfer [trans] unit\s of the solution to [target].")
+
+ else if(target.is_drainable()) //A dispenser. Transfer FROM it TO us.
+ if(!target.reagents.total_volume)
+ to_chat(user, "[target] is empty and can't be refilled!")
+ return
+
+ if(reagents.holder_full())
+ to_chat(user, "[src] is full.")
+ return
+
+ var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this)
+ to_chat(user, "You fill [src] with [trans] unit\s of the contents of [target].")
+
+ else if(reagents.total_volume)
+ if(user.a_intent == INTENT_HARM && spillable == TRUE)
+ user.visible_message("[user] splashes the contents of [src] onto [target]!", \
+ "You splash the contents of [src] onto [target].")
+ reagents.reaction(target, TOUCH)
+ reagents.clear_reagents()
+
+/obj/item/reagent_containers/food/snacks/grown/coconut/dropped(mob/user)
+ . = ..()
+ transform *= TRANSFORM_USING_VARIABLE(40, 100) + 0.5 //temporary fix for size?
+
+/obj/item/reagent_containers/food/snacks/grown/coconut/proc/prime()
+ if (!defused)
+ var/turf/T = get_turf(src)
+ reagents.chem_temp = 1000
+ //Disable seperated contents when the grenade primes
+ if (seed.get_gene(/datum/plant_gene/trait/noreact))
+ DISABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT)
+ reagents.handle_reactions()
+ log_game("Coconut bomb detonation at [AREACOORD(T)], location [loc]")
+ qdel(src)
+
+/obj/item/reagent_containers/food/snacks/grown/coconut/ex_act(severity)
+ qdel(src)
+
+/obj/item/reagent_containers/food/snacks/grown/coconut/deconstruct(disassembled = TRUE)
+ if(!disassembled && fused)
+ prime()
+ if(!QDELETED(src))
+ qdel(src)
\ No newline at end of file
diff --git a/code/modules/hydroponics/grown/towercap.dm b/code/modules/hydroponics/grown/towercap.dm
index 23f178ed..6df0f0cd 100644
--- a/code/modules/hydroponics/grown/towercap.dm
+++ b/code/modules/hydroponics/grown/towercap.dm
@@ -98,6 +98,49 @@
/obj/item/grown/log/steel/CheckAccepted(obj/item/I)
return FALSE
+/obj/item/seeds/bamboo
+ name = "pack of bamboo seeds"
+ desc = "A plant known for its flexible and resistant logs."
+ icon_state = "seed-bamboo"
+ species = "bamboo"
+ plantname = "Bamboo"
+ product = /obj/item/grown/log/bamboo
+ lifespan = 80
+ endurance = 70
+ maturation = 15
+ production = 2
+ yield = 5
+ potency = 50
+ growthstages = 2
+ growing_icon = 'icons/obj/hydroponics/growing.dmi'
+ icon_dead = "bamboo-dead"
+ genes = list(/datum/plant_gene/trait/repeated_harvest)
+
+/obj/item/grown/log/bamboo
+ seed = /obj/item/seeds/bamboo
+ name = "bamboo log"
+ desc = "A long and resistant bamboo log."
+ icon_state = "bamboo"
+ plank_type = /obj/item/stack/sheet/mineral/bamboo
+ plank_name = "bamboo sticks"
+
+/obj/item/grown/log/bamboo/CheckAccepted(obj/item/I)
+ return FALSE
+
+/obj/structure/punji_sticks
+ name = "punji sticks"
+ desc = "Don't step on this."
+ icon = 'icons/obj/hydroponics/equipment.dmi'
+ icon_state = "punji"
+ resistance_flags = FLAMMABLE
+ max_integrity = 30
+ density = FALSE
+ anchored = TRUE
+
+/obj/structure/punji_sticks/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/caltrop, 20, 30, 100, CALTROP_BYPASS_SHOES)
+
/////////BONFIRES//////////
/obj/structure/bonfire
diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm
index 53e94c73..536cfe68 100644
--- a/code/modules/hydroponics/plant_genes.dm
+++ b/code/modules/hydroponics/plant_genes.dm
@@ -301,14 +301,39 @@
/datum/plant_gene/trait/glow/shadow/glow_power(obj/item/seeds/S)
return -max(S.potency*(rate*0.2), 0.2)
-/datum/plant_gene/trait/glow/red
- name = "Red Electrical Glow"
- glow_color = LIGHT_COLOR_RED
+//Colored versions of bioluminescence.
+datum/plant_gene/trait/glow/white
+ name = "White Bioluminescence"
+ glow_color = "#FFFFFF"
-/datum/plant_gene/trait/glow/berry
- name = "Strong Bioluminescence"
- rate = 0.05
- glow_color = null
+/datum/plant_gene/trait/glow/red
+ name = "Red Bioluminescence"
+ glow_color = "#FF3333"
+
+/datum/plant_gene/trait/glow/yellow
+ //not the disgusting glowshroom yellow hopefully
+ name = "Yellow Bioluminescence"
+ glow_color = "#FFFF66"
+
+/datum/plant_gene/trait/glow/green
+ //oh no, now i'm radioactive
+ name = "Green Bioluminescence"
+ glow_color = "#99FF99"
+
+/datum/plant_gene/trait/glow/blue
+ //the best one
+ name = "Blue Bioluminescence"
+ glow_color = "#6699FF"
+
+/datum/plant_gene/trait/glow/purple
+ //did you know that notepad++ doesnt think bioluminescence is a word
+ name = "Purple Bioluminescence"
+ glow_color = "#D966FF"
+
+/datum/plant_gene/trait/glow/pink
+ //gay tide station pride
+ name = "Pink Bioluminescence"
+ glow_color = "#FFB3DA"
/datum/plant_gene/trait/teleport
diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm
index f7f831a8..ab9668a3 100644
--- a/code/modules/hydroponics/seeds.dm
+++ b/code/modules/hydroponics/seeds.dm
@@ -26,6 +26,7 @@
var/rarity = 0 // How rare the plant is. Used for giving points to cargo when shipping off to CentCom.
var/list/mutatelist = list() // The type of plants that this plant can mutate into.
var/list/genes = list() // Plant genes are stored here, see plant_genes.dm for more info.
+ var/list/forbiddengenes = list() // Plant genes that the seed may be forbidden from having.
var/list/reagents_add = list()
// A list of reagents to add to product.
// Format: "reagent_id" = potency multiplier
@@ -90,6 +91,10 @@
/obj/item/seeds/proc/get_gene(typepath)
return (locate(typepath) in genes)
+obj/item/seeds/proc/is_gene_forbidden(typepath)
+ return (locate(typepath) in forbiddengenes)
+
+
/obj/item/seeds/proc/reagents_from_genes()
reagents_add = list()
for(var/datum/plant_gene/reagent/R in genes)
@@ -390,7 +395,7 @@
for(var/i in 1 to amount_random_traits)
var/random_trait = pick((subtypesof(/datum/plant_gene/trait)-typesof(/datum/plant_gene/trait/plant_type)))
var/datum/plant_gene/trait/T = new random_trait
- if(T.can_add(src))
+ if(T.can_add(src) && !is_gene_forbidden(T))
genes += T
else
qdel(T)
diff --git a/code/modules/projectiles/guns/misc/syringe_gun.dm b/code/modules/projectiles/guns/misc/syringe_gun.dm
index c9e8f2f2..3e4b800b 100644
--- a/code/modules/projectiles/guns/misc/syringe_gun.dm
+++ b/code/modules/projectiles/guns/misc/syringe_gun.dm
@@ -122,3 +122,19 @@
else
to_chat(user, "You can't put the [A] into \the [src]!")
return FALSE
+
+/obj/item/gun/syringe/blowgun
+ name = "blowgun"
+ desc = "Fire syringes at a short distance."
+ icon_state = "blowgun"
+ item_state = "blowgun"
+ fire_sound = 'sound/weapons/grenadelaunch.ogg'
+
+/obj/item/gun/syringe/blowgun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
+ visible_message("[user] starts aiming with a blowgun!")
+ if(do_after(user, 25, target = src))
+ var/shot
+ shot = ..()
+ if (shot == TRUE)
+ user.adjustStaminaLoss(15)
+ user.adjustOxyLoss(15)
diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
index bfefc073..b4e61faa 100644
--- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
@@ -242,6 +242,23 @@
. = 1
..()
+/datum/reagent/consumable/coconutmilk
+ name = "Coconut Milk"
+ id = "coconutmilk"
+ description = "A transparent white liquid extracted from coconuts. Rich in taste."
+ color = "#DFDFDF" // rgb: 223, 223, 223
+ taste_description = "sweet milk"
+ quality = DRINK_GOOD
+ glass_icon_state = "glass_white"
+ glass_name = "glass of coconut milk"
+ glass_desc = "White and nutritious goodness!"
+
+/datum/reagent/consumable/coconutmilk/on_mob_life(mob/living/carbon/M)
+ if(M.getBruteLoss() && prob(20))
+ M.heal_bodypart_damage(2,0, 0)
+ . = 1
+ ..()
+
/datum/reagent/consumable/cream
name = "Cream"
id = "cream"
diff --git a/code/modules/vending/megaseed.dm b/code/modules/vending/megaseed.dm
index 0569b9f1..d48da5b1 100644
--- a/code/modules/vending/megaseed.dm
+++ b/code/modules/vending/megaseed.dm
@@ -14,6 +14,7 @@
/obj/item/seeds/chanter = 3,
/obj/item/seeds/chili = 3,
/obj/item/seeds/cocoapod = 3,
+ /obj/item/seeds/coconut = 3,
/obj/item/seeds/coffee = 3,
/obj/item/seeds/cotton = 3,
/obj/item/seeds/corn = 3,
diff --git a/icons/mob/inhands/weapons/guns_lefthand.dmi b/icons/mob/inhands/weapons/guns_lefthand.dmi
index 8978d172..ea185c5a 100644
Binary files a/icons/mob/inhands/weapons/guns_lefthand.dmi and b/icons/mob/inhands/weapons/guns_lefthand.dmi differ
diff --git a/icons/mob/inhands/weapons/guns_righthand.dmi b/icons/mob/inhands/weapons/guns_righthand.dmi
index 3f8a876d..1d380e34 100644
Binary files a/icons/mob/inhands/weapons/guns_righthand.dmi and b/icons/mob/inhands/weapons/guns_righthand.dmi differ
diff --git a/icons/obj/bongs.dmi b/icons/obj/bongs.dmi
new file mode 100644
index 00000000..406cce38
Binary files /dev/null and b/icons/obj/bongs.dmi differ
diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi
index 0ac8ccf5..588f58e5 100644
Binary files a/icons/obj/guns/projectile.dmi and b/icons/obj/guns/projectile.dmi differ
diff --git a/icons/obj/hydroponics/equipment.dmi b/icons/obj/hydroponics/equipment.dmi
index dd4d1e1f..37adf547 100644
Binary files a/icons/obj/hydroponics/equipment.dmi and b/icons/obj/hydroponics/equipment.dmi differ
diff --git a/icons/obj/hydroponics/growing.dmi b/icons/obj/hydroponics/growing.dmi
index e7dee229..7dc253eb 100644
Binary files a/icons/obj/hydroponics/growing.dmi and b/icons/obj/hydroponics/growing.dmi differ
diff --git a/icons/obj/hydroponics/growing_fruits.dmi b/icons/obj/hydroponics/growing_fruits.dmi
index 32d7fc53..9c0aa7ec 100644
Binary files a/icons/obj/hydroponics/growing_fruits.dmi and b/icons/obj/hydroponics/growing_fruits.dmi differ
diff --git a/icons/obj/hydroponics/harvest.dmi b/icons/obj/hydroponics/harvest.dmi
index b59e23ef..7ba91fe5 100644
Binary files a/icons/obj/hydroponics/harvest.dmi and b/icons/obj/hydroponics/harvest.dmi differ
diff --git a/icons/obj/hydroponics/seeds.dmi b/icons/obj/hydroponics/seeds.dmi
index c0f97be5..c653f54b 100644
Binary files a/icons/obj/hydroponics/seeds.dmi and b/icons/obj/hydroponics/seeds.dmi differ
diff --git a/icons/obj/stack_objects.dmi b/icons/obj/stack_objects.dmi
index 7fa9f24a..f8271e11 100644
Binary files a/icons/obj/stack_objects.dmi and b/icons/obj/stack_objects.dmi differ
diff --git a/icons/obj/tiles.dmi b/icons/obj/tiles.dmi
index 3aa6912d..c8c2202a 100644
Binary files a/icons/obj/tiles.dmi and b/icons/obj/tiles.dmi differ
diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi
index 04384bc8..71339f5f 100644
Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ
diff --git a/sound/effects/bonghit.ogg b/sound/effects/bonghit.ogg
new file mode 100644
index 00000000..45a0dec1
Binary files /dev/null and b/sound/effects/bonghit.ogg differ
diff --git a/sound/weapons/klonk.ogg b/sound/weapons/klonk.ogg
new file mode 100644
index 00000000..471f3ad8
Binary files /dev/null and b/sound/weapons/klonk.ogg differ