mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-20 10:37:17 +01:00
Adds Shadow demons (#19732)
* reshuffle * shared base type * moves this to the base type * the monster * event * FUCK * better sprites * refactors bloodcrawl, more nice sprites * review stuff * Apply suggestions from code review Co-authored-by: Sirryan2002 <80364400+Sirryan2002@users.noreply.github.com> * heart of darkness * pre TM tweaks * ARGH * hopefully fixes double hits * tweaks * derp * tweaks * TEMP RUNTIME REMOVE LATER * fixes * runtime fixes * cig runtime fix * review + another runtime fix * re adds sprite * removes runtime * oop I forgor * DRUNK CODING * SPRITES Co-authored-by: Sirryan2002 <80364400+Sirryan2002@users.noreply.github.com>
This commit is contained in:
@@ -47,7 +47,7 @@
|
||||
var/title
|
||||
var/large = FALSE
|
||||
var/living_message
|
||||
if(istype(user, /mob/living/simple_animal/slaughter/cult)) //Harbringers of the Slaughter
|
||||
if(istype(user, /mob/living/simple_animal/demon/slaughter/cult)) //Harbringers of the Slaughter
|
||||
title = "<b>Harbringer of the Slaughter</b>"
|
||||
large = TRUE
|
||||
else
|
||||
|
||||
@@ -303,7 +303,7 @@
|
||||
if(curselimit > 1)
|
||||
to_chat(user, "<span class='notice'>We have exhausted our ability to curse the shuttle.</span>")
|
||||
return
|
||||
if(locate(/obj/singularity/narsie) in GLOB.poi_list || locate(/mob/living/simple_animal/slaughter/cult) in GLOB.mob_list)
|
||||
if(locate(/obj/singularity/narsie) in GLOB.poi_list || locate(/mob/living/simple_animal/demon/slaughter/cult) in GLOB.mob_list)
|
||||
to_chat(user, "<span class='danger'>Nar'Sie or her avatars are already on this plane, there is no delaying the end of all things.</span>")
|
||||
return
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/mob/living/simple_animal/demon
|
||||
name = "a generic demon"
|
||||
desc = "you shouldnt be reading this, file a github report"
|
||||
speak_emote = list("gurgles")
|
||||
emote_hear = list("wails","screeches")
|
||||
response_help = "thinks better of touching"
|
||||
response_disarm = "flails at"
|
||||
response_harm = "punches"
|
||||
speed = 1
|
||||
a_intent = INTENT_HARM
|
||||
mob_biotypes = MOB_ORGANIC | MOB_HUMANOID
|
||||
stop_automated_movement = TRUE
|
||||
status_flags = CANPUSH
|
||||
attack_sound = 'sound/misc/demon_attack1.ogg'
|
||||
death_sound = 'sound/misc/demon_dies.ogg'
|
||||
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
|
||||
maxbodytemp = INFINITY
|
||||
faction = list("demon")
|
||||
attacktext = "wildly tears into"
|
||||
maxHealth = 200
|
||||
health = 200
|
||||
environment_smash = ENVIRONMENT_SMASH_STRUCTURES
|
||||
obj_damage = 50
|
||||
melee_damage_lower = 30
|
||||
melee_damage_upper = 30
|
||||
see_in_dark = 8
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
del_on_death = TRUE
|
||||
var/datum/action/innate/demon/whisper/whisper_action
|
||||
|
||||
/mob/living/simple_animal/demon/Initialize(mapload)
|
||||
. = ..()
|
||||
whisper_action = new()
|
||||
whisper_action.Grant(src)
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/mob/living/simple_animal/demon/shadow
|
||||
name = "shadow demon"
|
||||
desc = "A creature that's barely tangible, you can feel its gaze piercing you"
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "shadow_demon"
|
||||
icon_living = "shadow_demon"
|
||||
move_resist = MOVE_FORCE_STRONG
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE // so they can tell where the darkness is
|
||||
loot = list(/obj/item/organ/internal/heart/demon/shadow)
|
||||
var/thrown_alert = FALSE
|
||||
|
||||
/mob/living/simple_animal/demon/shadow/Life(seconds, times_fired)
|
||||
. = ..()
|
||||
var/lum_count = check_darkness()
|
||||
var/damage_mod = istype(loc, /obj/effect/dummy/slaughter) ? 0.5 : 1
|
||||
if(lum_count > 0.2)
|
||||
adjustBruteLoss(40 * damage_mod) // 10 seconds in light
|
||||
SEND_SOUND(src, sound('sound/weapons/sear.ogg'))
|
||||
to_chat(src, "<span class='biggerdanger'>The light scalds you!</span>")
|
||||
else
|
||||
adjustBruteLoss(-20)
|
||||
|
||||
|
||||
/mob/living/simple_animal/demon/shadow/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
||||
if(isliving(AM)) // when a living creature is thrown at it, dont knock it back
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
/mob/living/simple_animal/demon/shadow/Initialize(mapload)
|
||||
. = ..()
|
||||
AddSpell(new /obj/effect/proc_holder/spell/fireball/shadow_grapple)
|
||||
var/obj/effect/proc_holder/spell/bloodcrawl/shadow_crawl/S = new
|
||||
AddSpell(S)
|
||||
if(istype(loc, /obj/effect/dummy/slaughter))
|
||||
S.phased = TRUE
|
||||
RegisterSignal(loc, COMSIG_MOVABLE_MOVED, TYPE_PROC_REF(/mob/living/simple_animal/demon/shadow, check_darkness))
|
||||
RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(check_darkness))
|
||||
|
||||
/mob/living/simple_animal/demon/shadow/proc/check_darkness()
|
||||
var/turf/T = get_turf(src)
|
||||
var/lum_count = T.get_lumcount()
|
||||
if(lum_count > 0.2)
|
||||
if(!thrown_alert)
|
||||
thrown_alert = TRUE
|
||||
throw_alert("light", /obj/screen/alert/lightexposure)
|
||||
alpha = 255
|
||||
else
|
||||
if(thrown_alert)
|
||||
thrown_alert = FALSE
|
||||
clear_alert("light")
|
||||
alpha = 125
|
||||
return lum_count
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/shadow_grapple
|
||||
name = "Shadow Grapple"
|
||||
desc = "Fire one of your hands, if it hits a person it pulls them in. If you hit a structure you get pulled to the structure."
|
||||
base_cooldown = 10 SECONDS
|
||||
fireball_type = /obj/item/projectile/magic/shadow_hand
|
||||
|
||||
selection_activated_message = "<span class='notice'>You raise your hand, full of demonic energy! <b>Left-click to cast at a target!</b></span>"
|
||||
selection_deactivated_message = "<span class='notice'>You re-absorb the energy...for now.</span>"
|
||||
|
||||
action_background_icon_state = "shadow_demon_bg"
|
||||
action_icon_state = "shadow_grapple"
|
||||
panel = "Demon"
|
||||
|
||||
sound = null
|
||||
invocation_type = "none"
|
||||
invocation = null
|
||||
|
||||
/obj/effect/proc_holder/spell/fireball/shadow_grapple/update_icon_state()
|
||||
return
|
||||
|
||||
/obj/item/projectile/magic/shadow_hand
|
||||
name = "shadow hand"
|
||||
icon_state = "shadow_hand"
|
||||
plane = FLOOR_PLANE
|
||||
var/hit = FALSE
|
||||
|
||||
/obj/item/projectile/magic/shadow_hand/fire(setAngle)
|
||||
if(firer)
|
||||
firer.Beam(src, icon_state = "grabber_beam", time = INFINITY, maxdistance = INFINITY, beam_sleep_time = 1, beam_type = /obj/effect/ebeam/floor)
|
||||
return ..()
|
||||
|
||||
/obj/item/projectile/magic/shadow_hand/on_hit(atom/target, blocked, hit_zone)
|
||||
if(hit)
|
||||
return
|
||||
hit = TRUE // to prevent double hits from the pull
|
||||
. = ..()
|
||||
if(!isliving(target))
|
||||
firer.throw_at(get_step(target, get_dir(target, firer)), 50, 10)
|
||||
else
|
||||
var/mob/living/L = target
|
||||
L.Immobilize(2 SECONDS)
|
||||
L.apply_damage(40, BRUTE, BODY_ZONE_CHEST)
|
||||
L.throw_at(get_step(firer, get_dir(firer, target)), 50, 10)
|
||||
target.extinguish_light(TRUE)
|
||||
|
||||
/obj/effect/ebeam/floor
|
||||
plane = FLOOR_PLANE
|
||||
|
||||
/obj/item/organ/internal/heart/demon/shadow
|
||||
name = "heart of darkness"
|
||||
desc = "It still beats furiously, emitting an aura of fear."
|
||||
color = COLOR_BLACK
|
||||
|
||||
/obj/item/organ/internal/heart/demon/shadow/attack_self(mob/living/user)
|
||||
. = ..()
|
||||
user.drop_item()
|
||||
insert(user)
|
||||
|
||||
/obj/item/organ/internal/heart/demon/shadow/insert(mob/living/carbon/M, special = 0)
|
||||
. = ..()
|
||||
if(M.mind)
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/fireball/shadow_grapple)
|
||||
|
||||
/obj/item/organ/internal/heart/demon/shadow/remove(mob/living/carbon/M, special = 0)
|
||||
..()
|
||||
if(M.mind)
|
||||
M.mind.RemoveSpell(/obj/effect/proc_holder/spell/fireball/shadow_grapple)
|
||||
+30
-58
@@ -1,42 +1,15 @@
|
||||
//////////////////The Monster
|
||||
|
||||
/mob/living/simple_animal/slaughter
|
||||
/mob/living/simple_animal/demon/slaughter
|
||||
name = "slaughter demon"
|
||||
real_name = "slaughter demon"
|
||||
desc = "A large, menacing creature covered in armored black scales. You should run."
|
||||
speak = list("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri", "orkan", "allaq")
|
||||
speak_emote = list("gurgles")
|
||||
emote_hear = list("wails","screeches")
|
||||
response_help = "thinks better of touching"
|
||||
response_disarm = "flails at"
|
||||
response_harm = "punches"
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "daemon"
|
||||
icon_living = "daemon"
|
||||
speed = 1
|
||||
a_intent = INTENT_HARM
|
||||
mob_biotypes = MOB_ORGANIC | MOB_HUMANOID
|
||||
stop_automated_movement = TRUE
|
||||
status_flags = CANPUSH
|
||||
attack_sound = 'sound/misc/demon_attack1.ogg'
|
||||
var/feast_sound = 'sound/misc/demon_consume.ogg'
|
||||
death_sound = 'sound/misc/demon_dies.ogg'
|
||||
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
|
||||
maxbodytemp = INFINITY
|
||||
faction = list("slaughter")
|
||||
attacktext = "wildly tears into"
|
||||
maxHealth = 200
|
||||
health = 200
|
||||
environment_smash = 1
|
||||
obj_damage = 50
|
||||
melee_damage_lower = 30
|
||||
melee_damage_upper = 30
|
||||
see_in_dark = 8
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
var/boost = 0
|
||||
|
||||
|
||||
var/feast_sound = 'sound/misc/demon_consume.ogg'
|
||||
var/devoured = 0
|
||||
var/list/consumed_mobs = list()
|
||||
|
||||
@@ -44,7 +17,7 @@
|
||||
var/cooldown = 0
|
||||
var/gorecooldown = 0
|
||||
var/vialspawned = FALSE
|
||||
loot = list(/obj/effect/decal/cleanable/blood/innards, /obj/effect/decal/cleanable/blood, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic, /obj/item/organ/internal/heart/demon)
|
||||
loot = list(/obj/effect/decal/cleanable/blood/innards, /obj/effect/decal/cleanable/blood, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic, /obj/item/organ/internal/heart/demon/slaughter)
|
||||
var/playstyle_string = "<B>You are the Slaughter Demon, a terrible creature from another existence. You have a single desire: to kill. \
|
||||
You may use the blood crawl icon when on blood pools to travel through them, appearing and dissapearing from the station at will. \
|
||||
Pulling a dead or critical mob while you enter a pool will pull them in with you, allowing you to feast. \
|
||||
@@ -52,30 +25,26 @@
|
||||
del_on_death = TRUE
|
||||
deathmessage = "screams in anger as it collapses into a puddle of viscera!"
|
||||
|
||||
var/datum/action/innate/demon/whisper/whisper_action
|
||||
|
||||
|
||||
/mob/living/simple_animal/slaughter/New()
|
||||
/mob/living/simple_animal/demon/slaughter/New()
|
||||
..()
|
||||
remove_from_all_data_huds()
|
||||
ADD_TRAIT(src, TRAIT_BLOODCRAWL_EAT, "bloodcrawl_eat")
|
||||
var/obj/effect/proc_holder/spell/bloodcrawl/bloodspell = new
|
||||
AddSpell(bloodspell)
|
||||
whisper_action = new()
|
||||
whisper_action.Grant(src)
|
||||
if(istype(loc, /obj/effect/dummy/slaughter))
|
||||
bloodspell.phased = TRUE
|
||||
addtimer(CALLBACK(src, PROC_REF(attempt_objectives)), 5 SECONDS)
|
||||
|
||||
|
||||
/mob/living/simple_animal/slaughter/Life(seconds, times_fired)
|
||||
/mob/living/simple_animal/demon/slaughter/Life(seconds, times_fired)
|
||||
..()
|
||||
if(boost < world.time)
|
||||
speed = 1
|
||||
else
|
||||
speed = 0
|
||||
|
||||
/mob/living/simple_animal/slaughter/proc/attempt_objectives()
|
||||
/mob/living/simple_animal/demon/slaughter/proc/attempt_objectives()
|
||||
if(mind)
|
||||
to_chat(src, src.playstyle_string)
|
||||
to_chat(src, "<B><span class ='notice'>You are not currently in the same plane of existence as the station. Use the blood crawl action at a blood pool to manifest.</span></B>")
|
||||
@@ -100,28 +69,24 @@
|
||||
name = "pile of viscera"
|
||||
desc = "A repulsive pile of guts and gore."
|
||||
|
||||
/mob/living/simple_animal/slaughter/Destroy()
|
||||
/mob/living/simple_animal/demon/slaughter/Destroy()
|
||||
// Only execute the below if we successfully died
|
||||
for(var/mob/living/M in consumed_mobs)
|
||||
release_consumed(M)
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/slaughter/proc/release_consumed(mob/living/M)
|
||||
/mob/living/simple_animal/demon/slaughter/proc/release_consumed(mob/living/M)
|
||||
M.forceMove(get_turf(src))
|
||||
|
||||
/mob/living/simple_animal/slaughter/phasein()
|
||||
. = ..()
|
||||
speed = 0
|
||||
boost = world.time + 60
|
||||
|
||||
// Midround slaughter demon, less tanky
|
||||
|
||||
/mob/living/simple_animal/slaughter/lesser
|
||||
/mob/living/simple_animal/demon/slaughter/lesser
|
||||
maxHealth = 130
|
||||
health = 130
|
||||
|
||||
// Cult slaughter demon
|
||||
/mob/living/simple_animal/slaughter/cult //Summoned as part of the cult objective "Bring the Slaughter"
|
||||
/mob/living/simple_animal/demon/slaughter/cult //Summoned as part of the cult objective "Bring the Slaughter"
|
||||
name = "harbinger of the slaughter"
|
||||
real_name = "harbinger of the Slaughter"
|
||||
desc = "An awful creature from beyond the realms of madness."
|
||||
@@ -163,10 +128,10 @@
|
||||
return 0
|
||||
to_chat(user, "<span class='danger'>You sense a terrified soul at [A]. <b>Show [A.p_them()] the error of [A.p_their()] ways.</b></span>")
|
||||
|
||||
/mob/living/simple_animal/slaughter/cult/New()
|
||||
/mob/living/simple_animal/demon/slaughter/cult/New()
|
||||
..()
|
||||
spawn(5)
|
||||
var/list/demon_candidates = SSghost_spawns.poll_candidates("Do you want to play as a slaughter demon?", ROLE_DEMON, TRUE, 10 SECONDS, source = /mob/living/simple_animal/slaughter/cult)
|
||||
var/list/demon_candidates = SSghost_spawns.poll_candidates("Do you want to play as a slaughter demon?", ROLE_DEMON, TRUE, 10 SECONDS, source = /mob/living/simple_animal/demon/slaughter/cult)
|
||||
if(!demon_candidates.len)
|
||||
visible_message("<span class='warning'>[src] disappears in a flash of red light!</span>")
|
||||
qdel(src)
|
||||
@@ -174,7 +139,7 @@
|
||||
if(QDELETED(src)) // Just in case
|
||||
return
|
||||
var/mob/M = pick(demon_candidates)
|
||||
var/mob/living/simple_animal/slaughter/cult/S = src
|
||||
var/mob/living/simple_animal/demon/slaughter/cult/S = src
|
||||
if(!M || !M.client)
|
||||
visible_message("<span class='warning'>[src] disappears in a flash of red light!</span>")
|
||||
qdel(src)
|
||||
@@ -240,7 +205,7 @@
|
||||
|
||||
//////////The Loot
|
||||
|
||||
//The loot from killing a slaughter demon - can be consumed to allow the user to blood crawl
|
||||
// Demon heart base type
|
||||
/obj/item/organ/internal/heart/demon
|
||||
name = "demon heart"
|
||||
desc = "Still it beats furiously, emanating an aura of utter hate."
|
||||
@@ -254,11 +219,22 @@
|
||||
/obj/item/organ/internal/heart/demon/prepare_eat()
|
||||
return // Just so people don't accidentally waste it
|
||||
|
||||
/obj/item/organ/internal/heart/demon/Stop()
|
||||
return 0 // Always beating.
|
||||
|
||||
/obj/item/organ/internal/heart/demon/attack_self(mob/living/user)
|
||||
user.visible_message("<span class='warning'>[user] raises [src] to [user.p_their()] mouth and tears into it with [user.p_their()] teeth!</span>", \
|
||||
"<span class='danger'>An unnatural hunger consumes you. You raise [src] to your mouth and devour it!</span>")
|
||||
playsound(user, 'sound/misc/demon_consume.ogg', 50, 1)
|
||||
|
||||
//////////The Loot
|
||||
|
||||
//The loot from killing a slaughter demon - can be consumed to allow the user to blood crawl
|
||||
/// SLAUGHTER DEMON HEART
|
||||
|
||||
/obj/item/organ/internal/heart/demon/slaughter/attack_self(mob/living/user)
|
||||
..()
|
||||
|
||||
// Eating the heart for the first time. Gives basic bloodcrawling. This is the only time we need to insert the heart.
|
||||
if(!HAS_TRAIT(user, TRAIT_BLOODCRAWL))
|
||||
user.visible_message("<span class='warning'>[user]'s eyes flare a deep crimson!</span>", \
|
||||
@@ -279,23 +255,19 @@
|
||||
to_chat(user, "<span class='warning'>...and you don't feel any different.</span>")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/organ/internal/heart/demon/insert(mob/living/carbon/M, special = 0)
|
||||
/obj/item/organ/internal/heart/demon/slaughter/insert(mob/living/carbon/M, special = 0)
|
||||
. = ..()
|
||||
if(M.mind)
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/bloodcrawl(null))
|
||||
|
||||
/obj/item/organ/internal/heart/demon/remove(mob/living/carbon/M, special = 0)
|
||||
/obj/item/organ/internal/heart/demon/slaughter/remove(mob/living/carbon/M, special = 0)
|
||||
..()
|
||||
if(M.mind)
|
||||
REMOVE_TRAIT(M, TRAIT_BLOODCRAWL, "bloodcrawl")
|
||||
REMOVE_TRAIT(M, TRAIT_BLOODCRAWL_EAT, "bloodcrawl_eat")
|
||||
M.mind.RemoveSpell(/obj/effect/proc_holder/spell/bloodcrawl)
|
||||
|
||||
/obj/item/organ/internal/heart/demon/Stop()
|
||||
return 0 // Always beating.
|
||||
|
||||
|
||||
/mob/living/simple_animal/slaughter/laughter
|
||||
/mob/living/simple_animal/demon/slaughter/laughter
|
||||
// The laughter demon! It's everyone's best friend! It just wants to hug
|
||||
// them so much, it wants to hug everyone at once!
|
||||
name = "laughter demon"
|
||||
@@ -324,7 +296,7 @@
|
||||
deathmessage = "fades out, as all of its friends are released from its prison of hugs."
|
||||
loot = list(/mob/living/simple_animal/pet/cat/kitten{name = "Laughter"})
|
||||
|
||||
/mob/living/simple_animal/slaughter/laughter/release_consumed(mob/living/M)
|
||||
/mob/living/simple_animal/demon/slaughter/laughter/release_consumed(mob/living/M)
|
||||
if(M.revive())
|
||||
M.grab_ghost(force = TRUE)
|
||||
playsound(get_turf(src), feast_sound, 50, 1, -1)
|
||||
@@ -348,7 +320,7 @@
|
||||
for(var/datum/mind/M in get_owners())
|
||||
if(!isslaughterdemon(M.current) || QDELETED(M.current))
|
||||
continue
|
||||
var/mob/living/simple_animal/slaughter/R = M.current
|
||||
var/mob/living/simple_animal/demon/slaughter/R = M.current
|
||||
kill_count += R.devoured
|
||||
if(kill_count >= targetKill)
|
||||
return TRUE
|
||||
@@ -1,180 +0,0 @@
|
||||
//Travel through pools of blood. Slaughter Demon powers for everyone!
|
||||
#define BLOODCRAWL 1
|
||||
#define BLOODCRAWL_EAT 2
|
||||
|
||||
/mob/living/proc/phaseout(obj/effect/decal/cleanable/B)
|
||||
|
||||
if(iscarbon(src))
|
||||
var/mob/living/carbon/C = src
|
||||
if(C.l_hand || C.r_hand)
|
||||
to_chat(C, "<span class='warning'>You may not hold items while blood crawling!</span>")
|
||||
return 0
|
||||
var/obj/item/bloodcrawl/B1 = new(C)
|
||||
var/obj/item/bloodcrawl/B2 = new(C)
|
||||
B1.icon_state = "bloodhand_left"
|
||||
B2.icon_state = "bloodhand_right"
|
||||
C.put_in_hands(B1)
|
||||
C.put_in_hands(B2)
|
||||
C.regenerate_icons()
|
||||
|
||||
var/mob/living/kidnapped = null
|
||||
var/turf/mobloc = get_turf(loc)
|
||||
notransform = TRUE
|
||||
spawn(0)
|
||||
visible_message("<span class='danger'>[src] sinks into [B].</span>")
|
||||
playsound(get_turf(src), 'sound/misc/enter_blood.ogg', 100, 1, -1)
|
||||
var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(mobloc)
|
||||
var/atom/movable/overlay/animation = new /atom/movable/overlay(mobloc)
|
||||
animation.name = "odd blood"
|
||||
animation.density = FALSE
|
||||
animation.anchored = TRUE
|
||||
animation.icon = 'icons/mob/mob.dmi'
|
||||
animation.icon_state = "jaunt"
|
||||
animation.layer = 5
|
||||
animation.master = holder
|
||||
animation.dir = dir
|
||||
|
||||
ExtinguishMob()
|
||||
if(pulling && HAS_TRAIT(src, TRAIT_BLOODCRAWL_EAT))
|
||||
if(isliving(pulling))
|
||||
var/mob/living/victim = pulling
|
||||
if(victim.stat == CONSCIOUS)
|
||||
visible_message("<span class='warning'>[victim] kicks free of [B] just before entering it!</span>")
|
||||
stop_pulling()
|
||||
else
|
||||
victim.forceMove(holder)//holder
|
||||
victim.emote("scream")
|
||||
visible_message("<span class='warning'><b>[src] drags [victim] into [B]!</b></span>")
|
||||
kidnapped = victim
|
||||
stop_pulling()
|
||||
flick("jaunt",animation)
|
||||
|
||||
src.holder = holder
|
||||
forceMove(holder)
|
||||
|
||||
if(kidnapped)
|
||||
to_chat(src, "<B>You begin to feast on [kidnapped]. You can not move while you are doing this.</B>")
|
||||
visible_message("<span class='warning'><B>Loud eating sounds come from the blood...</B></span>")
|
||||
sleep(6)
|
||||
if(animation)
|
||||
qdel(animation)
|
||||
var/sound
|
||||
if(isslaughterdemon(src))
|
||||
var/mob/living/simple_animal/slaughter/SD = src
|
||||
sound = SD.feast_sound
|
||||
else
|
||||
sound = 'sound/misc/demon_consume.ogg'
|
||||
|
||||
for(var/i in 1 to 3)
|
||||
playsound(get_turf(src), sound, 100, 1)
|
||||
sleep(30)
|
||||
|
||||
if(kidnapped)
|
||||
if(ishuman(kidnapped) || isrobot(kidnapped))
|
||||
to_chat(src, "<span class='warning'>You devour [kidnapped]. Your health is fully restored.</span>")
|
||||
adjustBruteLoss(-1000)
|
||||
adjustFireLoss(-1000)
|
||||
adjustOxyLoss(-1000)
|
||||
adjustToxLoss(-1000)
|
||||
else
|
||||
to_chat(src, "<span class='warning'>You devour [kidnapped], but this measly meal barely sates your appetite!</span>")
|
||||
adjustBruteLoss(-25)
|
||||
adjustFireLoss(-25)
|
||||
if(istype(src, /mob/living/simple_animal/slaughter)) //rason, do not want humans to get this
|
||||
var/mob/living/simple_animal/slaughter/demon = src
|
||||
demon.devoured++
|
||||
to_chat(kidnapped, "<span class='userdanger'>You feel teeth sink into your flesh, and the--</span>")
|
||||
kidnapped.adjustBruteLoss(1000)
|
||||
kidnapped.forceMove(src)
|
||||
demon.consumed_mobs.Add(kidnapped)
|
||||
if(ishuman(kidnapped))
|
||||
var/mob/living/carbon/human/H = kidnapped
|
||||
if(H.w_uniform && istype(H.w_uniform, /obj/item/clothing/under))
|
||||
var/obj/item/clothing/under/U = H.w_uniform
|
||||
U.sensor_mode = SENSOR_OFF
|
||||
else
|
||||
kidnapped.ghostize()
|
||||
qdel(kidnapped)
|
||||
else
|
||||
to_chat(src, "<span class='danger'>You happily devour... nothing? Your meal vanished at some point!</span>")
|
||||
else
|
||||
sleep(6)
|
||||
if(animation)
|
||||
qdel(animation)
|
||||
notransform = FALSE
|
||||
return 1
|
||||
|
||||
/obj/item/bloodcrawl
|
||||
name = "blood crawl"
|
||||
desc = "You are unable to hold anything while in this form."
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
flags = NODROP|ABSTRACT
|
||||
|
||||
/mob/living/proc/phasein(obj/effect/decal/cleanable/B)
|
||||
|
||||
if(notransform)
|
||||
to_chat(src, "<span class='warning'>Finish eating first!</span>")
|
||||
return 0
|
||||
B.visible_message("<span class='warning'>[B] starts to bubble...</span>")
|
||||
if(!do_after(src, 20, target = B))
|
||||
return
|
||||
if(!B)
|
||||
return
|
||||
forceMove(B.loc)
|
||||
client.eye = src
|
||||
|
||||
var/atom/movable/overlay/animation = new /atom/movable/overlay( B.loc )
|
||||
animation.name = "odd blood"
|
||||
animation.density = FALSE
|
||||
animation.anchored = TRUE
|
||||
animation.icon = 'icons/mob/mob.dmi'
|
||||
animation.icon_state = "jauntup" //Paradise Port:I reversed the jaunt animation so it looks like its rising up
|
||||
animation.layer = 5
|
||||
animation.master = B.loc
|
||||
animation.dir = dir
|
||||
|
||||
if(prob(25) && isslaughterdemon(src))
|
||||
var/list/voice = list('sound/hallucinations/behind_you1.ogg','sound/hallucinations/im_here1.ogg','sound/hallucinations/turn_around1.ogg','sound/hallucinations/i_see_you1.ogg')
|
||||
playsound(get_turf(src), pick(voice),50, 1, -1)
|
||||
visible_message("<span class='warning'><B>\The [src] rises out of \the [B]!</B>")
|
||||
playsound(get_turf(src), 'sound/misc/exit_blood.ogg', 100, 1, -1)
|
||||
|
||||
flick("jauntup",animation)
|
||||
QDEL_NULL(holder)
|
||||
|
||||
if(iscarbon(src))
|
||||
var/mob/living/carbon/C = src
|
||||
for(var/obj/item/bloodcrawl/BC in C)
|
||||
C.flags = null
|
||||
C.unEquip(BC)
|
||||
qdel(BC)
|
||||
|
||||
var/oldcolor = color
|
||||
color = B.color
|
||||
sleep(6)//wait for animation to finish
|
||||
if(animation)
|
||||
qdel(animation)
|
||||
spawn(30)
|
||||
color = oldcolor
|
||||
return 1
|
||||
|
||||
/obj/effect/dummy/slaughter //Can't use the wizard one, blocked by jaunt/slow
|
||||
name = "odd blood"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "nothing"
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
invisibility = 60
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
|
||||
/obj/effect/dummy/slaughter/relaymove(mob/user, direction)
|
||||
forceMove(get_step(src,direction))
|
||||
|
||||
/obj/effect/dummy/slaughter/ex_act()
|
||||
return
|
||||
|
||||
/obj/effect/dummy/slaughter/bullet_act()
|
||||
return
|
||||
|
||||
/obj/effect/dummy/slaughter/singularity_act()
|
||||
return
|
||||
Reference in New Issue
Block a user