Merge pull request #4116 from TheDZD/NOTTHEBEES

It's the Bees!
This commit is contained in:
Fox McCloud
2016-04-14 21:27:01 -04:00
39 changed files with 784 additions and 730 deletions
+1 -7
View File
@@ -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
+18 -20
View File
@@ -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 ///////////////////////////////////////
@@ -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
return
-110
View File
@@ -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 = {"<html>
<head>
<style>
h1 {font-size: 18px; margin: 15px 0px 5px;}
h2 {font-size: 15px; margin: 15px 0px 5px;}
li {margin: 2px 0px 2px 15px;}
ul {list-style: none; margin: 5px; padding: 0px;}
ol {margin: 5px; padding: 0px 15px;}
</style>
</head>
<body>
<h3>Raising Bees</h3>
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.<br.
<br>
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.
</body>
</html>
"}
+1 -1
View File
@@ -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, "<span class='notice'>Now [anchored ? "un" : ""]securing [name].</span>")
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
@@ -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
@@ -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
@@ -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
@@ -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, "<span class='warning'>There is no queen bee! There won't bee any honeycomb without a queen!</span>")
var/half_bee = get_max_bees()*0.5
if(half_bee && (bees.len >= half_bee))
to_chat(user, "<span class='notice'>This place is a BUZZ with activity... there are lots of bees!</span>")
to_chat(user, "<span class='notice'>[bee_resources]/100 resource supply.</span>")
to_chat(user, "<span class='notice'>[bee_resources]% towards a new honeycomb.</span>")
to_chat(user, "<span class='notice'>[bee_resources*2]% towards a new bee.</span>")
if(honeycombs.len)
var/plural = honeycombs.len > 1
to_chat(user, "<span class='notice'>There [plural? "are" : "is"] [honeycombs.len] uncollected honeycomb[plural ? "s":""] in the apiary.</span>")
if(honeycombs.len >= get_max_honeycomb())
to_chat(user, "<span class='warning'>there's no room for more honeycomb!</span>")
/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("<span class='notice'>[user] adds a frame to the apiary.</span>")
user.unEquip(HF)
HF.forceMove(src)
honey_frames += HF
else
to_chat(user, "<span class='warning'>There's no room for anymore frames in the apiary!</span>")
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, "<span class='warning'>This hive already has a queen!</span>")
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("<span class='notice'>[user] sets [qb] down inside the apiary, making it their new home.</span>")
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, "<span class='warning'>This queen has a different reagent to some of the bees who live here, those bees will not return to this apiary!</span>")
else
to_chat(user, "<span class='warning'>The queen bee disappeared! bees disappearing has been in the news lately...</span>")
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("<span class='danger'>[user] disturbs the bees!</span>")
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, "<span class='warning'>There are no honey frames to remove!</span>")
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("<span class='notice'>[user] removes a frame from the apiary.</span>")
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("<span class='notice'>[user] scrapes [multiple ? "[fallen]" : "a"] honeycomb[multiple ? "s" : ""] off of the frame.</span>")
if("Remove the Queen Bee")
if(!queen_bee || queen_bee.loc != src)
to_chat(user, "<span class='warning'>There is no queen bee to remove!</span>")
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("<span class='notice'>[user] removes the queen from the apiary.</span>")
queen_bee = null
@@ -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)
@@ -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)
@@ -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()
+3 -14
View File
@@ -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, "<span class='danger'>[src] is already occupied!</span>")
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
holding = null
+2 -2
View File
@@ -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, "<span class='info'>[src] is moving around too much to repair!</span>")
return
if(maxHealth == health)
@@ -1061,4 +1061,4 @@
return ..()
C.preserved = 1
to_chat(user, "<span class='notice'>You inject the hivelord core with the stabilizer. It will no longer go inert.</span>")
qdel(src)
qdel(src)
@@ -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"*/
..()
@@ -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()
@@ -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
@@ -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, "<span class='warning'>This bee is homeless!</span>")
/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("<span class='notice'>[user] injects [src] with royal bee jelly, causing it to split into two bees, MORE BEES!</span>","<span class ='warning'>You inject [src] with royal bee jelly, causing it to split into two bees, MORE BEES!</span>")
else
to_chat(user, "<span class='warning'>You don't have enough royal bee jelly to split a bee in two!</span>")
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("<span class='warning'>[user] injects [src]'s genome with [R.name], mutating it's DNA!</span>","<span class='warning'>You inject [src]'s genome with [R.name], mutating it's DNA!</span>")
name = queen.name
else
to_chat(user, "<span class='warning'>You don't have enough units of that chemical to modify the bee's DNA!</span>")
..()
/obj/item/queen_bee/bought/New()
..()
queen = new(src)
/obj/item/queen_bee/Destroy()
qdel(queen)
return ..()
@@ -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
#undef SPINNING_COCOON
@@ -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()
warpbots()
@@ -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)
@@ -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("<span class='danger'>\the [src] knocks down \the [L]!</span>")
/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
@@ -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("<span class='danger'>The [src.name]'s stare chills [L.name] to the bone!</span>")
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("<span class='notice'>The [src.name] looks at [target.name] with hungry eyes.</span>")
stance = HOSTILE_STANCE_ATTACK
return
if(isliving(target))
else if(isliving(target))
Aggro()
stance = HOSTILE_STANCE_ATTACK
visible_message("<span class='danger'>The [src.name] tries to flee from [target.name]!</span>")
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, "<span class='warning'>You can't add armour onto the mech while someone is inside!</span>")
else
to_chat(user, "<span class='warning'>You can't improve [D] any further!</span>")
return
return
@@ -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
@@ -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)
obstacle.attack_animal(src)
@@ -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
return 1
+2 -1
View File
@@ -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 (
+6 -9
View File
@@ -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
..()
..()
+19 -1
View File
@@ -386,4 +386,22 @@ datum/reagent/triplepiss
id = "triplepiss"
description = "Ewwwwwwwww."
reagent_state = LIQUID
color = "#857400"
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
@@ -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,
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 KiB

After

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 457 KiB

After

Width:  |  Height:  |  Size: 458 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 14 KiB

+5 -4
View File
@@ -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"