diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 02e71c0f08f..365e3ade3f6 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -704,15 +704,13 @@
/obj/structure/closet/crate/necropolis/bubblegum/New()
..()
- var/loot = rand(1,4)
+ var/loot = rand(1,3)
switch(loot)
if(1)
- new /obj/item/weapon/antag_spawner/slaughter_demon(src)
- if(2)
new /obj/item/mayhem(src)
- if(3)
+ if(2)
new /obj/item/blood_contract(src)
- if(4)
+ if(3)
new /obj/item/weapon/gun/magic/staff/spellblade(src)
/obj/item/blood_contract
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
index f961094c4c9..b64463f3b7c 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
@@ -9,15 +9,15 @@ Bubblegum's footsteps are heralded by shaking booms, proving its tremendous size
It acts as a melee creature, chasing down and attacking its target while also using different attacks to augment its power that increase as it takes damage.
-It often charges, dealing massive damage to anything unfortunate enough to be standing where it's aiming.
-Whenever it isn't chasing something down, it will sink into nearby blood pools (if possible) and springs out of the closest one to its target.
-To make this possible, it sprays streams of blood at random.
-From these blood pools Bubblegum may summon slaughterlings - weak, low-damage minions designed to impede the target's progress.
+It tries to strike at its target through any bloodpools under them; if it fails to do that, it will spray blood and then attempt to warp to a bloodpool near the target.
+If it fails to warp to a target, it may summon up to 6 slaughterlings from the blood around it.
+If it does not summon all 6 slaughterlings, it will instead charge at its target, dealing massive damage to anything it hits and spraying a stream of blood.
+At half health, it will either charge three times or warp, then charge, instead of doing a single charge.
When Bubblegum dies, it leaves behind a chest that can contain three things:
- 1. A slaughter demon spawner
- 2. A bottle that, when activated, drives everyone nearby into a frenzy
- 3. A contract that marks for death the chosen target
+ 1. A bottle that, when activated, drives everyone nearby into a frenzy
+ 2. A contract that marks for death the chosen target
+ 3. A spellblade that can slice off limbs at range
Difficulty: Hard
@@ -45,6 +45,7 @@ Difficulty: Hard
pixel_x = -32
del_on_death = 1
loot = list(/obj/structure/closet/crate/necropolis/bubblegum)
+ blood_volume = BLOOD_VOLUME_MAXIMUM //BLEED FOR ME
var/charging = 0
medal_type = MEDAL_PREFIX
score_type = BUBBLEGUM_SCORE
@@ -57,6 +58,12 @@ Difficulty: Hard
desc = "You're not quite sure how a signal can be bloody."
invisibility = 100
+/mob/living/simple_animal/hostile/megafauna/bubblegum/adjustBruteLoss(amount)
+ if(amount > 0 && prob(33))
+ var/obj/effect/decal/cleanable/blood/B = new /obj/effect/decal/cleanable/blood(loc)
+ B.bloodiness = 20
+ . = ..()
+
/mob/living/simple_animal/hostile/megafauna/bubblegum/Life()
..()
move_to_delay = Clamp(round((health/maxHealth) * 10), 5, 10)
@@ -67,18 +74,21 @@ Difficulty: Hard
return
ranged_cooldown = world.time + ranged_cooldown_time
- blood_warp()
-
- if(prob(25))
+ var/warped = FALSE
+ if(!try_bloodattack())
addtimer(src, "blood_spray", 0)
+ warped = blood_warp()
+ if(warped && prob(100 - anger_modifier))
+ return
- else if(prob(5+anger_modifier/2))
- slaughterlings()
- else
- if(health > maxHealth/2 && !client)
+ if(prob(90 - anger_modifier) || slaughterlings())
+ if(health > maxHealth * 0.5 || client)
addtimer(src, "charge", 0)
else
- addtimer(src, "triple_charge", 0)
+ if(prob(70) || warped)
+ addtimer(src, "triple_charge", 0)
+ else
+ addtimer(src, "warp_charge", 0)
/mob/living/simple_animal/hostile/megafauna/bubblegum/New()
@@ -109,20 +119,22 @@ Difficulty: Hard
..()
/mob/living/simple_animal/hostile/megafauna/bubblegum/Move()
- if(!stat)
- playsound(src.loc, 'sound/effects/meteorimpact.ogg', 200, 1, 2, 1)
if(charging)
PoolOrNew(/obj/effect/overlay/temp/decoy/fading, list(loc,src))
DestroySurroundings()
. = ..()
+ if(!stat && .)
+ playsound(src, 'sound/effects/meteorimpact.ogg', 200, 1, 2, 1)
if(charging)
DestroySurroundings()
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/warp_charge()
+ blood_warp()
+ charge()
+
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/triple_charge()
charge()
- sleep(10)
charge()
- sleep(10)
charge()
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge()
@@ -139,6 +151,7 @@ Difficulty: Hard
sleep(5)
throw_at(T, get_dist(src, T), 1, src, 0)
charging = 0
+ try_bloodattack()
Goto(target, move_to_delay, minimum_distance)
@@ -166,17 +179,132 @@ Difficulty: Hard
charging = 0
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_mobs_on_blood()
+ var/list/targets = ListTargets()
+ . = list()
+ for(var/mob/living/L in targets)
+ var/list/bloodpool = get_pools(get_turf(L), 0)
+ if(bloodpool.len && !faction_check(L))
+ . += L
+
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/try_bloodattack()
+ var/list/targets = get_mobs_on_blood()
+ if(targets.len)
+ addtimer(src, "bloodattack", 0, FALSE, targets)
+
+ return TRUE
+ return FALSE
+
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodattack(list/targets)
+ var/mob/living/target_one = pick_n_take(targets)
+ var/turf/target_one_turf = get_turf(target_one)
+ var/mob/living/target_two
+ if(targets.len)
+ target_two = pick_n_take(targets)
+ var/turf/target_two_turf = get_turf(target_two)
+ if(target_two.stat != CONSCIOUS || prob(10))
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightpaw, target_two_turf)
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightthumb, target_two_turf)
+ bloodgrab(target_two_turf)
+ else
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightsmack, target_two_turf)
+ bloodsmack(target_two_turf)
+
+ var/list/pools = get_pools(get_turf(target_one), 0)
+ if(pools.len)
+ target_one_turf = get_turf(target_one)
+ if(target_one.stat != CONSCIOUS || prob(10))
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/leftpaw, target_one_turf)
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/leftthumb, target_one_turf)
+ bloodgrab(target_one_turf)
+ else
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/leftsmack, target_one_turf)
+ bloodsmack(target_one_turf)
+
+ if(!target_two && target_one)
+ pools = get_pools(get_turf(target_one), 0)
+ if(pools.len)
+ target_one_turf = get_turf(target_one)
+ if(target_one.stat != CONSCIOUS || prob(10))
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightpaw, target_one_turf)
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightthumb, target_one_turf)
+ bloodgrab(target_one_turf)
+ else
+ PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightsmack, target_one_turf)
+ bloodsmack(target_one_turf)
+
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodsmack(turf/T)
+ sleep(2.5)
+ for(var/mob/living/L in T)
+ if(!faction_check(L))
+ L << "[src] rends you!"
+ playsound(T, attack_sound, 100, 1, -1)
+ var/limb_to_hit = L.get_bodypart(pick("head", "chest", "r_arm", "l_arm", "r_leg", "l_leg"))
+ L.apply_damage(25, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, "melee", null, null, armour_penetration))
+ sleep(3)
+
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodgrab(turf/T)
+ sleep(6)
+ for(var/mob/living/L in T)
+ if(!faction_check(L))
+ L << "[src] drags you through the blood!"
+ playsound(T, 'sound/magic/enter_blood.ogg', 100, 1, -1)
+ var/turf/targetturf = get_step(src, dir)
+ L.forceMove(targetturf)
+ playsound(targetturf, 'sound/magic/exit_blood.ogg', 100, 1, -1)
+ if(L.stat != CONSCIOUS)
+ addtimer(src, "devour", 2, FALSE, L)
+ sleep(1)
+
+/obj/effect/overlay/temp/bubblegum_hands
+ icon = 'icons/effects/bubblegum.dmi'
+ duration = 9
+
+/obj/effect/overlay/temp/bubblegum_hands/rightthumb
+ icon_state = "rightthumbgrab"
+
+/obj/effect/overlay/temp/bubblegum_hands/leftthumb
+ icon_state = "leftthumbgrab"
+
+/obj/effect/overlay/temp/bubblegum_hands/rightpaw
+ icon_state = "rightpawgrab"
+ layer = BELOW_MOB_LAYER
+
+/obj/effect/overlay/temp/bubblegum_hands/leftpaw
+ icon_state = "leftpawgrab"
+ layer = BELOW_MOB_LAYER
+
+/obj/effect/overlay/temp/bubblegum_hands/rightsmack
+ icon_state = "rightsmack"
+
+/obj/effect/overlay/temp/bubblegum_hands/leftsmack
+ icon_state = "leftsmack"
+
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_warp()
+ if(Adjacent(target))
+ return FALSE
+ var/list/can_jaunt = get_pools(get_turf(src), 1)
+ if(!can_jaunt.len)
+ return FALSE
+
+ var/list/pools = get_pools(get_turf(target), 2)
+ var/list/pools_to_remove = get_pools(get_turf(target), 1)
+ pools -= pools_to_remove
+ if(!pools.len)
+ return FALSE
+
+ var/obj/effect/overlay/temp/decoy/DA = PoolOrNew(/obj/effect/overlay/temp/decoy, list(loc,src))
+ DA.color = "#FF0000"
+ var/oldtransform = DA.transform
+ DA.transform = matrix()*2
+ animate(DA, alpha = 255, color = initial(DA.color), transform = oldtransform, time = 5)
+ sleep(5)
+ qdel(DA)
+
var/obj/effect/decal/cleanable/blood/found_bloodpool
- var/list/pools = list()
- var/can_jaunt = FALSE
- for(var/obj/effect/decal/cleanable/blood/nearby in view(src,2))
- can_jaunt = TRUE
- break
- if(!can_jaunt)
- return
- for(var/obj/effect/decal/cleanable/blood/nearby in view(get_turf(target),2))
- pools += nearby
+ pools = get_pools(get_turf(target), 2)
+ pools_to_remove = get_pools(get_turf(target), 1)
+ pools -= pools_to_remove
if(pools.len)
shuffle(pools)
found_bloodpool = pick(pools)
@@ -186,35 +314,56 @@ Difficulty: Hard
forceMove(get_turf(found_bloodpool))
playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
visible_message("And springs back out!")
+ return TRUE
+ return FALSE
+/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_pools(turf/T, range)
+ . = list()
+ for(var/obj/effect/decal/cleanable/blood/nearby in view(T, range))
+ . += nearby
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_spray()
visible_message("[src] sprays a stream of gore!")
- var/turf/E = get_edge_target_turf(src, src.dir)
- var/range = 10
+ var/range = 6 + round(anger_modifier * 0.4)
var/turf/previousturf = get_turf(src)
- for(var/turf/J in getline(src,E))
- if(!range)
- break
+ var/turf/J = previousturf
+ var/targetdir = get_dir(src, target)
+ if(target.loc == loc)
+ targetdir = dir
+ face_atom(target)
+ new /obj/effect/decal/cleanable/blood(J)
+ for(var/i in 1 to range)
+ J = get_step(previousturf, targetdir)
PoolOrNew(/obj/effect/overlay/temp/dir_setting/bloodsplatter, list(previousturf, get_dir(previousturf, J)))
- if(!previousturf.CanAtmosPass(J))
+ playsound(previousturf,'sound/effects/splat.ogg', 100, 1, -1)
+ if(!J || !previousturf.CanAtmosPass(J))
break
- playsound(J,'sound/effects/splat.ogg', 100, 1, -1)
- new /obj/effect/decal/cleanable/blood(J)
- range--
+ var/obj/effect/decal/cleanable/blood/B = new /obj/effect/decal/cleanable/blood(J)
+ B.bloodiness = 0
previousturf = J
sleep(1)
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/slaughterlings()
visible_message("[src] summons a shoal of slaughterlings!")
- for(var/obj/effect/decal/cleanable/blood/H in range(src, 10))
- if(prob(25))
- new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter(H.loc)
+ var/max_amount = 6
+ for(var/H in get_pools(get_turf(src), 1))
+ if(!max_amount)
+ break
+ max_amount--
+ var/obj/effect/decal/cleanable/blood/B = H
+ new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter(B.loc)
+ return max_amount
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter
name = "slaughterling"
desc = "Though not yet strong enough to create a true physical form, it's nonetheless determined to murder you."
- faction = list("mining")
+ density = 0
+ faction = list("mining", "boss")
weather_immunities = list("lava","ash")
+/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter/CanPass(atom/movable/mover, turf/target, height = 0)
+ if(istype(mover, /mob/living/simple_animal/hostile/megafauna/bubblegum))
+ return 1
+ return 0
+
#undef MEDAL_PREFIX
\ No newline at end of file
diff --git a/icons/effects/bubblegum.dmi b/icons/effects/bubblegum.dmi
new file mode 100644
index 00000000000..a53dd7d563a
Binary files /dev/null and b/icons/effects/bubblegum.dmi differ