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"