Merge branch 'master' into spellcheck

This commit is contained in:
ShizCalev
2018-06-26 16:43:41 -04:00
committed by GitHub
186 changed files with 2073 additions and 1570 deletions
+1 -1
View File
@@ -11,7 +11,7 @@
var/motd = global.config.motd
if(motd)
to_chat(src, "<div class=\"motd\">[motd]</div>")
to_chat(src, "<div class=\"motd\">[motd]</div>", handle_whitespace=FALSE)
if(GLOB.admin_notice)
to_chat(src, "<span class='notice'><b>Admin Notice:</b>\n \t [GLOB.admin_notice]</span>")
@@ -137,3 +137,6 @@
update_inv_wear_mask()
update_inv_head()
/mob/living/carbon/proc/get_holding_bodypart_of_item(obj/item/I)
var/index = get_held_index_of_item(I)
return index && hand_bodyparts[index]
+1 -1
View File
@@ -54,7 +54,7 @@
var/turf/T = get_turf(src)
for(var/obj/item/I in contents)
I.on_mob_death(src, gibbed)
if(mind && mind.name && mind.active && (!(T.flags_1 & NO_DEATHRATTLE_1)))
if(mind && mind.name && mind.active && !istype(T.loc, /area/ctf))
var/rendered = "<span class='deadsay'><b>[mind.name]</b> has died at <b>[get_area_name(T)]</b>.</span>"
deadchat_broadcast(rendered, follow_target = src, turf_target = T, message_type=DEADCHAT_DEATHRATTLE)
if(mind)
@@ -18,12 +18,21 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
// The object used for the clickable stat() button.
var/obj/effect/statclick/statclick
// The object used in vis_contents of obscured turfs
var/vis_contents
// The image given to the effect in vis_contents on AI clients
var/image/obscured
/datum/cameranet/New()
vis_contents = new /obj/effect/overlay/camera_static()
obscured = new('icons/effects/cameravis.dmi', vis_contents, null, BYOND_LIGHTING_LAYER + 0.1)
obscured.plane = BYOND_LIGHTING_PLANE + 1
// Checks if a chunk has been Generated in x, y, z.
/datum/cameranet/proc/chunkGenerated(x, y, z)
x &= ~(CHUNK_SIZE - 1)
y &= ~(CHUNK_SIZE - 1)
var/key = "[x],[y],[z]"
return (chunks[key])
return chunks["[x],[y],[z]"]
// Returns the chunk in the x, y, z.
// If there is no chunk, it creates a new chunk and returns that.
@@ -31,10 +40,9 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
x &= ~(CHUNK_SIZE - 1)
y &= ~(CHUNK_SIZE - 1)
var/key = "[x],[y],[z]"
if(!chunks[key])
chunks[key] = new /datum/camerachunk(null, x, y, z)
return chunks[key]
. = chunks[key]
if(!.)
chunks[key] = . = new /datum/camerachunk(x, y, z)
// Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set.
@@ -46,14 +54,8 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
else
other_eyes = list()
var/list/chunks_pre_seen = list()
var/list/chunks_post_seen = list()
for(var/V in moved_eyes)
var/mob/camera/aiEye/eye = V
if(C)
chunks_pre_seen |= eye.visibleCameraChunks
// 0xf = 15
var/static_range = eye.static_visibility_range
var/x1 = max(0, eye.x - static_range) & ~(CHUNK_SIZE - 1)
var/y1 = max(0, eye.y - static_range) & ~(CHUNK_SIZE - 1)
@@ -71,44 +73,26 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
for(var/chunk in remove)
var/datum/camerachunk/c = chunk
c.remove(eye, FALSE)
c.remove(eye)
for(var/chunk in add)
var/datum/camerachunk/c = chunk
c.add(eye, FALSE)
if(C)
chunks_post_seen |= eye.visibleCameraChunks
c.add(eye)
if(C)
for(var/V in other_eyes)
var/mob/camera/aiEye/eye = V
chunks_post_seen |= eye.visibleCameraChunks
var/list/remove = chunks_pre_seen - chunks_post_seen
var/list/add = chunks_post_seen - chunks_pre_seen
for(var/chunk in remove)
var/datum/camerachunk/c = chunk
C.images -= c.obscured
for(var/chunk in add)
var/datum/camerachunk/c = chunk
C.images += c.obscured
C.images += obscured
// Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open.
/datum/cameranet/proc/updateVisibility(atom/A, opacity_check = 1)
if(!SSticker || (opacity_check && !A.opacity))
return
majorChunkChange(A, 2)
/datum/cameranet/proc/updateChunk(x, y, z)
// 0xf = 15
if(!chunkGenerated(x, y, z))
var/datum/camerachunk/chunk = chunkGenerated(x, y, z)
if (!chunk)
return
var/datum/camerachunk/chunk = getCameraChunk(x, y, z)
chunk.hasChanged()
// Removes a camera from a chunk.
@@ -135,7 +119,6 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
// If you want to update the chunks around an object, without adding/removing a camera, use choice 2.
/datum/cameranet/proc/majorChunkChange(atom/c, choice)
// 0xf = 15
if(!c)
return
@@ -147,8 +130,8 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
var/y2 = min(world.maxy, T.y + (CHUNK_SIZE / 2)) & ~(CHUNK_SIZE - 1)
for(var/x = x1; x <= x2; x += CHUNK_SIZE)
for(var/y = y1; y <= y2; y += CHUNK_SIZE)
if(chunkGenerated(x, y, T.z))
var/datum/camerachunk/chunk = getCameraChunk(x, y, T.z)
var/datum/camerachunk/chunk = chunkGenerated(x, y, T.z)
if(chunk)
if(choice == 0)
// Remove the camera.
chunk.cameras -= c
@@ -160,14 +143,12 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
// Will check if a mob is on a viewable turf. Returns 1 if it is, otherwise returns 0.
/datum/cameranet/proc/checkCameraVis(mob/living/target)
// 0xf = 15
var/turf/position = get_turf(target)
return checkTurfVis(position)
/datum/cameranet/proc/checkTurfVis(turf/position)
var/datum/camerachunk/chunk = getCameraChunk(position.x, position.y, position.z)
var/datum/camerachunk/chunk = chunkGenerated(position.x, position.y, position.z)
if(chunk)
if(chunk.changed)
chunk.hasChanged(1) // Update now, no matter if it's visible or not.
@@ -180,3 +161,17 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
stat(name, statclick.update("Cameras: [GLOB.cameranet.cameras.len] | Chunks: [GLOB.cameranet.chunks.len]"))
/obj/effect/overlay/camera_static
name = "static"
icon = null
icon_state = null
anchored = TRUE // should only appear in vis_contents, but to be safe
appearance_flags = RESET_TRANSFORM | TILE_BOUND
// this combination makes the static block clicks to everything below it,
// without appearing in the right-click menu for non-AI clients
mouse_opacity = MOUSE_OPACITY_ICON
invisibility = INVISIBILITY_ABSTRACT
layer = BYOND_LIGHTING_LAYER + 0.1
plane = BYOND_LIGHTING_PLANE + 1
@@ -8,11 +8,9 @@
/datum/camerachunk
var/list/obscuredTurfs = list()
var/list/visibleTurfs = list()
var/list/obscured = list()
var/list/cameras = list()
var/list/turfs = list()
var/list/seenby = list()
var/visible = FALSE
var/changed = 0
var/x = 0
var/y = 0
@@ -20,28 +18,17 @@
// Add an AI eye to the chunk, then update if changed.
/datum/camerachunk/proc/add(mob/camera/aiEye/eye, add_images = TRUE)
if(add_images)
var/client/client = eye.GetViewerClient()
if(client)
client.images += obscured
/datum/camerachunk/proc/add(mob/camera/aiEye/eye)
eye.visibleCameraChunks += src
visible++
seenby += eye
if(changed)
update()
// Remove an AI eye from the chunk, then update if changed.
/datum/camerachunk/proc/remove(mob/camera/aiEye/eye, remove_images = TRUE)
if(remove_images)
var/client/client = eye.GetViewerClient()
if(client)
client.images -= obscured
/datum/camerachunk/proc/remove(mob/camera/aiEye/eye)
eye.visibleCameraChunks -= src
seenby -= eye
if(visible > 0)
visible--
// Called when a chunk has changed. I.E: A wall was deleted.
@@ -54,7 +41,7 @@
// instead be flagged to update the next time an AI Eye moves near it.
/datum/camerachunk/proc/hasChanged(update_now = 0)
if(visible || update_now)
if(seenby.len || update_now)
addtimer(CALLBACK(src, .proc/update), UPDATE_BUFFER, TIMER_UNIQUE)
else
changed = 1
@@ -94,41 +81,18 @@
for(var/turf in visAdded)
var/turf/t = turf
if(t.obscured)
obscured -= t.obscured
for(var/eye in seenby)
var/mob/camera/aiEye/m = eye
if(!m)
continue
var/client/client = m.GetViewerClient()
if(client)
client.images -= t.obscured
t.vis_contents -= GLOB.cameranet.vis_contents
for(var/turf in visRemoved)
var/turf/t = turf
if(obscuredTurfs[t])
if(!t.obscured)
t.obscured = image('icons/effects/cameravis.dmi', t, null, BYOND_LIGHTING_LAYER+0.1)
t.obscured.pixel_x = -t.pixel_x
t.obscured.pixel_y = -t.pixel_y
t.obscured.plane = BYOND_LIGHTING_PLANE+0.1
obscured += t.obscured
for(var/eye in seenby)
var/mob/camera/aiEye/m = eye
if(!m)
seenby -= m
continue
var/client/client = m.GetViewerClient()
if(client)
client.images += t.obscured
if(obscuredTurfs[t] && !istype(t, /turf/open/ai_visible))
t.vis_contents += GLOB.cameranet.vis_contents
changed = 0
// Create a new camera chunk, since the chunks are made as they are needed.
/datum/camerachunk/New(loc, x, y, z)
// 0xf = 15
/datum/camerachunk/New(x, y, z)
x &= ~(CHUNK_SIZE - 1)
y &= ~(CHUNK_SIZE - 1)
@@ -164,12 +128,7 @@
for(var/turf in obscuredTurfs)
var/turf/t = turf
if(!t.obscured)
t.obscured = image('icons/effects/cameravis.dmi', t, null, BYOND_LIGHTING_LAYER+0.1)
t.obscured.pixel_x = -t.pixel_x
t.obscured.pixel_y = -t.pixel_y
t.obscured.plane = BYOND_LIGHTING_PLANE+0.1
obscured += t.obscured
t.vis_contents += GLOB.cameranet.vis_contents
#undef UPDATE_BUFFER
#undef CHUNK_SIZE
@@ -50,9 +50,7 @@
/mob/camera/aiEye/proc/RemoveImages()
var/client/C = GetViewerClient()
if(C && use_static)
for(var/V in visibleCameraChunks)
var/datum/camerachunk/c = V
C.images -= c.obscured
C.images -= GLOB.cameranet.obscured
/mob/camera/aiEye/Destroy()
if(ai)
@@ -88,10 +88,6 @@
icon_state = "room_background"
flags_1 = NOJAUNT_1
/turf/open/ai_visible/Initialize()
. = ..()
obscured = image(null, src, null)
/area/ai_multicam_room
name = "ai_multicam_room"
icon_state = "ai_camera_room"
@@ -162,8 +162,8 @@
//If there's an MMI in the robot, have it ejected when the mob goes away. --NEO
/mob/living/silicon/robot/Destroy()
var/atom/T = drop_location()//To hopefully prevent run time errors.
if(mmi && mind)//Safety for when a cyborg gets dust()ed. Or there is no MMI inside.
var/turf/T = get_turf(loc)//To hopefully prevent run time errors.
if(T)
mmi.forceMove(T)
if(mmi.brainmob)
@@ -182,6 +182,10 @@
connected_ai.connected_robots -= src
if(shell)
GLOB.available_ai_shells -= src
else
if(T && istype(radio) && istype(radio.keyslot))
radio.keyslot.forceMove(T)
radio.keyslot = null
qdel(wires)
qdel(module)
qdel(eye_lights)
@@ -228,7 +232,8 @@
if(custom_name)
changed_name = custom_name
if(changed_name == "" && client)
changed_name = client.prefs.custom_names["cyborg"]
rename_self(src, client)
return //built in camera handled in proc
if(!changed_name)
changed_name = get_standard_name()
@@ -1,3 +1,5 @@
#define MEDAL_PREFIX "Bubblegum"
/*
BUBBLEGUM
@@ -7,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 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.
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.
When Bubblegum dies, it leaves behind a H.E.C.K. mining suit as well as a chest that can contain three things:
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
When Bubblegum dies, it leaves behind a H.E.C.K. suit+helmet as well as a chest that can contain three things:
1. A spellblade that can slice off limbs at range
2. A bottle that, when activated, drives everyone nearby into a frenzy
3. A contract that marks for death the chosen target
Difficulty: Hard
@@ -44,8 +46,7 @@ Difficulty: Hard
del_on_death = 1
crusher_loot = list(/obj/structure/closet/crate/necropolis/bubblegum/crusher)
loot = list(/obj/structure/closet/crate/necropolis/bubblegum)
blood_volume = BLOOD_VOLUME_MAXIMUM //BLEED FOR ME
var/charging = FALSE
var/charging = 0
medal_type = BOSS_MEDAL_BUBBLEGUM
score_type = BUBBLEGUM_SCORE
deathmessage = "sinks into a pool of blood, fleeing the battle. You've won, for now... "
@@ -57,54 +58,33 @@ 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, updating_health = TRUE, forced = FALSE)
. = ..()
if(. > 0 && prob(25))
var/obj/effect/decal/cleanable/blood/gibs/bubblegum/B = new /obj/effect/decal/cleanable/blood/gibs/bubblegum(loc)
if(prob(40))
step(B, pick(GLOB.cardinals))
else
B.setDir(pick(GLOB.cardinals))
/obj/effect/decal/cleanable/blood/gibs/bubblegum
name = "thick blood"
desc = "Thick, splattered blood."
random_icon_states = list("gib3", "gib5", "gib6")
bloodiness = 20
/obj/effect/decal/cleanable/blood/gibs/bubblegum/can_bloodcrawl_in()
return TRUE
/mob/living/simple_animal/hostile/megafauna/bubblegum/Life()
..()
move_to_delay = CLAMP((health/maxHealth) * 10, 5, 10)
move_to_delay = CLAMP(round((health/maxHealth) * 10), 5, 10)
/mob/living/simple_animal/hostile/megafauna/bubblegum/OpenFire()
anger_modifier = CLAMP(((maxHealth - health)/60),0,20)
anger_modifier = CLAMP(((maxHealth - health)/50),0,20)
if(charging)
return
ranged_cooldown = world.time + ranged_cooldown_time
var/warped = FALSE
if(!try_bloodattack())
INVOKE_ASYNC(src, .proc/blood_spray)
warped = blood_warp()
if(warped && prob(100 - anger_modifier))
return
blood_warp()
if(prob(90 - anger_modifier) || slaughterlings())
if(health > maxHealth * 0.5)
if(prob(25))
INVOKE_ASYNC(src, .proc/blood_spray)
else if(prob(5+anger_modifier/2))
slaughterlings()
else
if(health > maxHealth/2 && !client)
INVOKE_ASYNC(src, .proc/charge)
else
if(prob(70) || warped)
INVOKE_ASYNC(src, .proc/charge, 2)
else
INVOKE_ASYNC(src, .proc/warp_charge)
INVOKE_ASYNC(src, .proc/triple_charge)
/mob/living/simple_animal/hostile/megafauna/bubblegum/Initialize()
. = ..()
for(var/mob/living/simple_animal/hostile/megafauna/bubblegum/B in GLOB.mob_living_list)
for(var/mob/living/simple_animal/hostile/megafauna/bubblegum/B in GLOB.mob_list)
if(B != src)
return INITIALIZE_HINT_QDEL //There can be only one
var/obj/effect/proc_holder/spell/bloodcrawl/bloodspell = new
@@ -118,56 +98,53 @@ Difficulty: Hard
if(.)
SSshuttle.shuttle_purchase_requirements_met |= "bubblegum"
/mob/living/simple_animal/hostile/megafauna/bubblegum/do_attack_animation(atom/A, visual_effect_icon)
if(!charging)
..()
/mob/living/simple_animal/hostile/megafauna/bubblegum/do_attack_animation(atom/A)
if(charging)
return
..()
/mob/living/simple_animal/hostile/megafauna/bubblegum/AttackingTarget()
if(!charging)
return ..()
if(charging)
return
..()
/mob/living/simple_animal/hostile/megafauna/bubblegum/Goto(target, delay, minimum_distance)
if(!charging)
..()
if(charging)
return
..()
/mob/living/simple_animal/hostile/megafauna/bubblegum/Move()
if(!stat)
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 200, 1, 2, 1)
if(charging)
new /obj/effect/temp_visual/decoy/fading(loc,src)
new/obj/effect/temp_visual/decoy/fading(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()
/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(bonus_charges)
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge()
var/turf/T = get_turf(target)
if(!T || T == loc)
return
new /obj/effect/temp_visual/dragon_swoop/bubblegum(T)
charging = TRUE
new /obj/effect/temp_visual/dragon_swoop(T)
charging = 1
DestroySurroundings()
walk(src, 0)
setDir(get_dir(src, T))
var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc,src)
animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 3)
sleep(3)
throw_at(T, get_dist(src, T), 1, src, 0, callback = CALLBACK(src, .charge_end, bonus_charges))
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge_end(bonus_charges, list/effects_to_destroy)
charging = FALSE
try_bloodattack()
if(target)
if(bonus_charges)
bonus_charges--
charge(bonus_charges)
else
Goto(target, move_to_delay, minimum_distance)
SetRecoveryTime(MEGAFAUNA_DEFAULT_RECOVERY_TIME)
animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 5)
sleep(5)
throw_at(T, get_dist(src, T), 1, src, 0)
charging = 0
Goto(target, move_to_delay, minimum_distance)
/mob/living/simple_animal/hostile/megafauna/bubblegum/Collide(atom/A)
@@ -191,142 +168,20 @@ Difficulty: Hard
var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src)))
L.throw_at(throwtarget, 3)
charging = FALSE
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_mob(L) || L.stat == DEAD))
. += L
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/try_bloodattack()
var/list/targets = get_mobs_on_blood()
if(targets.len)
INVOKE_ASYNC(src, .proc/bloodattack, targets, prob(50))
return TRUE
return FALSE
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodattack(list/targets, handedness)
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))
bloodgrab(target_two_turf, handedness)
else
bloodsmack(target_two_turf, handedness)
if(target_one)
var/list/pools = get_pools(get_turf(target_one), 0)
if(pools.len)
target_one_turf = get_turf(target_one)
if(target_one_turf)
if(target_one.stat != CONSCIOUS || prob(10))
bloodgrab(target_one_turf, !handedness)
else
bloodsmack(target_one_turf, !handedness)
if(!target_two && target_one)
var/list/poolstwo = get_pools(get_turf(target_one), 0)
if(poolstwo.len)
target_one_turf = get_turf(target_one)
if(target_one_turf)
if(target_one.stat != CONSCIOUS || prob(10))
bloodgrab(target_one_turf, handedness)
else
bloodsmack(target_one_turf, handedness)
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodsmack(turf/T, handedness)
if(handedness)
new /obj/effect/temp_visual/bubblegum_hands/rightsmack(T)
else
new /obj/effect/temp_visual/bubblegum_hands/leftsmack(T)
sleep(2.5)
for(var/mob/living/L in T)
if(!faction_check_mob(L))
to_chat(L, "<span class='userdanger'>[src] rends you!</span>")
playsound(T, attack_sound, 100, 1, -1)
var/limb_to_hit = L.get_bodypart(pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_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, handedness)
if(handedness)
new /obj/effect/temp_visual/bubblegum_hands/rightpaw(T)
new /obj/effect/temp_visual/bubblegum_hands/rightthumb(T)
else
new /obj/effect/temp_visual/bubblegum_hands/leftpaw(T)
new /obj/effect/temp_visual/bubblegum_hands/leftthumb(T)
sleep(6)
for(var/mob/living/L in T)
if(!faction_check_mob(L))
to_chat(L, "<span class='userdanger'>[src] drags you through the blood!</span>")
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(CALLBACK(src, .proc/devour, L), 2)
sleep(1)
/obj/effect/temp_visual/dragon_swoop/bubblegum
duration = 10
/obj/effect/temp_visual/bubblegum_hands
icon = 'icons/effects/bubblegum.dmi'
duration = 9
/obj/effect/temp_visual/bubblegum_hands/rightthumb
icon_state = "rightthumbgrab"
/obj/effect/temp_visual/bubblegum_hands/leftthumb
icon_state = "leftthumbgrab"
/obj/effect/temp_visual/bubblegum_hands/rightpaw
icon_state = "rightpawgrab"
layer = BELOW_MOB_LAYER
/obj/effect/temp_visual/bubblegum_hands/leftpaw
icon_state = "leftpawgrab"
layer = BELOW_MOB_LAYER
/obj/effect/temp_visual/bubblegum_hands/rightsmack
icon_state = "rightsmack"
/obj/effect/temp_visual/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/temp_visual/decoy/DA = new /obj/effect/temp_visual/decoy(loc,src)
DA.color = "#FF0000"
var/oldtransform = DA.transform
DA.transform = matrix()*2
animate(DA, alpha = 255, color = initial(DA.color), transform = oldtransform, time = 3)
sleep(3)
qdel(DA)
var/obj/effect/decal/cleanable/blood/found_bloodpool
pools = get_pools(get_turf(target), 2)
pools_to_remove = get_pools(get_turf(target), 1)
pools -= pools_to_remove
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
if(pools.len)
shuffle_inplace(pools)
found_bloodpool = pick(pools)
@@ -336,51 +191,30 @@ Difficulty: Hard
forceMove(get_turf(found_bloodpool))
playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
visible_message("<span class='danger'>And springs back out!</span>")
return TRUE
return FALSE
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_pools(turf/T, range)
. = list()
for(var/obj/effect/decal/cleanable/nearby in view(T, range))
if(nearby.can_bloodcrawl_in())
. += nearby
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_spray()
visible_message("<span class='danger'>[src] sprays a stream of gore!</span>")
var/range = 6 + round(anger_modifier * 0.4)
var/turf/E = get_edge_target_turf(src, src.dir)
var/range = 10
var/turf/previousturf = get_turf(src)
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/bubblegum(J)
for(var/i in 1 to range)
J = get_step(previousturf, targetdir)
new /obj/effect/temp_visual/dir_setting/bloodsplatter(previousturf, get_dir(previousturf, J))
playsound(previousturf,'sound/effects/splat.ogg', 100, 1, -1)
if(!J || !previousturf.atmos_adjacent_turfs || !previousturf.atmos_adjacent_turfs[J])
for(var/turf/J in getline(src,E))
if(!range)
break
new /obj/effect/decal/cleanable/blood/bubblegum(J)
new /obj/effect/temp_visual/dir_setting/bloodsplatter(previousturf, get_dir(previousturf, J))
if(!previousturf.CanAtmosPass(J))
break
playsound(J,'sound/effects/splat.ogg', 100, 1, -1)
new /obj/effect/decal/cleanable/blood(J)
range--
previousturf = J
sleep(1)
/obj/effect/decal/cleanable/blood/bubblegum
bloodiness = 0
/obj/effect/decal/cleanable/blood/bubblegum/can_bloodcrawl_in()
return TRUE
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/slaughterlings()
visible_message("<span class='danger'>[src] summons a shoal of slaughterlings!</span>")
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/slaughter(B.loc)
return max_amount
for(var/obj/effect/decal/cleanable/blood/H in range(src, 10))
if(prob(25))
new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/slaughter(H.loc)
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/slaughter
name = "slaughterling"
@@ -398,3 +232,5 @@ Difficulty: Hard
if(istype(mover, /mob/living/simple_animal/hostile/megafauna/bubblegum))
return 1
return 0
#undef MEDAL_PREFIX
+1
View File
@@ -7,6 +7,7 @@
hud_possible = list(ANTAG_HUD)
pressure_resistance = 8
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
throwforce = 10
var/lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
var/datum/mind/mind
var/list/datum/action/actions = list()
+1 -2
View File
@@ -379,8 +379,7 @@
else if(transfer_after)
R.key = key
if (CONFIG_GET(flag/rename_cyborg))
R.rename_self("cyborg")
R.rename_self("cyborg")
if(R.mmi)
R.mmi.name = "Man-Machine Interface: [real_name]"