diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm
index 1606ef5c7ea..bf620aad6e3 100644
--- a/code/__DEFINES/combat.dm
+++ b/code/__DEFINES/combat.dm
@@ -48,14 +48,8 @@
#define GRAB_UPGRADING 4
#define GRAB_KILL 5
-//Hostile Mob Stances
-#define HOSTILE_STANCE_IDLE 1
-#define HOSTILE_STANCE_ALERT 2
-#define HOSTILE_STANCE_ATTACK 3
-#define HOSTILE_STANCE_ATTACKING 4
-#define HOSTILE_STANCE_TIRED 5
//Hostile Mob AI Status
#define AI_ON 1
-#define AI_SLEEP 2
+#define AI_IDLE 2
#define AI_OFF 3
diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm
index 3b64d71e28d..baa299d535a 100644
--- a/code/datums/supplypacks.dm
+++ b/code/datums/supplypacks.dm
@@ -1062,28 +1062,26 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
cost = 15
containername = "exotic seeds crate"
-/datum/supply_packs/organic/bee_keeper
- name = "Beekeeping Crate"
- contains = list(/obj/item/beezeez,
- /obj/item/beezeez,
- /obj/item/weapon/bee_net,
- /obj/item/apiary,
- /obj/item/queen_bee,
- /obj/item/queen_bee,
- /obj/item/queen_bee)
- cost = 20
- containertype = /obj/structure/closet/crate/hydroponics
- containername = "Beekeeping crate"
- access = access_hydroponics
- announce_beacons = list("Hydroponics" = list("Hydroponics"))
+/datum/supply_packs/organic/hydroponics/beekeeping_fullkit
+ name = "Beekeeping Starter Kit"
+ contains = list(/obj/structure/beebox,
+ /obj/item/honey_frame,
+ /obj/item/honey_frame,
+ /obj/item/honey_frame,
+ /obj/item/queen_bee/bought,
+ /obj/item/clothing/head/beekeeper_head,
+ /obj/item/clothing/suit/beekeeper_suit)
+ cost = 15
+ containername = "beekeeping starter kit"
-/datum/supply_packs/organic/foodcart
- name = "Food Cart crate"
- contains = list(/obj/structure/foodcart)
+/datum/supply_packs/organic/hydroponics/beekeeping_suits
+ name = "2 Beekeeper suits"
+ contains = list(/obj/item/clothing/head/beekeeper_head,
+ /obj/item/clothing/suit/beekeeper_suit,
+ /obj/item/clothing/head/beekeeper_head,
+ /obj/item/clothing/suit/beekeeper_suit)
cost = 10
- containertype = /obj/structure/largecrate
- containername = "food cart crate"
- announce_beacons = list("Kitchen" = list("Kitchen"))
+ containername = "beekeeper suits"
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// Materials ///////////////////////////////////////
diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm
index f55370f2680..dbbf561b609 100644
--- a/code/game/gamemodes/miniantags/morph/morph.dm
+++ b/code/game/gamemodes/miniantags/morph/morph.dm
@@ -173,4 +173,4 @@
target.attack_animal(src)
/mob/living/simple_animal/hostile/morph/update_action_buttons() //So all eaten objects are not counted every life
- return
\ No newline at end of file
+ return
diff --git a/code/game/machinery/bees_items.dm b/code/game/machinery/bees_items.dm
deleted file mode 100644
index 41540788bb7..00000000000
--- a/code/game/machinery/bees_items.dm
+++ /dev/null
@@ -1,110 +0,0 @@
-
-/obj/item/queen_bee
- name = "queen bee packet"
- desc = "Place her into an apiary so she can get busy."
- icon = 'icons/obj/seeds.dmi'
- icon_state = "seed-kudzu"
- w_class = 1
-
-/obj/item/weapon/bee_net
- name = "bee net"
- desc = "For catching rogue bees."
- icon = 'icons/obj/apiary_bees_etc.dmi'
- icon_state = "bee_net"
- item_state = "bedsheet"
- w_class = 3
- var/caught_bees = 0
-
-/obj/item/weapon/bee_net/attack_self(mob/user as mob)
- var/turf/T = get_step(get_turf(user), user.dir)
- for(var/mob/living/simple_animal/bee/B in T)
- if(B.feral < 0)
- caught_bees += B.strength
- qdel(B)
- user.visible_message("\blue [user] nets some bees.","\blue You net up some of the becalmed bees.")
- else
- user.visible_message("\red [user] swings at some bees, they don't seem to like it.","\red You swing at some bees, they don't seem to like it.")
- B.feral = 5
- B.target_mob = user
-
-/obj/item/weapon/bee_net/verb/empty_bees()
- set src in usr
- set name = "empty bee net"
- set category = "Object"
- var/mob/living/carbon/M
- if(iscarbon(usr))
- M = usr
-
- while(caught_bees > 0)
- //release a few super massive swarms
- while(caught_bees > 5)
- var/mob/living/simple_animal/bee/B = new(src.loc)
- B.feral = 5
- B.target_mob = M
- B.strength = 6
- B.icon_state = "bees_swarm"
- caught_bees -= 6
-
- //what's left over
- var/mob/living/simple_animal/bee/B = new(src.loc)
- B.strength = caught_bees
- B.icon_state = "bees[B.strength]"
- B.feral = 5
- B.target_mob = M
-
- caught_bees = 0
-
-/obj/item/apiary
- name = "moveable apiary"
- icon = 'icons/obj/apiary_bees_etc.dmi'
- icon_state = "apiary_item"
- item_state = "giftbag"
- w_class = 5
-
-/obj/item/beezeez
- name = "bottle of BeezEez"
- icon = 'icons/obj/chemical.dmi'
- icon_state = "bottle17"
- New()
- src.pixel_x = rand(-5.0, 5)
- src.pixel_y = rand(-5.0, 5)
-
-/obj/item/weapon/reagent_containers/food/snacks/honeycomb
- name = "honeycomb"
- icon_state = "honeycomb"
- desc = "Dripping with sugary sweetness."
-
-/obj/item/weapon/reagent_containers/food/snacks/honeycomb/New()
- ..()
- reagents.add_reagent("honey",15)
- bitesize = 2
-
-/obj/item/weapon/book/manual/hydroponics_beekeeping
- name = "The Ins and Outs of Apiculture - A Precise Art"
- icon_state ="bookHydroponicsBees"
- author = "Beekeeper Dave"
- title = "The Ins and Outs of Apiculture - A Precise Art"
- dat = {"
-
-
-
-
- Raising Bees
-
- Bees are loving but fickle creatures. Don't mess with their hive and stay away from any clusters of them, and you'll avoid their ire.
- Sometimes, you'll need to dig around in there for those delicious sweeties though - in that case make sure you wear sealed protection gear
- and carry an extinguisher or smoker with you - any bees chasing you, once calmed down, can thusly be netted and returned safely to the hive.
- Beezeez is a cure-all panacea for them, but use it too much and the hive may grow to apocalyptic proportions. Other than that, bees are excellent pets
- for all the family and are excellent caretakers of one's garden: having a hive or two around will aid in the longevity and growth rate of plants,
- and aid them in fighting off poisons and disease.
-
-
-
- "}
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index 11fa7f71393..0b9d9410f73 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -407,7 +407,7 @@ Class Procs:
return 1
return 0
-/obj/machinery/proc/default_unfasten_wrench(mob/user, obj/item/weapon/wrench/W, time = 20)
+/obj/proc/default_unfasten_wrench(mob/user, obj/item/weapon/wrench/W, time = 20)
if(istype(W))
to_chat(user, "Now [anchored ? "un" : ""]securing [name].")
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 7cb53eaed5f..3fe6dc7102f 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -143,9 +143,10 @@ var/global/list/datum/stack_recipe/wood_recipes = list ( \
new/datum/stack_recipe("crossbow frame", /obj/item/weapon/crossbowframe, 5, time = 25, one_per_turf = 0, on_floor = 0), \
new/datum/stack_recipe("wooden door", /obj/structure/mineral_door/wood, 10, time = 20, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("coffin", /obj/structure/closet/coffin, 5, time = 15, one_per_turf = 1, on_floor = 1), \
- new/datum/stack_recipe("apiary", /obj/item/apiary, 10, time = 25, one_per_turf = 0, on_floor = 0), \
new/datum/stack_recipe("easel", /obj/structure/easel, 3, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("wooden buckler", /obj/item/weapon/shield/riot/buckler, 20, time = 40), \
+ new/datum/stack_recipe("apiary", /obj/structure/beebox, 40, time = 50),\
+ new/datum/stack_recipe("honey frame", /obj/item/honey_frame, 5, time = 10),\
)
/obj/item/stack/sheet/wood
diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm
index 350bf9c5e7a..41bc851dff1 100644
--- a/code/game/objects/items/weapons/storage/bags.dm
+++ b/code/game/objects/items/weapons/storage/bags.dm
@@ -161,7 +161,7 @@
max_combined_w_class = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * plants.w_class
max_w_class = 3
w_class = 1
- can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/grown","/obj/item/seeds","/obj/item/weapon/grown", "/obj/item/stack/tile/grass","/obj/item/stack/medical/ointment/aloe","/obj/item/stack/medical/bruise_pack/comfrey")
+ can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/grown","/obj/item/seeds","/obj/item/weapon/grown", "/obj/item/stack/tile/grass","/obj/item/stack/medical/ointment/aloe","/obj/item/stack/medical/bruise_pack/comfrey", "/obj/item/weapon/reagent_containers/honeycomb")
/obj/item/weapon/storage/bag/plants/portaseeder
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/hydroponics.dm b/code/game/objects/structures/crates_lockers/closets/secure/hydroponics.dm
index c661f3bead0..fb26aff5403 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/hydroponics.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/hydroponics.dm
@@ -25,5 +25,4 @@
new /obj/item/clothing/mask/bandana/botany(src)
new /obj/item/weapon/minihoe(src)
new /obj/item/weapon/hatchet(src)
- new /obj/item/weapon/bee_net(src)
return
\ No newline at end of file
diff --git a/code/modules/hydroponics/beekeeping/beebox.dm b/code/modules/hydroponics/beekeeping/beebox.dm
new file mode 100644
index 00000000000..d3d9cb0f3dc
--- /dev/null
+++ b/code/modules/hydroponics/beekeeping/beebox.dm
@@ -0,0 +1,254 @@
+
+#define BEEBOX_MAX_FRAMES 3 //Max frames per box
+#define BEES_RATIO 0.5 //Multiplied by the max number of honeycombs to find the max number of bees
+#define BEE_PROB_NEW_BEE 20 //The chance for spare bee_resources to be turned into new bees
+#define BEE_RESOURCE_HONEYCOMB_COST 100 //The amount of bee_resources for a new honeycomb to be produced, percentage cost 1-100
+#define BEE_RESOURCE_NEW_BEE_COST 50 //The amount of bee_resources for a new bee to be produced, percentage cost 1-100
+
+
+
+/mob/proc/bee_friendly()
+ return 0
+
+
+/mob/living/simple_animal/hostile/poison/bees/bee_friendly()
+ return 1
+
+/mob/living/simple_animal/bot/bee_friendly()
+ if(paicard)
+ return 0
+ return 1
+
+/mob/living/simple_animal/diona/bee_friendly()
+ return 1
+
+/mob/living/carbon/human/bee_friendly()
+ if(get_species() == "Diona") //bees pollinate plants, duh.
+ return 1
+ if((wear_suit && (wear_suit.flags & THICKMATERIAL)) && (head && (head.flags & THICKMATERIAL)))
+ return 1
+ return 0
+
+
+/obj/structure/beebox
+ name = "apiary"
+ desc = "Dr Miles Manners is just your average Wasp themed super hero by day, but by night he becomes DR BEES!"
+ icon = 'icons/obj/apiary_bees.dmi'
+ icon_state = "beebox"
+ anchored = 1
+ density = 1
+ var/mob/living/simple_animal/hostile/poison/bees/queen/queen_bee = null
+ var/list/bees = list() //bees owned by the box, not those inside it
+ var/list/honeycombs = list()
+ var/list/honey_frames = list()
+ var/bee_resources = 0
+
+
+/obj/structure/beebox/New()
+ ..()
+ processing_objects.Add(src)
+
+
+/obj/structure/beebox/Destroy()
+ processing_objects.Remove(src)
+ bees.Cut()
+ bees = null
+ honeycombs.Cut()
+ honeycombs = null
+ queen_bee = null
+ return ..()
+
+
+//Premade apiaries can spawn with a random reagent
+/obj/structure/beebox/premade
+ var/random_reagent = FALSE
+
+
+/obj/structure/beebox/premade/New()
+ ..()
+
+ var/datum/reagent/R = null
+ if(random_reagent)
+ R = pick(subtypesof(/datum/reagent))
+ R = chemical_reagents_list[initial(R.id)]
+
+ queen_bee = new(src)
+ queen_bee.beehome = src
+ bees += queen_bee
+ queen_bee.assign_reagent(R)
+
+ for(var/i in 1 to BEEBOX_MAX_FRAMES)
+ var/obj/item/honey_frame/HF = new(src)
+ honey_frames += HF
+
+ for(var/i in 1 to get_max_bees())
+ var/mob/living/simple_animal/hostile/poison/bees/B = new(src)
+ bees += B
+ B.beehome = src
+ B.assign_reagent(R)
+
+
+/obj/structure/beebox/premade/random
+ random_reagent = TRUE
+
+
+/obj/structure/beebox/process()
+ if(queen_bee)
+ if(bee_resources >= BEE_RESOURCE_HONEYCOMB_COST)
+ if(honeycombs.len < get_max_honeycomb())
+ bee_resources = max(bee_resources-BEE_RESOURCE_HONEYCOMB_COST, 0)
+ var/obj/item/weapon/reagent_containers/honeycomb/HC = new(src)
+ if(queen_bee.beegent)
+ HC.set_reagent(queen_bee.beegent.id)
+ honeycombs += HC
+
+ if(bees.len < get_max_bees())
+ var/freebee = FALSE //a freebee, geddit?, hahaha HAHAHAHA
+ if(bees.len <= 1) //there's always one set of worker bees, this isn't colony collapse disorder its 2d spessmen
+ freebee = TRUE
+ if((bee_resources >= BEE_RESOURCE_NEW_BEE_COST && prob(BEE_PROB_NEW_BEE)) || freebee)
+ if(!freebee)
+ bee_resources = max(bee_resources - BEE_RESOURCE_NEW_BEE_COST, 0)
+ var/mob/living/simple_animal/hostile/poison/bees/B = new(src)
+ B.beehome = src
+ B.assign_reagent(queen_bee.beegent)
+ bees += B
+
+
+/obj/structure/beebox/proc/get_max_honeycomb()
+ . = 0
+ for(var/hf in honey_frames)
+ var/obj/item/honey_frame/HF = hf
+ . += HF.honeycomb_capacity
+
+
+/obj/structure/beebox/proc/get_max_bees()
+ . = get_max_honeycomb() * BEES_RATIO
+
+
+/obj/structure/beebox/examine(mob/user)
+ ..()
+
+ if(!queen_bee)
+ to_chat(user, "There is no queen bee! There won't bee any honeycomb without a queen!")
+
+ var/half_bee = get_max_bees()*0.5
+ if(half_bee && (bees.len >= half_bee))
+ to_chat(user, "This place is a BUZZ with activity... there are lots of bees!")
+
+ to_chat(user, "[bee_resources]/100 resource supply.")
+ to_chat(user, "[bee_resources]% towards a new honeycomb.")
+ to_chat(user, "[bee_resources*2]% towards a new bee.")
+
+ if(honeycombs.len)
+ var/plural = honeycombs.len > 1
+ to_chat(user, "There [plural? "are" : "is"] [honeycombs.len] uncollected honeycomb[plural ? "s":""] in the apiary.")
+
+ if(honeycombs.len >= get_max_honeycomb())
+ to_chat(user, "there's no room for more honeycomb!")
+
+
+/obj/structure/beebox/attackby(obj/item/I, mob/user, params)
+ if(istype(I, /obj/item/honey_frame))
+ var/obj/item/honey_frame/HF = I
+ if(honey_frames.len < BEEBOX_MAX_FRAMES)
+ visible_message("[user] adds a frame to the apiary.")
+ user.unEquip(HF)
+ HF.forceMove(src)
+ honey_frames += HF
+ else
+ to_chat(user, "There's no room for anymore frames in the apiary!")
+
+ if(istype(I, /obj/item/weapon/wrench))
+ if(default_unfasten_wrench(user, I, time = 20))
+ return
+
+ if(istype(I, /obj/item/queen_bee))
+ if(queen_bee)
+ to_chat(user, "This hive already has a queen!")
+ return
+
+ var/obj/item/queen_bee/qb = I
+ user.unEquip(qb)
+
+ qb.queen.forceMove(src)
+ bees += qb.queen
+ queen_bee = qb.queen
+ qb.queen = null
+
+ if(queen_bee)
+ visible_message("[user] sets [qb] down inside the apiary, making it their new home.")
+ var/relocated = 0
+ for(var/b in bees)
+ var/mob/living/simple_animal/hostile/poison/bees/B = b
+ if(B.reagent_incompatible(queen_bee))
+ bees -= B
+ B.beehome = null
+ if(B.loc == src)
+ B.forceMove(get_turf(src))
+ relocated++
+ if(relocated)
+ to_chat(user, "This queen has a different reagent to some of the bees who live here, those bees will not return to this apiary!")
+
+ else
+ to_chat(user, "The queen bee disappeared! bees disappearing has been in the news lately...")
+
+ qdel(qb)
+
+
+/obj/structure/beebox/attack_hand(mob/user)
+ if(ishuman(user))
+ if(!user.bee_friendly())
+ //Time to get stung!
+ var/bees = FALSE
+ for(var/b in bees) //everyone who's ever lived here now instantly hates you, suck it assistant!
+ var/mob/living/simple_animal/hostile/poison/bees/B = b
+ if(B.isqueen)
+ continue
+ if(B.loc == src)
+ B.forceMove(get_turf(src))
+ B.target = user
+ bees = TRUE
+ if(bees)
+ visible_message("[user] disturbs the bees!")
+ else
+ var/option = input(user, "What Action do you wish to perform?", "Apiary") as null|anything in list("Remove a Honey Frame","Remove the Queen Bee")
+ if(!Adjacent(user) || !option)
+ return
+ switch(option)
+ if("Remove a Honey Frame")
+ if(!honey_frames.len)
+ to_chat(user, "There are no honey frames to remove!")
+ return
+
+ var/obj/item/honey_frame/HF = pick_n_take(honey_frames)
+ if(HF)
+ if(!user.put_in_active_hand(HF))
+ HF.forceMove(get_turf(src))
+ visible_message("[user] removes a frame from the apiary.")
+
+ var/amtH = HF.honeycomb_capacity
+ var/fallen = 0
+ while(honeycombs.len && amtH) //let's pretend you always grab the frame with the most honeycomb on it
+ var/obj/item/weapon/reagent_containers/honeycomb/HC = pick_n_take(honeycombs)
+ if(HC)
+ HC.forceMove(get_turf(src))
+ amtH--
+ fallen++
+ if(fallen)
+ var/multiple = fallen > 1
+ visible_message("[user] scrapes [multiple ? "[fallen]" : "a"] honeycomb[multiple ? "s" : ""] off of the frame.")
+
+ if("Remove the Queen Bee")
+ if(!queen_bee || queen_bee.loc != src)
+ to_chat(user, "There is no queen bee to remove!")
+ return
+ var/obj/item/queen_bee/QB = new()
+ queen_bee.forceMove(QB)
+ bees -= queen_bee
+ QB.queen = queen_bee
+ QB.name = queen_bee.name
+ if(!user.put_in_active_hand(QB))
+ QB.forceMove(get_turf(src))
+ visible_message("[user] removes the queen from the apiary.")
+ queen_bee = null
diff --git a/code/modules/hydroponics/beekeeping/beekeeper_suit.dm b/code/modules/hydroponics/beekeeping/beekeeper_suit.dm
new file mode 100644
index 00000000000..f4d47509292
--- /dev/null
+++ b/code/modules/hydroponics/beekeeping/beekeeper_suit.dm
@@ -0,0 +1,16 @@
+
+/obj/item/clothing/head/beekeeper_head
+ name = "beekeeper hat"
+ desc = "keeps the lil buzzing buggers out of your eyes"
+ icon_state = "beekeeper"
+ item_state = "beekeeper"
+ flags = THICKMATERIAL
+
+
+/obj/item/clothing/suit/beekeeper_suit
+ name = "beekeeper suit"
+ desc = "keeps the lil buzzing buggers away from your squishy bits"
+ icon_state = "beekeeper"
+ item_state = "beekeeper"
+ flags = THICKMATERIAL
+ allowed = list (/obj/item/weapon/reagent_containers/spray/plantbgone,/obj/item/device/analyzer/plant_analyzer,/obj/item/seeds,/obj/item/weapon/reagent_containers/glass/fertilizer,/obj/item/weapon/minihoe)
diff --git a/code/modules/hydroponics/beekeeping/honey_frame.dm b/code/modules/hydroponics/beekeeping/honey_frame.dm
new file mode 100644
index 00000000000..a58ab7041c7
--- /dev/null
+++ b/code/modules/hydroponics/beekeeping/honey_frame.dm
@@ -0,0 +1,12 @@
+
+/obj/item/honey_frame
+ name = "honey frame"
+ desc = "a scaffold for bees to build honeycomb on"
+ icon = 'icons/obj/apiary_bees.dmi'
+ icon_state = "honey_frame"
+ var/honeycomb_capacity = 10 //10 Honeycomb per frame by default, researchable frames perhaps?
+
+
+/obj/item/honey_frame/New()
+ pixel_x = rand(8,-8)
+ pixel_y = rand(8,-8)
diff --git a/code/modules/hydroponics/beekeeping/honeycomb.dm b/code/modules/hydroponics/beekeeping/honeycomb.dm
new file mode 100644
index 00000000000..23588cc5c48
--- /dev/null
+++ b/code/modules/hydroponics/beekeeping/honeycomb.dm
@@ -0,0 +1,40 @@
+
+/obj/item/weapon/reagent_containers/honeycomb
+ name = "honeycomb"
+ desc = "a hexagonal mesh of honeycomb"
+ icon = 'icons/obj/apiary_bees.dmi'
+ icon_state = "honeycomb"
+ possible_transfer_amounts = list()
+ disease_amount = 0
+ volume = 10
+ amount_per_transfer_from_this = 0
+ list_reagents = list("honey" = 5)
+ var/honey_color = ""
+
+/obj/item/weapon/reagent_containers/honeycomb/New()
+ ..()
+ pixel_x = rand(8,-8)
+ pixel_y = rand(8,-8)
+ update_icon()
+
+
+/obj/item/weapon/reagent_containers/honeycomb/update_icon()
+ overlays.Cut()
+ var/image/honey
+ if(honey_color)
+ honey = image(icon = 'icons/obj/apiary_bees.dmi', icon_state = "greyscale_honey")
+ honey.color = honey_color
+ else
+ honey = image(icon = 'icons/obj/apiary_bees.dmi', icon_state = "honey")
+ overlays += honey
+
+
+/obj/item/weapon/reagent_containers/honeycomb/proc/set_reagent(reagent)
+ var/datum/reagent/R = chemical_reagents_list[reagent]
+ if(istype(R))
+ name = "honeycomb ([R.name])"
+ honey_color = R.color
+ reagents.add_reagent(R.id,5)
+ else
+ honey_color = ""
+ update_icon()
diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm
index d394fcefea8..1f48cf69adf 100644
--- a/code/modules/hydroponics/trays/tray.dm
+++ b/code/modules/hydroponics/trays/tray.dm
@@ -49,6 +49,8 @@
var/last_plant_ikey //This is for debugging reference, and is otherwise useless. --FalseIncarnate
+ var/recent_bee_visit = FALSE //Have we been visited by a bee recently, so bees dont overpolinate one plant
+
/*
* process() can be found in \code\modules\hydroponics\tray\tray_process.dm
* reagent handling can be found in \code\modules\hydroponics\tray\tray_reagents.dm
@@ -586,19 +588,6 @@
anchored = !anchored
to_chat(user, "You [anchored ? "wrench" : "unwrench"] \the [src].")
- else if(istype(O, /obj/item/apiary))
-
- if(seed)
- to_chat(user, "[src] is already occupied!")
- else
- user.drop_item()
- qdel(O)
-
- var/obj/machinery/apiary/A = new(src.loc)
- A.icon = src.icon
- A.icon_state = src.icon_state
- A.hydrotray_type = src.type
- qdel(src)
else if ((istype(O, /obj/item/weapon/tank) && !( src.destroyed )))
if (src.holding)
to_chat(user, "\blue There is alreadu a tank loaded into the [src].")
@@ -715,4 +704,4 @@
if(istype(holding, /obj/item/weapon/tank))
to_chat(usr, "\blue You eject [holding.name] from [src].")
holding.loc = loc
- holding = null
\ No newline at end of file
+ holding = null
diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm
index 6fecd2c21ca..c94bfcd0ce8 100644
--- a/code/modules/mining/equipment_locker.dm
+++ b/code/modules/mining/equipment_locker.dm
@@ -730,7 +730,7 @@
if(istype(I, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/W = I
if(W.welding && !stat)
- if(stance != HOSTILE_STANCE_IDLE)
+ if(AIStatus == AI_ON)
to_chat(user, "[src] is moving around too much to repair!")
return
if(maxHealth == health)
@@ -1061,4 +1061,4 @@
return ..()
C.preserved = 1
to_chat(user, "You inject the hivelord core with the stabilizer. It will no longer go inert.")
- qdel(src)
\ No newline at end of file
+ qdel(src)
diff --git a/code/modules/mob/living/simple_animal/bees.dm b/code/modules/mob/living/simple_animal/bees.dm
deleted file mode 100644
index 959444ea5e4..00000000000
--- a/code/modules/mob/living/simple_animal/bees.dm
+++ /dev/null
@@ -1,180 +0,0 @@
-
-/mob/living/simple_animal/bee
- name = "bees"
- icon = 'icons/obj/apiary_bees_etc.dmi'
- icon_state = "bees1"
- icon_living = "bees1"
- icon_dead = "bees1"
- var/strength = 1
- var/feral = 0
- var/mut = 0
- var/toxic = 0
- var/turf/target_turf
- var/mob/target_mob
- var/obj/machinery/apiary/parent
- pass_flags = PASSTABLE
- turns_per_move = 6
- var/obj/machinery/portable_atmospherics/hydroponics/my_hydrotray
-
- // Allow final solutions.
- minbodytemp = 0
- maxbodytemp = 360
-
-/mob/living/simple_animal/bee/New(loc, var/obj/machinery/apiary/new_parent)
- ..()
- parent = new_parent
-
-/mob/living/simple_animal/bee/Destroy()
- if(parent)
- parent.owned_bee_swarms.Remove(src)
- return ..()
-
-/mob/living/simple_animal/bee/process_ai()
- //if we're strong enough, sting some people
- var/mob/living/carbon/human/M = target_mob
- var/sting_prob = 100 // Bees will always try to sting.
- if(M in view(src,1)) // Can I see my target?
- if(prob(max(feral * 10, 0))) // Am I mad enough to want to sting? And yes, when I initially appear, I AM mad enough
- var/obj/item/clothing/worn_suit = M.wear_suit
- var/obj/item/clothing/worn_helmet = M.head
- if(worn_suit) // Are you wearing clothes?
- sting_prob -= min(worn_suit.armor["bio"],70) // Is it sealed? I can't get to 70% of your body.
- if(worn_helmet)
- sting_prob -= min(worn_helmet.armor["bio"],30) // Is your helmet sealed? I can't get to 30% of your body.
- if( prob(sting_prob) && (M.stat == CONSCIOUS || (M.stat == UNCONSCIOUS && prob(25))) ) // Try to sting! If you're not moving, think about stinging.
- M.apply_damage(min(strength,2)+mut, BRUTE, sharp=1) // Stinging. The more mutated I am, the harder I sting.
- M.apply_damage((round(feral/10,1)*(max((round(strength/20,1)),1)))+toxic, TOX) // Bee venom based on how angry I am and how many there are of me!
- to_chat(M, "\red You have been stung!")
-
- //if we're chasing someone, get a little bit angry
- if(target_mob && prob(10))
- feral++
-
- //calm down a little bit
- if(feral > 0)
- if(prob(feral * 10))
- feral -= 1
- else
- //if feral is less than 0, we're becalmed by smoke or steam
- if(feral < 0)
- feral += 1
-
- if(target_mob)
- target_mob = null
- target_turf = null
- if(strength > 5)
- //calm down and spread out a little
- var/mob/living/simple_animal/bee/B = new(get_turf(pick(orange(src,1))))
- B.strength = rand(1,5)
- src.strength -= B.strength
- if(src.strength <= 5)
- src.icon_living = "bees[src.strength]"
- B.icon_living = "bees[B.strength]"
- if(src.parent)
- B.parent = src.parent
- src.parent.owned_bee_swarms.Add(B)
-
- //make some noise
- if(prob(0.5))
- src.visible_message("\blue [pick("Buzzzz.","Hmmmmm.","Bzzz.")]")
-
- //smoke, water and steam calms us down
- var/calming = 0
- var/list/calmers = list(/obj/effect/effect/chem_smoke, \
- /obj/effect/effect/water, \
- /obj/effect/effect/foam, \
- /obj/effect/effect/steam, \
- /obj/effect/mist)
-
- for(var/obj/effect/check_effect in src.loc)
- if(check_effect.type in calmers)
- calming = 1
- break
-
- if(calming)
- if(feral > 0)
- src.visible_message("\blue The bees calm down!")
- feral = -10
- target_mob = null
- target_turf = null
- wander = 1
-
- for(var/mob/living/simple_animal/bee/B in src.loc)
- if(B == src)
- continue
-
- if(feral > 0)
- src.strength += B.strength
- qdel(B)
- src.icon_living = "bees[src.strength]"
- if(strength > 5)
- icon_living = "bees_swarm"
- else if(prob(10))
- //make the other swarm of bees stronger, then move away
- var/total_bees = B.strength + src.strength
- if(total_bees < 10)
- B.strength = min(5, total_bees)
- src.strength = total_bees - B.strength
-
- B.icon_living = "bees[B.strength]"
- if(src.strength <= 0)
- qdel(src)
- return
- src.icon_living = "bees[B.strength]"
- var/turf/simulated/floor/T = get_turf(get_step(src, pick(1,2,4,8)))
- density = 1
- if(T.Enter(src, get_turf(src)))
- src.loc = T
- density = 0
- break
-
- if(target_mob)
- if(target_mob in view(src,7))
- target_turf = get_turf(target_mob)
- wander = 0
-
- else // My target's gone! But I might still be pissed! You there. You look like a good stinging target!
- for(var/mob/living/carbon/G in view(src,7))
- target_mob = G
- break
-
- if(target_turf)
- if (!(DirBlocked(get_step(src, get_dir(src,target_turf)),get_dir(src,target_turf)))) // Check for windows and doors!
- Move(get_step(src, get_dir(src,target_turf)))
- if (prob(0.1))
- src.visible_message("\blue The bees swarm after [target_mob]!")
- if(src.loc == target_turf)
- target_turf = null
- wander = 1
- else
- //find some flowers, harvest
- //angry bee swarms don't hang around
- if(feral > 0)
- turns_per_move = rand(1,3)
- else if(feral < 0)
- turns_since_move = 0
- else if(!my_hydrotray || my_hydrotray.loc != src.loc || my_hydrotray.dead || !my_hydrotray.seed)
- var/obj/machinery/portable_atmospherics/hydroponics/my_hydrotray = locate() in src.loc
- if(my_hydrotray)
- if(!my_hydrotray.dead && my_hydrotray.seed)
- turns_per_move = rand(20,50)
- else
- my_hydrotray = null
-
- pixel_x = rand(-12,12)
- pixel_y = rand(-12,12)
-
-/mob/living/simple_animal/bee/handle_state_icons()
- if(!parent && prob(10))
- strength -= 1
- if(strength <= 0)
- qdel(src)
- else if(strength <= 5)
- icon_living = "bees[strength]"
-
- //debugging
- /*icon_living = "[strength]"
- if(strength > 5)
- icon_living = "unknown"*/
-
- ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm
index 80571d2eef8..e536ac303bb 100644
--- a/code/modules/mob/living/simple_animal/hostile/alien.dm
+++ b/code/modules/mob/living/simple_animal/hostile/alien.dm
@@ -43,13 +43,12 @@
var/plant_cooldown = 30
var/plants_off = 0
-/mob/living/simple_animal/hostile/alien/drone/process_ai()
- . = ..()
- if(!.)
+/mob/living/simple_animal/hostile/alien/drone/handle_automated_action()
+ if(!..()) //AIStatus is off
return
plant_cooldown--
- if(stance==HOSTILE_STANCE_IDLE)
+ if(AIStatus == AI_IDLE)
if(!plants_off && prob(10) && plant_cooldown<=0)
plant_cooldown = initial(plant_cooldown)
SpreadPlants()
@@ -90,12 +89,12 @@
var/egg_cooldown = 30
var/plant_cooldown = 30
-/mob/living/simple_animal/hostile/alien/queen/process_ai()
- ..()
-
+/mob/living/simple_animal/hostile/alien/queen/handle_automated_action()
+ if(!..())
+ return
egg_cooldown--
plant_cooldown--
- if(stance==HOSTILE_STANCE_IDLE)
+ if(AIStatus == AI_IDLE)
if(!plants_off && prob(10) && plant_cooldown<=0)
plant_cooldown = initial(plant_cooldown)
SpreadPlants()
diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm
index f55c4ce98d6..798595a36e0 100644
--- a/code/modules/mob/living/simple_animal/hostile/bear.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bear.dm
@@ -23,12 +23,12 @@
melee_damage_lower = 20
melee_damage_upper = 30
attacktext = "mauls"
+ friendly = "bear hugs"
attack_sound = 'sound/weapons/genhit3.ogg'
//Space bears aren't affected by atmos.
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
- var/stance_step = 0
faction = list("russian")
gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE
@@ -36,10 +36,12 @@
//SPACE BEARS! SQUEEEEEEEE~ OW! FUCK! IT BIT MY HAND OFF!!
/mob/living/simple_animal/hostile/bear/Hudson
name = "Hudson"
- desc = ""
- response_help = "pets"
- response_disarm = "gently pushes aside"
- response_harm = "hits"
+ desc = "Feared outlaw, this guy is one bad news bear." //I'm sorry...
+
+/mob/living/simple_animal/hostile/bear/Hudson/New()
+ ..()
+ var/unbearable_pun = pick("He's unbearably cute.", "It looks like he is a bearer of bad news.", "Sadly, he is bearly able to comprehend puns.")
+ desc = "That's Hudson. " + unbearable_pun// I am not sorry for this.
/mob/living/simple_animal/hostile/bear/Move()
..()
@@ -49,121 +51,5 @@
else
icon_state = "bearfloor"
-/mob/living/simple_animal/hostile/bear/process_ai()
- . = ..()
- if(!.)
- return
-
- switch(stance)
-
- if(HOSTILE_STANCE_TIRED)
- stop_automated_movement = 1
- stance_step++
- if(stance_step >= 10) //rests for 10 ticks
- if(target && target in ListTargets())
- stance = HOSTILE_STANCE_ATTACK //If the mob he was chasing is still nearby, resume the attack, otherwise go idle.
- else
- stance = HOSTILE_STANCE_IDLE
-
- if(HOSTILE_STANCE_ALERT)
- stop_automated_movement = 1
- var/found_mob = 0
- if(target && target in ListTargets())
- if(CanAttack(target))
- stance_step = max(0, stance_step) //If we have not seen a mob in a while, the stance_step will be negative, we need to reset it to 0 as soon as we see a mob again.
- stance_step++
- found_mob = 1
- src.dir = get_dir(src,target) //Keep staring at the mob
-
- if(stance_step in list(1,4,7)) //every 3 ticks
- var/action = pick( list( "growls at [target]", "stares angrily at [target]", "prepares to attack [target]", "closely watches [target]" ) )
- if(action)
- custom_emote(1, action)
- if(!found_mob)
- stance_step--
-
- if(stance_step <= -20) //If we have not found a mob for 20-ish ticks, revert to idle mode
- stance = HOSTILE_STANCE_IDLE
- if(stance_step >= 7) //If we have been staring at a mob for 7 ticks,
- stance = HOSTILE_STANCE_ATTACK
-
- if(HOSTILE_STANCE_ATTACKING)
- if(stance_step >= 20) //attacks for 20 ticks, then it gets tired and needs to rest
- custom_emote(1, "is worn out and needs to rest" )
- stance = HOSTILE_STANCE_TIRED
- stance_step = 0
- walk(src, 0) //This stops the bear's walking
- return
-
-
-
-/mob/living/simple_animal/hostile/bear/attackby(var/obj/item/O as obj, var/mob/user as mob, params)
- if(stance != HOSTILE_STANCE_ATTACK && stance != HOSTILE_STANCE_ATTACKING)
- stance = HOSTILE_STANCE_ALERT
- stance_step = 6
- target = user
- ..()
-
-/mob/living/simple_animal/hostile/bear/attack_hand(mob/living/carbon/human/M as mob)
- if(stance != HOSTILE_STANCE_ATTACK && stance != HOSTILE_STANCE_ATTACKING)
- stance = HOSTILE_STANCE_ALERT
- stance_step = 6
- target = M
- ..()
-
/mob/living/simple_animal/hostile/bear/Process_Spacemove(var/movement_dir = 0)
return 1 //No drifting in space for space bears!
-
-/mob/living/simple_animal/hostile/bear/FindTarget()
- . = ..()
- if(.)
- custom_emote(1, "stares alertly at [.]")
- stance = HOSTILE_STANCE_ALERT
-
-/mob/living/simple_animal/hostile/bear/LoseTarget()
- ..(5)
-
-/mob/living/simple_animal/hostile/bear/AttackingTarget()
- custom_emote(1, pick( list("slashes at [target]", "bites [target]") ) )
-
- var/damage = rand(20,30)
-
- if(ishuman(target))
- var/mob/living/carbon/human/H = target
- var/dam_zone = pick("head", "chest", "groin", "l_arm", "l_hand", "r_arm", "r_hand", "l_leg", "l_foot", "r_leg", "r_foot")
- var/obj/item/organ/external/affecting = H.get_organ(ran_zone(dam_zone))
- H.apply_damage(damage, BRUTE, affecting, H.run_armor_check(affecting, "melee"), sharp=1, edge=1)
- return H
- else if(isliving(target))
- var/mob/living/L = target
- L.adjustBruteLoss(damage)
- return L
- else if(istype(target,/obj/mecha))
- var/obj/mecha/M = target
- M.attack_animal(src)
- return M
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm
new file mode 100644
index 00000000000..86be6f3013c
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/hostile/bees.dm
@@ -0,0 +1,290 @@
+#define BEE_IDLE_ROAMING 70 //The value of idle at which a bee in a beebox will try to wander
+#define BEE_IDLE_GOHOME 0 //The value of idle at which a bee will try to go home
+#define BEE_PROB_GOHOME 35 //Probability to go home when idle is below BEE_IDLE_GOHOME
+#define BEE_PROB_GOROAM 5 //Probability to go roaming when idle is above BEE_IDLE_ROAMING
+#define BEE_TRAY_RECENT_VISIT 200 //How long in deciseconds until a tray can be visited by a bee again
+#define BEE_DEFAULT_COLOUR "#e5e500" //the colour we make the stripes of the bee if our reagent has no colour (or we have no reagent)
+
+#define BEE_POLLINATE_YIELD_CHANCE 10
+#define BEE_POLLINATE_PEST_CHANCE 33
+#define BEE_POLLINATE_POTENTCY_CHANCE 50
+
+/mob/living/simple_animal/hostile/poison/bees
+ name = "bee"
+ desc = "buzzy buzzy bee, stingy sti- Ouch!"
+ icon_state = ""
+ icon_living = ""
+ icon = 'icons/mob/bees.dmi'
+ speak_emote = list("buzzes")
+ emote_hear = list("buzzes")
+ turns_per_move = 0
+ melee_damage_lower = 1
+ melee_damage_upper = 1
+ attacktext = "stings"
+ response_help = "shoos"
+ response_disarm = "swats away"
+ response_harm = "squashes"
+ maxHealth = 10
+ health = 10
+ faction = list("hostile")
+ move_to_delay = 0
+ environment_smash = 0
+ mouse_opacity = 2
+ pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
+ flying = 1
+ search_objects = 1 //have to find those plant trays!
+ density = 0
+ small = 1
+
+ //Spaceborn beings don't get hurt by space
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
+ minbodytemp = 0
+
+ var/datum/reagent/beegent = null //hehe, beegent
+ var/obj/structure/beebox/beehome = null
+ var/idle = 0
+ var/isqueen = FALSE
+ var/icon_base = "bee"
+ var/static/list/bee_icons = list()
+
+
+/mob/living/simple_animal/hostile/poison/bees/Process_Spacemove(movement_dir = 0)
+ return 1
+
+
+/mob/living/simple_animal/hostile/poison/bees/New()
+ ..()
+ generate_bee_visuals()
+
+
+/mob/living/simple_animal/hostile/poison/bees/Destroy()
+ if(beehome)
+ beehome.bees.Remove(src)
+ beehome = null
+ beegent = null
+ return ..()
+
+
+/mob/living/simple_animal/hostile/poison/bees/death(gibbed)
+ if(beehome)
+ beehome.bees.Remove(src)
+ beehome = null
+ beegent = null
+ ..()
+ ghostize()
+ qdel(src)
+
+/mob/living/simple_animal/hostile/poison/bees/examine(mob/user)
+ ..()
+
+ if(!beehome)
+ to_chat(user, "This bee is homeless!")
+
+
+/mob/living/simple_animal/hostile/poison/bees/proc/generate_bee_visuals()
+ overlays.Cut()
+
+ var/col = BEE_DEFAULT_COLOUR
+ if(beegent && beegent.color)
+ col = beegent.color
+
+ var/image/base
+ if(!bee_icons["[icon_base]_base"])
+ bee_icons["[icon_base]_base"] = image(icon = 'icons/mob/bees.dmi', icon_state = "[icon_base]_base")
+ base = bee_icons["[icon_base]_base"]
+ overlays += base
+
+ var/image/greyscale
+ if(!bee_icons["[icon_base]_grey_[col]"])
+ bee_icons["[icon_base]_grey_[col]"] = image(icon = 'icons/mob/bees.dmi', icon_state = "[icon_base]_grey")
+ greyscale = bee_icons["[icon_base]_grey_[col]"]
+ greyscale.color = col
+ overlays += greyscale
+
+ var/image/wings
+ if(!bee_icons["[icon_base]_wings"])
+ bee_icons["[icon_base]_wings"] = image(icon = 'icons/mob/bees.dmi', icon_state = "[icon_base]_wings")
+ wings = bee_icons["[icon_base]_wings"]
+ overlays += wings
+
+
+//We don't attack beekeepers/people dressed as bees//Todo: bee costume
+/mob/living/simple_animal/hostile/poison/bees/CanAttack(atom/the_target)
+ . = ..()
+ if(!.)
+ return 0
+ if(ishuman(the_target))
+ var/mob/living/carbon/human/H = the_target
+ return !H.bee_friendly()
+
+
+/mob/living/simple_animal/hostile/poison/bees/Found(atom/A)
+ if(istype(A, /obj/machinery/portable_atmospherics/hydroponics))
+ var/obj/machinery/portable_atmospherics/hydroponics/Hydro = A
+ if(Hydro.seed && !Hydro.dead && !Hydro.recent_bee_visit)
+ wanted_objects |= /obj/machinery/portable_atmospherics/hydroponics //so we only hunt them while they're alive/seeded/not visisted
+ return 1
+ if(ishuman(A))
+ var/mob/living/carbon/human/H = A
+ return !H.bee_friendly()
+ return 0
+
+
+/mob/living/simple_animal/hostile/poison/bees/AttackingTarget()
+ //Pollinate
+ if(istype(target, /obj/machinery/portable_atmospherics/hydroponics))
+ var/obj/machinery/portable_atmospherics/hydroponics/Hydro = target
+ pollinate(Hydro)
+ else if(target == beehome)
+ var/obj/structure/beebox/BB = target
+ forceMove(BB)
+ target = null
+ wanted_objects.Remove(/obj/structure/beebox) //so we don't attack beeboxes when not going home
+ else
+ if(beegent && isliving(target))
+ var/mob/living/L = target
+ if(!isnull(target.reagents))
+ beegent.reaction_mob(L, TOUCH)
+ L.reagents.add_reagent(beegent.id, rand(1,5))
+ target.attack_animal(src)
+
+
+/mob/living/simple_animal/hostile/poison/bees/proc/assign_reagent(datum/reagent/R)
+ if(istype(R))
+ beegent = R
+ name = "[initial(name)] ([R.name])"
+ generate_bee_visuals()
+
+
+/mob/living/simple_animal/hostile/poison/bees/proc/pollinate(obj/machinery/portable_atmospherics/hydroponics/Hydro)
+ if(!istype(Hydro) || !Hydro.seed || Hydro.dead || Hydro.recent_bee_visit)
+ target = null
+ return
+
+ target = null //so we pick a new hydro tray next FindTarget(), instead of loving the same plant for eternity
+ wanted_objects.Remove(/obj/machinery/portable_atmospherics/hydroponics) //so we only hunt them while they're alive/seeded/not visisted
+ Hydro.recent_bee_visit = TRUE
+ spawn(BEE_TRAY_RECENT_VISIT)
+ if(Hydro)
+ Hydro.recent_bee_visit = FALSE
+
+ var/growth = health //Health also means how many bees are in the swarm, roughly.
+ //better healthier plants!
+ Hydro.health += round(growth*0.5)
+ if(prob(BEE_POLLINATE_PEST_CHANCE))
+ Hydro.pestlevel = max(0, --Hydro.pestlevel)
+ if(prob(BEE_POLLINATE_YIELD_CHANCE)) //Yield mod is HELLA powerful, but quite rare
+ if(!isnull(plant_controller.seeds[Hydro.seed.name]))
+ Hydro.seed = Hydro.seed.diverge()
+ var/seed_yield = Hydro.seed.get_trait(TRAIT_YIELD)
+ Hydro.seed.set_trait(TRAIT_YIELD, seed_yield + 1, 10, 0)
+ if(prob(BEE_POLLINATE_POTENTCY_CHANCE))
+ if(!isnull(plant_controller.seeds[Hydro.seed.name]))
+ Hydro.seed = Hydro.seed.diverge()
+ var/seed_potency = Hydro.seed.get_trait(TRAIT_POTENCY)
+ Hydro.seed.set_trait(TRAIT_POTENCY, seed_potency + 1, 200, 0)
+
+ if(beehome)
+ beehome.bee_resources = min(beehome.bee_resources + growth, 100)
+
+
+/mob/living/simple_animal/hostile/poison/bees/handle_automated_action()
+ . = ..()
+ if(!.)
+ return
+
+ if(!isqueen)
+ if(loc == beehome)
+ idle = min(100, ++idle)
+ if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM))
+ forceMove(get_turf(beehome))
+ else
+ idle = max(0, --idle)
+ if(idle <= BEE_IDLE_GOHOME && prob(BEE_PROB_GOHOME))
+ if(!FindTarget())
+ wanted_objects.Add(/obj/structure/beebox) //so we don't attack beeboxes when not going home
+ target = beehome
+ if(!beehome) //add outselves to a beebox (of the same reagent) if we have no home
+ for(var/obj/structure/beebox/BB in view(vision_range, src))
+ if(reagent_incompatible(BB.queen_bee) || BB.bees.len >= BB.get_max_bees())
+ continue
+ BB.bees |= src
+ beehome = BB
+
+
+ /mob/living/simple_animal/hostile/poison/bees/queen
+ name = "queen bee"
+ desc = "she's the queen of bees, BZZ BZZ"
+ icon_base = "queen"
+ isqueen = TRUE
+
+
+ //the Queen doesn't leave the box on her own, and she CERTAINLY doesn't pollinate by herself
+/mob/living/simple_animal/hostile/poison/bees/queen/Found(atom/A)
+ return 0
+
+
+//leave pollination for the peasent bees
+/mob/living/simple_animal/hostile/poison/bees/queen/AttackingTarget()
+ if(beegent && isliving(target))
+ var/mob/living/L = target
+ beegent.reaction_mob(L, TOUCH)
+ L.reagents.add_reagent(beegent.id, rand(1,5))
+ target.attack_animal(src)
+
+
+//PEASENT BEES
+/mob/living/simple_animal/hostile/poison/bees/queen/pollinate()
+ return
+
+
+/mob/living/simple_animal/hostile/poison/bees/proc/reagent_incompatible(mob/living/simple_animal/hostile/poison/bees/B)
+ if(!B)
+ return 0
+ if(B.beegent && beegent && B.beegent.id != beegent.id || B.beegent && !beegent || !B.beegent && beegent)
+ return 1
+ return 0
+
+
+/obj/item/queen_bee
+ name = "queen bee"
+ desc = "she's the queen of bees, BZZ BZZ"
+ icon_state = "queen_item"
+ item_state = ""
+ icon = 'icons/mob/bees.dmi'
+ var/mob/living/simple_animal/hostile/poison/bees/queen/queen
+
+
+/obj/item/queen_bee/attackby(obj/item/I, mob/user, params)
+ if(istype(I,/obj/item/weapon/reagent_containers/syringe))
+ var/obj/item/weapon/reagent_containers/syringe/S = I
+ if(S.reagents.has_reagent("royal_bee_jelly")) //checked twice, because I really don't want royal bee jelly to be duped
+ if(S.reagents.has_reagent("royal_bee_jelly",5))
+ S.reagents.remove_reagent("royal_bee_jelly", 5)
+ var/obj/item/queen_bee/qb = new(get_turf(user))
+ qb.queen = new(qb)
+ if(queen && queen.beegent)
+ qb.queen.assign_reagent(queen.beegent) //Bees use the global singleton instances of reagents, so we don't need to worry about one bee being deleted and her copies losing their reagents.
+ user.put_in_active_hand(qb)
+ user.visible_message("[user] injects [src] with royal bee jelly, causing it to split into two bees, MORE BEES!","You inject [src] with royal bee jelly, causing it to split into two bees, MORE BEES!")
+ else
+ to_chat(user, "You don't have enough royal bee jelly to split a bee in two!")
+ else
+ var/datum/reagent/R = chemical_reagents_list[S.reagents.get_master_reagent_id()]
+ if(R && S.reagents.has_reagent(R.id, 5))
+ S.reagents.remove_reagent(R.id,5)
+ queen.assign_reagent(R)
+ user.visible_message("[user] injects [src]'s genome with [R.name], mutating it's DNA!","You inject [src]'s genome with [R.name], mutating it's DNA!")
+ name = queen.name
+ else
+ to_chat(user, "You don't have enough units of that chemical to modify the bee's DNA!")
+ ..()
+
+
+/obj/item/queen_bee/bought/New()
+ ..()
+ queen = new(src)
+
+/obj/item/queen_bee/Destroy()
+ qdel(queen)
+ return ..()
diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
index 5e25d37763d..368626f49fe 100644
--- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
+++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
@@ -82,18 +82,17 @@
move_to_delay = 5
/mob/living/simple_animal/hostile/poison/giant_spider/hunter/handle_automated_action()
- if(!stat)
- if(stance == HOSTILE_STANCE_IDLE)
- //1% chance to skitter madly away
- if(!busy && prob(1))
- /*var/list/move_targets = list()
- for(var/turf/T in orange(20, src))
- move_targets.Add(T)*/
- stop_automated_movement = 1
- Goto(pick(orange(20, src)), move_to_delay)
- spawn(50)
- stop_automated_movement = 0
- walk(src,0)
+ if(!..()) //AIStatus is off
+ return
+ if(AIStatus == AI_IDLE)
+ //1% chance to skitter madly away
+ if(!busy && prob(1))
+ stop_automated_movement = 1
+ Goto(pick(orange(20, src)), move_to_delay)
+ spawn(50)
+ stop_automated_movement = 0
+ walk(src,0)
+ return 1
/mob/living/simple_animal/hostile/poison/giant_spider/nurse/proc/GiveUp(var/C)
spawn(100)
@@ -104,36 +103,31 @@
stop_automated_movement = 0
/mob/living/simple_animal/hostile/poison/giant_spider/nurse/handle_automated_action()
- if(!stat && !ckey)
- if(stance == HOSTILE_STANCE_IDLE)
- var/list/can_see = view(src, 10)
- //30% chance to stop wandering and do something
- if(!busy && prob(30))
- //first, check for potential food nearby to cocoon
- for(var/mob/living/C in can_see)
- if(C.stat && !istype(C,/mob/living/simple_animal/hostile/poison/giant_spider))
- cocoon_target = C
- busy = MOVING_TO_TARGET
- Goto(C, move_to_delay)
- //give up if we can't reach them after 10 seconds
- GiveUp(C)
- return
-
- //second, spin a sticky spiderweb on this tile
- var/obj/effect/spider/stickyweb/W = locate() in get_turf(src)
- if(!W)
- Web()
+ if(..())
+ var/list/can_see = view(src, 10)
+ if(!busy && prob(30)) //30% chance to stop wandering and do something
+ //first, check for potential food nearby to cocoon
+ for(var/mob/living/C in can_see)
+ if(C.stat && !istype(C,/mob/living/simple_animal/hostile/poison/giant_spider))
+ cocoon_target = C
+ busy = MOVING_TO_TARGET
+ Goto(C, move_to_delay)
+ //give up if we can't reach them after 10 seconds
+ GiveUp(C)
+ return
+ //second, spin a sticky spiderweb on this tile
+ var/obj/effect/spider/stickyweb/W = locate() in get_turf(src)
+ if(!W)
+ Web()
+ else
+ //third, lay an egg cluster there
+ if(fed)
+ LayEggs()
else
- //third, lay an egg cluster there
- if(fed)
- LayEggs()
- else
- //fourthly, cocoon any nearby items so those pesky pinkskins can't use them
- for(var/obj/O in can_see)
-
- if(O.anchored)
- continue
-
+ //fourthly, cocoon any nearby items so those pesky pinkskins can't use them
+ for(var/obj/O in can_see)
+ if(O.anchored)
+ continue
if(istype(O, /obj/item) || istype(O, /obj/structure) || istype(O, /obj/machinery))
cocoon_target = O
busy = MOVING_TO_TARGET
@@ -142,13 +136,13 @@
//give up if we can't reach them after 10 seconds
GiveUp(O)
- else if(busy == MOVING_TO_TARGET && cocoon_target)
- if(get_dist(src, cocoon_target) <= 1)
- Wrap()
+ else if(busy == MOVING_TO_TARGET && cocoon_target)
+ if(get_dist(src, cocoon_target) <= 1)
+ Wrap()
- else
- busy = 0
- stop_automated_movement = 0
+ else
+ busy = 0
+ stop_automated_movement = 0
/mob/living/simple_animal/hostile/poison/giant_spider/verb/Web()
set name = "Lay Web"
@@ -254,4 +248,4 @@
#undef SPINNING_WEB
#undef LAYING_EGGS
#undef MOVING_TO_TARGET
-#undef SPINNING_COCOON
\ No newline at end of file
+#undef SPINNING_COCOON
diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
index 4d856ab397a..c5a656c8c66 100644
--- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
@@ -101,9 +101,8 @@
qdel(src)
return
-/mob/living/simple_animal/hostile/hivebot/tele/process_ai()
- . = ..()
- if(!.)
+/mob/living/simple_animal/hostile/hivebot/tele/handle_automated_action()
+ if(!..())
return
if(prob(2))//Might be a bit low, will mess with it likely
- warpbots()
\ No newline at end of file
+ warpbots()
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index d3a87be35e1..cc1de35947d 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -3,7 +3,6 @@
mouse_opacity = 2 //This makes it easier to hit hostile mobs, you only need to click on their tile, and is set back to 1 when they die
stop_automated_movement_when_pulled = 0
environment_smash = 1 //Set to 1 to break closets,tables,racks, etc; 2 for walls; 3 for rwalls
- var/stance = HOSTILE_STANCE_IDLE //Used to determine behavior
var/atom/target
var/ranged = 0
var/rapid = 0
@@ -30,39 +29,35 @@
var/stat_exclusive = 0 //Mobs with this set to 1 will exclusively attack things defined by stat_attack, stat_attack 2 means they will only attack corpses
var/attack_same = 0 //Set us to 1 to allow us to attack our own faction, or 2, to only ever attack our own faction
- var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_SLEEP (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever)
+ var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever)
/mob/living/simple_animal/hostile/Life()
. = ..()
if(!.)
walk(src, 0)
return 0
- if(ranged)
- ranged_cooldown--
/mob/living/simple_animal/hostile/process_ai()
..()
if(!AICanContinue())
return 0
- switch(stance)
- if(HOSTILE_STANCE_IDLE)
- var/new_target = FindTarget()
- GiveTarget(new_target)
-
- if(HOSTILE_STANCE_ATTACK)
- MoveToTarget()
- DestroySurroundings()
-
- if(HOSTILE_STANCE_ATTACKING)
- AttackTarget()
- DestroySurroundings()
-
- if(AIShouldSleep())
- AIStatus = AI_SLEEP
-
return 1
+/mob/living/simple_animal/hostile/handle_automated_action()
+ if(AIStatus == AI_OFF)
+ return 0
+ if(ranged)
+ ranged_cooldown--
+ var/list/possible_targets = ListTargets() //we look around for potential targets and make it a list for later use.
+ if(environment_smash)
+ EscapeConfinement()
+ if(AICanContinue(possible_targets))
+ DestroySurroundings()
+ if(!MoveToTarget(possible_targets)) //if we lose our target
+ if(AIShouldSleep(possible_targets)) // we try to acquire a new one
+ AIStatus = AI_IDLE // otherwise we go idle
+ return 1
//////////////HOSTILE MOB TARGETTING AND AGGRESSION////////////
@@ -82,19 +77,18 @@
L += Objects
return L
-/mob/living/simple_animal/hostile/proc/FindTarget()//Step 2, filter down possible targets to things we actually care about
+/mob/living/simple_animal/hostile/proc/FindTarget(var/list/possible_targets, var/HasTargetsList = 0)//Step 2, filter down possible targets to things we actually care about
var/list/Targets = list()
- var/Target
- for(var/atom/A in ListTargets())
+ if(!HasTargetsList)
+ possible_targets = ListTargets()
+ for(var/atom/A in possible_targets)
if(Found(A))//Just in case people want to override targetting
- var/list/FoundTarget = list()
- FoundTarget += A
- Targets = FoundTarget
+ Targets = list(A)
break
if(CanAttack(A))//Can we attack it?
Targets += A
continue
- Target = PickTarget(Targets)
+ var/Target = PickTarget(Targets)
GiveTarget(Target)
return Target //We now have a target
@@ -102,14 +96,14 @@
return
/mob/living/simple_animal/hostile/proc/PickTarget(var/list/Targets)//Step 3, pick amongst the possible, attackable targets
+ if(!Targets.len)//We didnt find nothin!
+ return
if(target != null)//If we already have a target, but are told to pick again, calculate the lowest distance between all possible, and pick from the lowest distance targets
for(var/atom/A in Targets)
var/target_dist = get_dist(src, target)
var/possible_target_distance = get_dist(src, A)
if(target_dist < possible_target_distance)
Targets -= A
- if(!Targets.len)//We didnt find nothin!
- return
var/chosen_target = pick(Targets)//Pick the remaining targets (if any) at random
return chosen_target
@@ -148,23 +142,21 @@
return 0
return 1
if(isobj(the_target))
- if(the_target.type in wanted_objects)
+ if(is_type_in_list(the_target, wanted_objects))
return 1
return 0
/mob/living/simple_animal/hostile/proc/GiveTarget(var/new_target)//Step 4, give us our selected target
target = new_target
if(target != null)
- Aggro()
- stance = HOSTILE_STANCE_ATTACK
- return
+ return 1
-/mob/living/simple_animal/hostile/proc/MoveToTarget()//Step 5, handle movement between us and our target
+/mob/living/simple_animal/hostile/proc/MoveToTarget(var/list/possible_targets)//Step 5, handle movement between us and our target
stop_automated_movement = 1
if(!target || !CanAttack(target))
LoseTarget()
- return
- if(target in ListTargets())
+ return 0
+ if(target in possible_targets)
var/target_distance = get_dist(src,target)
if(ranged)//We ranged? Shoot at em
if(target_distance >= 2 && ranged_cooldown <= 0)//But make sure they're a tile away at least, and our range attack is off cooldown
@@ -178,17 +170,18 @@
Goto(target,move_to_delay,minimum_distance)
if(isturf(loc) && target.Adjacent(src)) //If they're next to us, attack
AttackingTarget()
- return
+ return 1
if(environment_smash)
if(target.loc != null && get_dist(src, target.loc) <= vision_range)//We can't see our target, but he's in our vision range still
if(environment_smash >= 2)//If we're capable of smashing through walls, forget about vision completely after finding our target
Goto(target,move_to_delay,minimum_distance)
FindHidden()
- return
+ return 1
else
if(FindHidden())
- return
+ return 1
LostTarget()
+ return 0
/mob/living/simple_animal/hostile/proc/Goto(var/target, var/delay, var/minimum_distance)
walk_to(src, target, minimum_distance, delay)
@@ -199,27 +192,11 @@
if(search_objects)//Turn off item searching and ignore whatever item we were looking at, we're more concerned with fight or flight
search_objects = 0
target = null
- if(stance == HOSTILE_STANCE_IDLE)//If we took damage while idle, immediately attempt to find the source of it so we find a living target
- Aggro()
- var/new_target = FindTarget()
- GiveTarget(new_target)
- if(stance == HOSTILE_STANCE_ATTACK)//No more pulling a mob forever and having a second player attack it, it can switch targets now if it finds a more suitable one
- if(target != null && prob(25))
- var/new_target = FindTarget()
- GiveTarget(new_target)
-
-/mob/living/simple_animal/hostile/proc/AttackTarget()
-
- stop_automated_movement = 1
- if(!target || !CanAttack(target))
- LoseTarget()
- return 0
- if(!(target in ListTargets()))
- LostTarget()
- return 0
- if(isturf(loc) && target.Adjacent(src))
- AttackingTarget()
- return 1
+ if(AIStatus == AI_IDLE)
+ AIStatus = AI_ON
+ FindTarget()
+ else if(target != null && prob(40))//No more pulling a mob forever and having a second player attack it, it can switch targets now if it finds a more suitable one
+ FindTarget()
/mob/living/simple_animal/hostile/proc/AttackingTarget()
target.attack_animal(src)
@@ -232,13 +209,11 @@
vision_range = idle_vision_range
/mob/living/simple_animal/hostile/proc/LoseTarget()
- stance = HOSTILE_STANCE_IDLE
target = null
walk(src, 0)
LoseAggro()
/mob/living/simple_animal/hostile/proc/LostTarget()
- stance = HOSTILE_STANCE_IDLE
walk(src, 0)
LoseAggro()
@@ -340,28 +315,16 @@
////// AI Status ///////
-/mob/living/simple_animal/hostile/proc/AICanContinue()
+/mob/living/simple_animal/hostile/proc/AICanContinue(var/list/possible_targets)
switch(AIStatus)
if(AI_ON)
. = 1
- if(AI_SLEEP)
- if(AIShouldWake())
+ if(AI_IDLE)
+ if(FindTarget(possible_targets, 1))
. = 1
AIStatus = AI_ON //Wake up for more than one Life() cycle.
else
. = 0
- if(AI_OFF)
- . = 0
-
-//Returns 1 if the AI should wake up
-//Returns 0 if the AI should remain asleep
-/mob/living/simple_animal/hostile/proc/AIShouldWake()
- . = 0
- if(FindTarget())
- . = 1
-
-
-//Convenience
-/mob/living/simple_animal/hostile/proc/AIShouldSleep()
- . = !(AIShouldWake())
+/mob/living/simple_animal/hostile/proc/AIShouldSleep(var/list/possible_targets)
+ return !FindTarget(possible_targets, 1)
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle_animals.dm b/code/modules/mob/living/simple_animal/hostile/jungle_animals.dm
index 85268dee619..51baabb0c76 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle_animals.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle_animals.dm
@@ -32,13 +32,7 @@
var/stalk_tick_delay = 3
gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE
-/mob/living/simple_animal/hostile/panther/ListTargets()
- var/list/targets = list()
- for(var/mob/living/carbon/human/H in view(src, 10))
- targets += H
- return targets
-
-/mob/living/simple_animal/hostile/panther/FindTarget()
+/mob/living/simple_animal/hostile/panther/FindTarget(var/list/possible_targets)
. = ..()
if(.)
emote("nashes at [.]")
@@ -51,14 +45,6 @@
L.Weaken(3)
L.visible_message("\the [src] knocks down \the [L]!")
-/mob/living/simple_animal/hostile/panther/AttackTarget()
- ..()
- if(stance == HOSTILE_STANCE_ATTACKING && get_dist(src, target))
- stalk_tick_delay -= 1
- if(stalk_tick_delay <= 0)
- src.loc = get_step_towards(src, target)
- stalk_tick_delay = 3
-
//*******//
// Snake //
//*******//
@@ -90,12 +76,6 @@
var/stalk_tick_delay = 3
gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE
-/mob/living/simple_animal/hostile/snake/ListTargets()
- var/list/targets = list()
- for(var/mob/living/carbon/human/H in view(src, 10))
- targets += H
- return targets
-
/mob/living/simple_animal/hostile/snake/FindTarget()
. = ..()
if(.)
@@ -106,11 +86,3 @@
var/mob/living/L = .
if(istype(L))
L.apply_damage(rand(3,12), TOX)
-
-/mob/living/simple_animal/hostile/snake/AttackTarget()
- ..()
- if(stance == HOSTILE_STANCE_ATTACKING && get_dist(src, target))
- stalk_tick_delay -= 1
- if(stalk_tick_delay <= 0)
- src.loc = get_step_towards(src, target)
- stalk_tick_delay = 3
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
index 0d5d4b89772..5145a7c6a60 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
@@ -84,16 +84,12 @@
temperature = 50
/mob/living/simple_animal/hostile/asteroid/basilisk/GiveTarget(var/new_target)
- target = new_target
- if(target != null)
- Aggro()
- stance = HOSTILE_STANCE_ATTACK
+ if(..()) //we have a target
if(isliving(target))
var/mob/living/L = target
if(L.bodytemperature > 261)
L.bodytemperature = 261
visible_message("The [src.name]'s stare chills [L.name] to the bone!")
- return
/mob/living/simple_animal/hostile/asteroid/basilisk/ex_act(severity)
switch(severity)
@@ -156,17 +152,12 @@
if(target != null)
if(istype(target, /obj/item/weapon/ore))
visible_message("The [src.name] looks at [target.name] with hungry eyes.")
- stance = HOSTILE_STANCE_ATTACK
- return
- if(isliving(target))
+ else if(isliving(target))
Aggro()
- stance = HOSTILE_STANCE_ATTACK
visible_message("The [src.name] tries to flee from [target.name]!")
retreat_distance = 10
minimum_distance = 10
Burrow()
- return
- return
/mob/living/simple_animal/hostile/asteroid/goldgrub/AttackingTarget()
if(istype(target, /obj/item/weapon/ore))
@@ -387,7 +378,7 @@
/mob/living/simple_animal/hostile/asteroid/goliath/proc/handle_preattack()
if(ranged_cooldown <= 2 && !pre_attack)
pre_attack++
- if(!pre_attack || stat || stance == HOSTILE_STANCE_IDLE)
+ if(!pre_attack || stat || AIStatus == AI_IDLE)
return
icon_state = "Goliath_preattack"
@@ -511,4 +502,4 @@
to_chat(user, "You can't add armour onto the mech while someone is inside!")
else
to_chat(user, "You can't improve [D] any further!")
- return
\ No newline at end of file
+ return
diff --git a/code/modules/mob/living/simple_animal/hostile/poison_bees.dm b/code/modules/mob/living/simple_animal/hostile/poison_bees.dm
deleted file mode 100644
index c8a6a79fb04..00000000000
--- a/code/modules/mob/living/simple_animal/hostile/poison_bees.dm
+++ /dev/null
@@ -1,65 +0,0 @@
-/mob/living/simple_animal/hostile/poison/bees
- name = "space bee swarm"
- desc = ""
- icon_state = "bee_1"
- icon_living = "bee"
- speak_emote = list("buzzes")
- emote_hear = list("buzzes")
- turns_per_move = 0
- melee_damage_lower = 1
- melee_damage_upper = 1
- attacktext = "stings"
- response_help = "shoos"
- response_disarm = "swats away"
- response_harm = "squashes"
- maxHealth = 10
- health = 10
- faction = list("hostile")
- move_to_delay = 0
- environment_smash = 0
- mouse_opacity = 2
- pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
- flying = 1
-
- //Spaceborn beings don't get hurt by space
- atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
- minbodytemp = 0
- gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE
-
-/mob/living/simple_animal/hostile/poison/bees/Process_Spacemove(var/check_drift = 0)
- return 1
-
-/mob/living/simple_animal/hostile/poison/bees/New()
- ..()
- var/bees = rand(2, 10)
- for(var/i, i <= bees, i++)
- var/N = rand(1, 4)
- var/image/I = image(icon='icons/mob/animal.dmi',icon_state="bee_[N]", pixel_x = rand(-8, 8), pixel_y = rand(-8, 8))
- overlays += I
-
- //update_bees()
-
-/mob/living/simple_animal/hostile/poison/bees/death()
- ..()
- ghostize()
- qdel(src)
- return
-
-/*/mob/living/simple_animal/hostile/poison/bees/Life()
- ..()
-
- update_bees()
-
-/mob/living/simple_animal/hostile/poison/bees/proc/update_bees()
- while(overlays.len != health-1) //how many bees do we have in the swarm?
- var/N = rand(1, 4)
- var/image/I = image(icon='icons/mob/animal.dmi',icon_state="bee_[N]", pixel_x = rand(-8, 8), pixel_y = rand(-8, 8))
- if(overlays.len < health-1)
- overlays.Add(I)
- if(overlays.len > health-1)
- overlays.Remove(I) //REMOVING A RANDOM IMAGE FROM AN OVERLAYS LIST THAT DOES NOT CONTAIN THAT IMAGE
- poison_per_bite = health * 0.5 //each bee is half a toxin reagent //WHAT A GREAT FUCKING PLAN
- if(health > 1)
- desc = "A buzzy swarm of [health] poisonous space bees, renowned for their aggressiveness"
- else
- desc = "Although now lonely, this single space bee is still poisonous and very angry at you."*///NOVEL IDEA: INFINITE LOOP IMPLEMENTATION
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm
index 6cf9a8aec56..b9f04ec68ee 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm
@@ -5,19 +5,16 @@
if(isliving(A))
var/mob/living/L = A
if(!L.stat)
- stance = HOSTILE_STANCE_ATTACK
return L
else
enemies -= L
else if(istype(A, /obj/mecha))
var/obj/mecha/M = A
if(M.occupant)
- stance = HOSTILE_STANCE_ATTACK
return A
else if(istype(A, /obj/spacepod))
var/obj/spacepod/M = A
if(M.occupant || M.occupant2)
- stance = HOSTILE_STANCE_ATTACK
return A
/mob/living/simple_animal/hostile/retaliate/ListTargets()
@@ -72,4 +69,4 @@
for(var/dir in cardinal) // North, South, East, West
var/obj/structure/obstacle = locate(/obj/structure, get_step(src, dir))
if(istype(obstacle, /obj/structure/closet) || istype(obstacle, /obj/structure/table))
- obstacle.attack_animal(src)
\ No newline at end of file
+ obstacle.attack_animal(src)
diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm
index aeda42633a6..1c7836c0a13 100644
--- a/code/modules/mob/living/simple_animal/hostile/statue.dm
+++ b/code/modules/mob/living/simple_animal/hostile/statue.dm
@@ -70,9 +70,9 @@
return 0
return ..()
-
-/mob/living/simple_animal/hostile/statue/process_ai()
- ..()
+/mob/living/simple_animal/hostile/statue/handle_automated_action()
+ if(!..())
+ return
if(target) // If we have a target and we're AI controlled
var/mob/watching = can_be_seen()
// If they're not our target
@@ -211,11 +211,10 @@
name = "Toggle Nightvision \[OFF\]"
return
-
/mob/living/simple_animal/hostile/statue/sentience_act()
faction -= "neutral"
/mob/living/simple_animal/hostile/statue/restrained()
. = ..()
if(can_be_seen(loc))
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm
index 15ea3a5343f..43bdd538125 100644
--- a/code/modules/reagents/Chemistry-Machinery.dm
+++ b/code/modules/reagents/Chemistry-Machinery.dm
@@ -831,7 +831,8 @@
//All types that you can put into the grinder to transfer the reagents to the beaker. !Put all recipes above this.!
/obj/item/weapon/reagent_containers/food/pill = list(),
- /obj/item/weapon/reagent_containers/food = list()
+ /obj/item/weapon/reagent_containers/food = list(),
+ /obj/item/weapon/reagent_containers/honeycomb = list()
)
var/list/blend_tags = list (
diff --git a/code/modules/reagents/newchem/food.dm b/code/modules/reagents/newchem/food.dm
index ed65daca83a..6dd18d307f7 100644
--- a/code/modules/reagents/newchem/food.dm
+++ b/code/modules/reagents/newchem/food.dm
@@ -116,20 +116,17 @@ datum/reagent/vhfcs/on_mob_life(var/mob/living/M as mob)
id = "honey"
description = "A sweet substance produced by bees through partial digestion. Bee barf."
reagent_state = LIQUID
- color = "#CFCF1F"
+ color = "#d3a308"
datum/reagent/honey/on_mob_life(var/mob/living/M as mob)
- if(!M) M = holder.my_atom
+ if(!M)
+ M = holder.my_atom
M.reagents.add_reagent("sugar", 0.4)
+ if(prob(20))
+ M.heal_organ_damage(3,1)
..()
return
-datum/reagent/honey/reaction_turf(var/turf/T, var/volume)
- src = null
- if(volume >= 5)
- new /obj/item/weapon/reagent_containers/food/snacks/honeycomb(T)
- return
-
/datum/reagent/chocolate
name = "Chocolate"
id = "chocolate"
@@ -605,4 +602,4 @@ datum/reagent/pepperoni/reaction_mob(var/mob/living/M, var/method=TOUCH, var/vol
var/mob/living/carbon/human/H = M
if(!H.heart_attack)
H.heart_attack = 1
- ..()
\ No newline at end of file
+ ..()
diff --git a/code/modules/reagents/newchem/other.dm b/code/modules/reagents/newchem/other.dm
index 7cd45d056d3..c26d8bbe983 100644
--- a/code/modules/reagents/newchem/other.dm
+++ b/code/modules/reagents/newchem/other.dm
@@ -386,4 +386,22 @@ datum/reagent/triplepiss
id = "triplepiss"
description = "Ewwwwwwwww."
reagent_state = LIQUID
- color = "#857400"
\ No newline at end of file
+ color = "#857400"
+
+/datum/reagent/royal_bee_jelly
+ name = "royal bee jelly"
+ id = "royal_bee_jelly"
+ description = "Royal Bee Jelly, if injected into a Queen Space Bee said bee will split into two bees."
+ color = "#00ff80"
+
+/datum/reagent/royal_bee_jelly/on_mob_life(mob/living/M)
+ if(prob(2))
+ M.say(pick("Bzzz...","BZZ BZZ","Bzzzzzzzzzzz..."))
+ ..()
+
+/datum/chemical_reaction/royal_bee_jelly
+ name = "royal bee jelly"
+ id = "royal_bee_jelly"
+ result = "royal_bee_jelly"
+ required_reagents = list("mutagen" = 10, "honey" = 40)
+ result_amount = 5
\ No newline at end of file
diff --git a/code/modules/reagents/reagent_containers/glass_containers.dm b/code/modules/reagents/reagent_containers/glass_containers.dm
index 190b02c60d7..457f473c8bb 100644
--- a/code/modules/reagents/reagent_containers/glass_containers.dm
+++ b/code/modules/reagents/reagent_containers/glass_containers.dm
@@ -33,7 +33,6 @@
/obj/machinery/iv_drip,
/obj/machinery/computer/pandemic,
/obj/machinery/disposal,
- /obj/machinery/apiary,
/mob/living/simple_animal/cow,
/mob/living/simple_animal/hostile/retaliate/goat,
/obj/machinery/sleeper,
diff --git a/icons/mob/bees.dmi b/icons/mob/bees.dmi
new file mode 100644
index 00000000000..5d9bfea48b6
Binary files /dev/null and b/icons/mob/bees.dmi differ
diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi
index 38ce685a266..a67d328271e 100644
Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ
diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi
index c640d20334f..844d1b39b69 100644
Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ
diff --git a/icons/obj/apiary_bees.dmi b/icons/obj/apiary_bees.dmi
new file mode 100644
index 00000000000..df4cb0a0ac3
Binary files /dev/null and b/icons/obj/apiary_bees.dmi differ
diff --git a/icons/obj/apiary_bees_etc.dmi b/icons/obj/apiary_bees_etc.dmi
deleted file mode 100644
index de97e1a715a..00000000000
Binary files a/icons/obj/apiary_bees_etc.dmi and /dev/null differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index db2b15697bb..fafdcb56031 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi
index cd6ae3095a0..6b2732f13ed 100644
Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ
diff --git a/icons/obj/hydroponics_machines.dmi b/icons/obj/hydroponics_machines.dmi
index 1cc2998c531..cb3d548a6d9 100644
Binary files a/icons/obj/hydroponics_machines.dmi and b/icons/obj/hydroponics_machines.dmi differ
diff --git a/paradise.dme b/paradise.dme
index b962d51d018..5b4da54a732 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -474,7 +474,6 @@
#include "code\game\machinery\atmo_control.dm"
#include "code\game\machinery\autolathe.dm"
#include "code\game\machinery\Beacon.dm"
-#include "code\game\machinery\bees_items.dm"
#include "code\game\machinery\biogenerator.dm"
#include "code\game\machinery\buttons.dm"
#include "code\game\machinery\cell_charger.dm"
@@ -1304,11 +1303,14 @@
#include "code\modules\hydroponics\seed_mobs.dm"
#include "code\modules\hydroponics\seed_packets.dm"
#include "code\modules\hydroponics\seed_storage.dm"
+#include "code\modules\hydroponics\beekeeping\beebox.dm"
+#include "code\modules\hydroponics\beekeeping\beekeeper_suit.dm"
+#include "code\modules\hydroponics\beekeeping\honey_frame.dm"
+#include "code\modules\hydroponics\beekeeping\honeycomb.dm"
#include "code\modules\hydroponics\spreading\spreading.dm"
#include "code\modules\hydroponics\spreading\spreading_growth.dm"
#include "code\modules\hydroponics\spreading\spreading_response.dm"
#include "code\modules\hydroponics\trays\tray.dm"
-#include "code\modules\hydroponics\trays\tray_apiary.dm"
#include "code\modules\hydroponics\trays\tray_process.dm"
#include "code\modules\hydroponics\trays\tray_reagents.dm"
#include "code\modules\hydroponics\trays\tray_soil.dm"
@@ -1531,7 +1533,6 @@
#include "code\modules\mob\living\silicon\robot\drone\drone_items.dm"
#include "code\modules\mob\living\silicon\robot\drone\drone_manufacturer.dm"
#include "code\modules\mob\living\silicon\robot\drone\drone_say.dm"
-#include "code\modules\mob\living\simple_animal\bees.dm"
#include "code\modules\mob\living\simple_animal\constructs.dm"
#include "code\modules\mob\living\simple_animal\corpse.dm"
#include "code\modules\mob\living\simple_animal\parrot.dm"
@@ -1568,6 +1569,7 @@
#include "code\modules\mob\living\simple_animal\hostile\alien.dm"
#include "code\modules\mob\living\simple_animal\hostile\bat.dm"
#include "code\modules\mob\living\simple_animal\hostile\bear.dm"
+#include "code\modules\mob\living\simple_animal\hostile\bees.dm"
#include "code\modules\mob\living\simple_animal\hostile\carp.dm"
#include "code\modules\mob\living\simple_animal\hostile\creature.dm"
#include "code\modules\mob\living\simple_animal\hostile\faithless.dm"
@@ -1581,7 +1583,6 @@
#include "code\modules\mob\living\simple_animal\hostile\mining_mobs.dm"
#include "code\modules\mob\living\simple_animal\hostile\mushroom.dm"
#include "code\modules\mob\living\simple_animal\hostile\pirate.dm"
-#include "code\modules\mob\living\simple_animal\hostile\poison_bees.dm"
#include "code\modules\mob\living\simple_animal\hostile\russian.dm"
#include "code\modules\mob\living\simple_animal\hostile\spaceworms.dm"
#include "code\modules\mob\living\simple_animal\hostile\statue.dm"