mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-30 16:38:22 +01:00
Refactored (second passage) how movement works, now it's mostly in line with TG handling and avoids calling 3 gazillion Cross() Uncross() etc. on every atom in a turf. Fixed EMP protection from species not actually protecting (this includes the surge prevention for IPCs). Fixed EMP 3D calculation runtiming because I forgot to make the value absolute and it was doing the square root of a negative number. It's now possible to queue the round to start with the Start Round verb even while the system is initializing, for an even faster pain train to enter the round and test things.
294 lines
9.3 KiB
Plaintext
294 lines
9.3 KiB
Plaintext
//Bees are spawned from an apiary, and will slowly die if it is destroyed.
|
|
|
|
/mob/living/simple_animal/bee
|
|
name = "bees"
|
|
icon = 'icons/obj/beekeeping.dmi'
|
|
icon_state = "bees1"
|
|
icon_dead = "bees1"
|
|
mob_size = 0.5
|
|
unsuitable_atoms_damage = 2.5
|
|
maxHealth = 20
|
|
density = 0
|
|
var/strength = 1
|
|
var/feral = 0
|
|
var/mut = 0
|
|
var/toxic = 0
|
|
var/turf/target_turf
|
|
var/mob/target_mob
|
|
var/obj/machinery/beehive/parent
|
|
var/loner = 0
|
|
pass_flags = PASSTABLE | PASSRAILING
|
|
turns_per_move = 6
|
|
var/obj/machinery/portable_atmospherics/hydroponics/my_hydrotray
|
|
emote_sounds = list('sound/effects/creatures/bees.ogg')
|
|
|
|
/mob/living/simple_animal/bee/Initialize(mapload, var/obj/machinery/beehive/new_parent)
|
|
. = ..()
|
|
parent = new_parent
|
|
|
|
/mob/living/simple_animal/bee/Destroy()
|
|
if(parent)
|
|
parent.owned_bee_swarms.Remove(src)
|
|
my_hydrotray = null
|
|
parent = null
|
|
target_turf = null
|
|
target_mob = null
|
|
return ..()
|
|
|
|
/mob/living/simple_animal/bee/can_name(var/mob/living/M)
|
|
return FALSE
|
|
|
|
//Special death behaviour. When bees accumulate enough damage to 'die', they don't outright die. Thus no call to parent
|
|
//Instead the swarm strength (ie, size, or quantity of bees) drops and their health is refilled
|
|
//Repeat until strength hits zero. only THEN do they die, and they qdel and leave no corpse in doing so
|
|
//Because we don't have sprites for a carpet made of bee corpses.
|
|
/mob/living/simple_animal/bee/death()
|
|
if (!QDELING(src))
|
|
strength -= 1
|
|
if (strength <= 0)
|
|
if (prob(25))//probability to reduce spam
|
|
src.visible_message(SPAN_WARNING("The bee swarm completely dissipates."))
|
|
qdel(src)
|
|
return
|
|
else
|
|
health = maxHealth
|
|
if (prob(25))//probability to reduce spam
|
|
src.visible_message(SPAN_WARNING("The bee swarm starts to thin out a little."))
|
|
|
|
update_icon()
|
|
else
|
|
..()
|
|
|
|
/mob/living/simple_animal/bee/Life(seconds_per_tick, times_fired)
|
|
if(!loner && strength && !parent && prob(7-strength))
|
|
strength -= 1
|
|
|
|
if(strength <= 0)
|
|
death()
|
|
else
|
|
update_icon()
|
|
|
|
..()
|
|
|
|
/mob/living/simple_animal/bee/proc/verify_stingable(var/mob/living/M)
|
|
if(M.isSynthetic()) //Can't sting robots, unfortunately
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/mob/living/simple_animal/bee/proc/do_sting()
|
|
//if we're strong enough, sting some people
|
|
var/mob/living/carbon/human/M = target_mob
|
|
if(!verify_stingable(M)) //If we can't sting this, why is it our target?
|
|
target_mob = null
|
|
return FALSE
|
|
var/sting_prob = 40 // Bees will always try to sting.
|
|
var/prob_mult = 1
|
|
if(Adjacent(M)) //Can I reach my target?
|
|
var/obj/item/clothing/worn_suit = M.wear_suit
|
|
var/obj/item/clothing/worn_helmet = M.head
|
|
if(worn_suit) // Are you wearing clothes?
|
|
if ((worn_suit.item_flags & ITEM_FLAG_THICK_MATERIAL))
|
|
prob_mult -= 0.7
|
|
else
|
|
prob_mult -= 0.01 * (min(LAZYACCESS(worn_suit.armor, BIO), 70)) // Is it sealed? I can't get to 70% of your body.
|
|
if(worn_helmet)
|
|
if ((worn_helmet.item_flags & ITEM_FLAG_THICK_MATERIAL))
|
|
prob_mult -= 0.3
|
|
else
|
|
prob_mult -= 0.01 *(min(LAZYACCESS(worn_helmet.armor, BIO), 30))// Is your helmet sealed? I can't get to 30% of your body.
|
|
if( prob(sting_prob*prob_mult) && (M.stat == CONSCIOUS || (M.stat == UNCONSCIOUS && prob(25*prob_mult))) ) // Try to sting! If you're not moving, think about stinging.
|
|
M.apply_damage(min(strength*0.85,2)+mut, DAMAGE_BURN, damage_flags = DAMAGE_FLAG_SHARP) // Stinging. The more mutated I am, the harder I sting.
|
|
var/venom_strength = max(strength*0.2, (round(feral/10,1) * (max(round(strength/20,1), 1)))) + toxic // Bee venom based on how angry I am and how many there are of me!
|
|
M.apply_damage(venom_strength, DAMAGE_PAIN) //Bee venom causes pain, not organ failure
|
|
if(prob(max(80, strength * 10))) //If there's enough of a swarm, it can also cause breathing trouble. Yes, even without being allergic.
|
|
M.apply_damage(venom_strength, DAMAGE_OXY)
|
|
update_icon()
|
|
to_chat(M, SPAN_WARNING("You have been stung!"))
|
|
M.flash_pain(5)
|
|
else
|
|
step_to(src, target_mob)
|
|
|
|
/mob/living/simple_animal/bee/think()
|
|
..()
|
|
if (stat != CONSCIOUS)
|
|
return
|
|
|
|
if(target_mob)
|
|
do_sting()
|
|
|
|
//calm down a little bit
|
|
if(feral > 0 && !target_mob)
|
|
if(prob(feral * 20))
|
|
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(src))
|
|
B.strength = rand(1,5)
|
|
strength -= B.strength
|
|
update_icon()
|
|
B.update_icon()
|
|
if(parent)
|
|
B.parent = parent
|
|
parent.owned_bee_swarms.Add(B)
|
|
|
|
//make some noise
|
|
if(prob(2))
|
|
src.audible_message("[SPAN_BOLD("\The [src]")] [pick("buzz", "hum")].")
|
|
playsound(src, pick('sound/effects/Buzz1.ogg', 'sound/effects/Buzz2.ogg'), 10, TRUE, -4)
|
|
|
|
if (feral && isturf(loc))
|
|
//smoke, water and steam calms us down
|
|
var/static/list/calmers = typecacheof(list(
|
|
/obj/effect/smoke,
|
|
/obj/effect/effect/water,
|
|
/obj/effect/effect/foam,
|
|
/obj/effect/effect/steam,
|
|
/obj/effect/mist
|
|
))
|
|
|
|
if(range_in_typecache(src, 2, calmers))
|
|
if(feral > 0)
|
|
src.visible_message(SPAN_NOTICE("The bees calm down!"))
|
|
feral = -15
|
|
target_mob = null
|
|
target_turf = null
|
|
wander = TRUE
|
|
|
|
for(var/mob/living/simple_animal/bee/B in src.loc)
|
|
if(B == src)
|
|
continue
|
|
|
|
if(feral > 0 && prob(50)) //We'll combine into a stronger swarm if this passes
|
|
if(B.strength > strength) //This is so that we'll take the toxic and mut values of the larger swarm, as that will be the majority of bees. If B is smaller, we keep ours.
|
|
mut = B.mut
|
|
toxic = B.toxic
|
|
strength += B.strength
|
|
B.strength = 0
|
|
qdel(B) //We've absorbed the other bees, they're gone. Qdel here to avoid spamming disipate messages
|
|
update_icon()
|
|
|
|
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)
|
|
strength = total_bees - B.strength
|
|
|
|
update_icon()
|
|
B.update_icon()
|
|
if(strength <= 0)
|
|
qdel(src)
|
|
return
|
|
var/turf/simulated/floor/T = get_step(src, pick(GLOB.cardinals))
|
|
if(istype(T))
|
|
Move(T)
|
|
break
|
|
|
|
if(target_mob)//If we have a target
|
|
if(target_mob in view(5, src))//Check that we can still see them
|
|
target_turf = get_turf(target_mob)//If so, update the location
|
|
wander = FALSE
|
|
else//Otherwise, if our target is out of view, we clear them so we can pick a new one in the next step
|
|
target_mob = null
|
|
target_turf = null
|
|
wander = TRUE
|
|
|
|
//If we're angry but have no target, lets search for one
|
|
if (!target_mob && feral)
|
|
for(var/mob/living/carbon/G in view(src,7))
|
|
if(verify_stingable(G))
|
|
target_mob = G
|
|
break
|
|
|
|
//if we're chasing someone, get a little bit angry
|
|
if(target_mob && prob(5))
|
|
feral++
|
|
|
|
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(10))
|
|
visible_message(SPAN_NOTICE("The bees swarm after [target_mob]!"))
|
|
if(get_turf(src) == target_turf)
|
|
target_turf = null
|
|
wander = TRUE
|
|
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
|
|
|
|
animate(src, pixel_x = rand(-12, 12), pixel_y = rand(-12, 12), time = 0.5)
|
|
|
|
|
|
/mob/living/simple_animal/bee/update_icon()
|
|
if(strength <= 5)
|
|
icon_state = "bees[round(strength,1)]"
|
|
else
|
|
icon_state = "bees_swarm"
|
|
|
|
//Kill it with fire!
|
|
/mob/living/simple_animal/bee/adjustFireLoss(damage)
|
|
..(damage * 2)
|
|
|
|
|
|
//No more grabbing bee swarms
|
|
/mob/living/simple_animal/bee/attempt_grab(var/mob/living/grabber)
|
|
if (prob(strength*5))//if the swarm is big you might grab a few bees, you won't make a serious dent
|
|
to_chat(grabber, "<span class = 'warning'>You attempt to grab the swarm, but only manage to snatch a scant handful of crushed bees.</span>")
|
|
apply_damage(strength*0.5, DAMAGE_BRUTE, used_weapon = "Crushing by [grabber.name]")
|
|
else
|
|
to_chat(grabber, "<span class = 'warning'>For some bizarre reason known only to yourself, you attempt to grab ahold of the swarm of bees. You come away with nothing but empty, slightly stung hands.</span>")
|
|
if(verify_stingable(grabber))
|
|
grabber.apply_damage(strength*0.5, DAMAGE_BURN)
|
|
|
|
return 0
|
|
|
|
/mob/living/simple_animal/bee/attempt_pull(var/mob/living/grabber)
|
|
return attempt_grab(grabber)
|
|
|
|
/mob/living/simple_animal/bee/can_fall()
|
|
return FALSE
|
|
|
|
/mob/living/simple_animal/bee/can_ztravel()
|
|
return TRUE
|
|
|
|
/mob/living/simple_animal/bee/CanAvoidGravity()
|
|
return TRUE
|
|
|
|
//Bee for spawning as a hostile mob, it wont fade without a hive
|
|
/mob/living/simple_animal/bee/standalone
|
|
loner = 1
|
|
|
|
/mob/living/simple_animal/bee/standalone/Initialize(mapload, var/obj/machinery/beehive/new_parent)
|
|
. = ..()
|
|
strength = rand(4,8)
|
|
update_icon()
|
|
|
|
/mob/living/simple_animal/bee/beegun
|
|
maxHealth = 30
|
|
strength = 5
|
|
feral = 30
|
|
|
|
/mob/living/simple_animal/bee/beegun/Initialize()
|
|
. = ..()
|
|
mut = rand(0, 1) //We're creating bees out of energy. They have a chance of being mutated...
|
|
toxic = rand(0, 1) //...or slightly more toxic
|