diff --git a/code/datums/spells/bloodcrawl.dm b/code/datums/spells/bloodcrawl.dm index 0e5db631223..320661b61c7 100644 --- a/code/datums/spells/bloodcrawl.dm +++ b/code/datums/spells/bloodcrawl.dm @@ -1,13 +1,14 @@ /obj/effect/proc_holder/spell/bloodcrawl - name = "Blood crawl" - desc = "Use blood to travel." - charge_max = 10 + name = "Blood Crawl" + desc = "Use pools of blood to phase out of existence." + charge_max = 0 clothes_req = 0 selection_type = "range" range = 1 cooldown_min = 0 overlay = null action_icon_state = "bloodcrawl" + action_background_icon_state = "bg_slaughter" var/phased = 0 /obj/effect/proc_holder/spell/bloodcrawl/choose_targets(mob/user = usr) @@ -16,7 +17,7 @@ perform(target) return revert_cast() - user << "You need blood to blood crawl." + user << "There must be a nearby source of blood!" /obj/effect/proc_holder/spell/bloodcrawl/perform(obj/effect/decal/cleanable/target, recharge = 1, mob/living/user = usr) if(istype(user)) @@ -29,4 +30,4 @@ start_recharge() return revert_cast() - user << "You cannot blood crawl." \ No newline at end of file + user << "You are unable to blood crawl!" \ No newline at end of file diff --git a/code/modules/mob/living/bloodcrawl.dm b/code/modules/mob/living/bloodcrawl.dm index 3f7bfba90cf..c185a60a582 100644 --- a/code/modules/mob/living/bloodcrawl.dm +++ b/code/modules/mob/living/bloodcrawl.dm @@ -35,7 +35,7 @@ obj/effect/dummy/slaughter/relaymove(mob/user, direction) var/turf/mobloc = get_turf(src.loc) src.notransform = TRUE spawn(0) - src.visible_message("[src] sinks into the pool of blood.") + src.visible_message("[src] sinks into the pool of blood!") playsound(get_turf(src), 'sound/magic/enter_blood.ogg', 100, 1, -1) var/obj/effect/dummy/slaughter/holder = PoolOrNew(/obj/effect/dummy/slaughter,mobloc) src.ExtinguishMob() @@ -45,41 +45,50 @@ obj/effect/dummy/slaughter/relaymove(mob/user, direction) if(istype(src.pulling, /mob/living)) var/mob/living/victim = src.pulling if(victim.stat == CONSCIOUS) - src.visible_message("[victim] kicks free of the [src] at the last second!") + src.visible_message("[victim] kicks free of the blood pool just before entering it!") else victim.loc = holder - src.visible_message("The [src] drags [victim] into the pool of blood!") + victim.emote("scream") + src.visible_message("[src] drags [victim] into the pool of blood!") kidnapped = victim src.loc = holder src.holder = holder if(kidnapped) - src << "You begin to feast on [kidnapped]. You can not move while you are doing this." - playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1) - sleep(30) - playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1) - sleep(30) - playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1) - sleep(30) + src << "You begin to feast on [kidnapped]. You can not move while you are doing this." + for(var/i = 3; i > 0; i--) + playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1) + sleep(30) if(kidnapped) - src << "You devour [kidnapped]. Your health is fully restored." + src << "You devour [kidnapped]. Your health is fully restored." src.adjustBruteLoss(-1000) src.adjustFireLoss(-1000) src.adjustOxyLoss(-1000) src.adjustToxLoss(-1000) - kidnapped.ghostize() - qdel(kidnapped) + if(istype(src, /mob/living/simple_animal/slaughter)) + var/mob/living/simple_animal/slaughter/S = src + kidnapped << "You feel teeth sink into your flesh, and the--" + kidnapped.adjustBruteLoss(1000) + kidnapped.loc = src + S.consumed_mobs.Add(kidnapped) + else + kidnapped.ghostize() + qdel(kidnapped) else - src << "You happily devour...nothing? Your meal vanished at some point!" + src << "You happily devour... nothing? Your meal vanished at some point!" src.notransform = 0 /mob/living/proc/phasein(obj/effect/decal/cleanable/B) if(src.notransform) - src << "Finish eating first!" + src << "Finish eating first!" return 0 - + B.visible_message("[B] starts to bubble...") + if(!do_after(src, 20, target = B)) + return + if(!B) + return src.loc = B.loc src.client.eye = src - src.visible_message("The [src] rises out of the pool of blood!") + src.visible_message("[src] rises out of the pool of blood!") playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1) qdel(src.holder) src.holder = null diff --git a/code/modules/mob/living/simple_animal/morph/morph.dm b/code/modules/mob/living/simple_animal/morph/morph.dm index b8d9d8e3230..c815f567578 100644 --- a/code/modules/mob/living/simple_animal/morph/morph.dm +++ b/code/modules/mob/living/simple_animal/morph/morph.dm @@ -1,9 +1,9 @@ #define MORPH_COOLDOWN 50 /mob/living/simple_animal/hostile/morph - name = "Morph" - real_name = "Morph" - desc = "some amorphous blob" + name = "morph" + real_name = "morph" + desc = "A revolting, pulsating pile of flesh." speak_emote = list("gurgles") emote_hear = list("gurgles") icon = 'icons/mob/animal.dmi' @@ -28,16 +28,25 @@ see_invisible = SEE_INVISIBLE_MINIMUM idle_vision_range = 1 // Only attack when target is close wander = 0 + attacktext = "glomps" + attack_sound = 'sound/effects/blobattack.ogg' var/morphed = 0 var/atom/movable/form = null var/morph_time = 0 + var/playstyle_string = "You are a morph, an abomination of science created primarily with changeling cells. \ + You may take the form of anything nearby by middle-clicking it. This process will alert any nearby \ + observers, and can only be performed once every five seconds. While morphed, you move faster, but do \ + less damage. In addition, anyone within three tiles will note an uncanny wrongness if examining you. \ + You can attack any item or dead creature to consume it - creatures will fully restore your health. \ + Finally, you can restore yourself to your original form while morphed by middle-clicking yourself." + /mob/living/simple_animal/hostile/morph/examine(mob/user) if(morphed) form.examine(user) // Refactor examine to return desc so it's static? Not sure if worth it if(get_dist(user,src)<=3) - user << "Looks odd!" + user << "It doesn't look quite right..." else ..() return @@ -57,6 +66,7 @@ if(istype(A) && allowed(A)) assume(A) else + src << "Your chameleon skin is still repairing itself!" ..() /mob/living/simple_animal/hostile/morph/proc/assume(atom/movable/target) @@ -72,11 +82,15 @@ else overlays = target.overlays.Copy() + visible_message("[src] suddenly twists and changes shape, becoming a copy of [target]!", \ + "You twist your body and assume the form of [target].") + name = target.name icon = target.icon icon_state = target.icon_state overlays = target.overlays + //Morphed is weaker melee_damage_lower = 5 melee_damage_upper = 5 @@ -93,6 +107,8 @@ //anim(loc,src,'icons/mob/mob.dmi',,"morph",,src.dir) + visible_message("[src] suddenly collapses in on itself, dissolving into a pile of green flesh!", \ + "You reform to your normal body.") name = initial(name) icon = initial(icon) icon_state = initial(icon_state) @@ -108,7 +124,8 @@ /mob/living/simple_animal/hostile/morph/death() if(morphed) - visible_message("The [src] dissolves!") + visible_message("[src] twists and dissolves into a pile of green flesh!", \ + "Your skin ruptures! Your flesh breaks apart! No disguise can ward off de--") restore() //Dump eaten stuff @@ -148,7 +165,7 @@ var/mob/living/L = target if(L.stat == DEAD) if(do_after(src, 30, target = L)) - visible_message("[src] swallows the [target] whole!") + visible_message("[src] swallows [target] whole!") L.loc = src adjustBruteLoss(-50) return @@ -156,7 +173,7 @@ var/obj/item/I = target if(!I.anchored) if(do_after(src,20, target = I)) - visible_message("[src] swallows the [target] whole!") + visible_message("[src] swallows [target] whole!") I.loc = src return target.attack_animal(src) @@ -198,15 +215,10 @@ player_mind.assigned_role = "Morph" player_mind.special_role = "Morph" ticker.mode.traitors |= player_mind - var/info = {"You are a Morph, a shapeshifting alien creature. - You can assume the shape of anything in sight by Shift-Clicking it. - You can only transform every 5 seconds. - To return to your basic form Shift-Click on yourself. - Base form is slow but strong, you're much weaker and faster when disguised. - You can eat items and corpses by clicking on them,eating corpses will heal you."} - S << info - message_admins("[key_of_morph] has been made into Morph by an event.") - log_game("[key_of_morph] was spawned as a Morph by an event.") + S << S.playstyle_string + S << 'sound/magic/Mutate.ogg' + message_admins("[key_of_morph] has been made into morph by an event.") + log_game("[key_of_morph] was spawned as a morph by an event.") return 1 /datum/round_event/morph/start() @@ -214,11 +226,11 @@ /datum/round_event/morph/proc/find_morph() - message_admins("Attempted to spawn a Morph but there was no players available. Will try again momentarily.") + message_admins("Attempted to spawn a morph but there was no players available. Will try again momentarily.") spawn(50) if(get_morph(1)) - message_admins("Situation has been resolved, [key_of_morph] has been spawned as a Morph.") - log_game("[key_of_morph] was spawned as a Morph by an event.") + message_admins("Situation has been resolved, [key_of_morph] has been spawned as a morph.") + log_game("[key_of_morph] was spawned as a morph by an event.") return 0 - message_admins("Unfortunately, no candidates were available for becoming a Morph. Shutting down.") + message_admins("Unfortunately, no candidates were available for becoming a morph. Shutting down.") return kill() \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/slaughter/slaughter.dm b/code/modules/mob/living/simple_animal/slaughter/slaughter.dm index 5f39ad01d46..07896ec81fa 100644 --- a/code/modules/mob/living/simple_animal/slaughter/slaughter.dm +++ b/code/modules/mob/living/simple_animal/slaughter/slaughter.dm @@ -1,9 +1,9 @@ //////////////////The Monster /mob/living/simple_animal/slaughter - name = "Slaughter Demon" - real_name = "Slaughter Demon" - desc = "You should run." + name = "slaughter demon" + real_name = "slaughter demon" + desc = "A large, menacing creature covered in armored black scales." speak_emote = list("gurgles") emote_hear = list("wails","screeches") response_help = "thinks better of touching" @@ -31,10 +31,11 @@ var/boost = 0 bloodcrawl = BLOODCRAWL_EAT see_invisible = SEE_INVISIBLE_MINIMUM - var/playstyle_string = "You are the Slaughter Demon, a terible creature from another existence. You have a single desire: To kill. \ - You may Ctrl+Click on blood pools to travel through them, appearing and dissaapearing 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. \ - You move quickly upon leaving a pool of blood, but the material world will soon sap your strength and leave you sluggish. " + var/list/consumed_mobs = list() + var/playstyle_string = "You are a slaughter demon, a terrible creature from another realm. You have a single desire: To kill. \ + You may use the \"Blood Crawl\" ability near blood pools to travel through them, appearing and dissaapearing from the station at will. \ + Pulling a dead or unconscious mob while you enter a pool will pull them in with you, allowing you to feast and regain your health. \ + You move quickly upon leaving a pool of blood, but the material world will soon sap your strength and leave you sluggish. " /mob/living/simple_animal/slaughter/New() ..() @@ -52,10 +53,17 @@ /mob/living/simple_animal/slaughter/death() ..(1) - new /obj/effect/decal/cleanable/blood (src.loc) - new /obj/item/weapon/demonheart (src.loc) + new /obj/effect/decal/cleanable/blood (get_turf(src)) + var/obj/effect/decal/cleanable/blood/innards = new (get_turf(src)) + innards.icon = 'icons/obj/surgery.dmi' + innards.icon_state = "innards" + innards.name = "pile of viscera" + innards.desc = "A repulsive pile of guts and gore." + new /obj/item/organ/internal/heart/demon (src.loc) playsound(get_turf(src),'sound/magic/demon_dies.ogg', 200, 1) - visible_message("The [src] screams in anger as its form collapes into a pool of viscera.") + visible_message("[src] screams in anger as it collapses into a puddle of viscera, its most recent meals spilling out of it.") + for(var/mob/living/M in consumed_mobs) + M.loc = get_turf(src) ghostize() qdel(src) return @@ -67,23 +75,28 @@ boost = world.time + 30 -//////////The Loot - -/obj/item/weapon/demonheart - name = "demon's heart" - desc = "It's still faintly beating with rage" +//The loot from killing a slaughter demon - can be consumed to allow the user to blood crawl +/obj/item/organ/internal/heart/demon + name = "demon heart" + desc = "Still it beats furiously, emanating an aura of utter hate." icon = 'icons/obj/surgery.dmi' - icon_state = "heart-on" + icon_state = "demon_heart" origin_tech = "combat=5;biotech=8" + beating = 1 //What did you expect? -/obj/item/weapon/demonheart/attack_self(mob/living/user) - visible_message("[user] feasts upon the [src].") +/obj/item/organ/internal/heart/demon/attack(mob/M, mob/living/user, obj/target) + if(M != user) + return ..() + user.visible_message("[user] raises [src] to their mouth and tears into it with their teeth!", \ + "An unnatural hunger consumes you. You raise [src] your mouth and devour it!") + playsound(user, 'sound/magic/Demon_consume.ogg', 50, 1) for(var/obj/effect/proc_holder/spell/knownspell in user.mind.spell_list) if(knownspell.type == /obj/effect/proc_holder/spell/bloodcrawl) - user <<"You already know how to blood crawl." + user <<"...and you don't feel any different." qdel(src) return - user << "You absorb some of the demon's power!" + user.visible_message("[user]'s eyes flare a deep crimson!", \ + "You feel a strange power seep into your body... you have absorbed the demon's blood-travelling powers!") user.mind.AddSpell(new /obj/effect/proc_holder/spell/bloodcrawl) + user.drop_item() qdel(src) - diff --git a/code/modules/mob/living/simple_animal/slaughter/slaughterevent.dm b/code/modules/mob/living/simple_animal/slaughter/slaughterevent.dm index de3e477ab6d..cbc845bc69d 100644 --- a/code/modules/mob/living/simple_animal/slaughter/slaughterevent.dm +++ b/code/modules/mob/living/simple_animal/slaughter/slaughterevent.dm @@ -44,9 +44,10 @@ player_mind.special_role = "Slaughter Demon" ticker.mode.traitors |= player_mind S << S.playstyle_string - S << "You are currently not currently in the same plane of existence as the station. Ctrl+Click a blood pool to manifest." - message_admins("[key_of_slaughter] has been made into a Slaughter Demon by an event.") - log_game("[key_of_slaughter] was spawned as a Slaughter Demon by an event.") + S << "You are currently not currently in the same plane of existence as the station. Blood Crawl near a blood pool to manifest." + S << 'sound/magic/demon_dies.ogg' + message_admins("[key_of_slaughter] has been made into a slaughter demon by an event.") + log_game("[key_of_slaughter] was spawned as a slaughter demon by an event.") return 1 @@ -57,11 +58,11 @@ /datum/round_event/slaughter/proc/find_slaughter() - message_admins("Attempted to spawn a Slaughter Demon but there was no players available. Will try again momentarily.") + message_admins("Attempted to spawn a slaughter demon but there was no players available. Will try again momentarily.") spawn(50) if(get_slaughter(1)) - message_admins("Situation has been resolved, [key_of_slaughter] has been spawned as a Slaughter Demon.") - log_game("[key_of_slaughter] was spawned as a Slaughter Demon by an event.") + message_admins("Situation has been resolved, [key_of_slaughter] has been spawned as a slaughter demon.") + log_game("[key_of_slaughter] was spawned as a slaughter demon by an event.") return 0 - message_admins("Unfortunately, no candidates were available for becoming a Slaugter Demon. Shutting down.") + message_admins("Unfortunately, no candidates were available for becoming a slaughter demon. Shutting down.") return kill() diff --git a/html/changelogs/Xhuis-DemonsAndMorphs.yml b/html/changelogs/Xhuis-DemonsAndMorphs.yml new file mode 100644 index 00000000000..1862bea6f80 --- /dev/null +++ b/html/changelogs/Xhuis-DemonsAndMorphs.yml @@ -0,0 +1,13 @@ +author: Xhuis +delete-after: True + +changes: + - tweak: "When a morph changes form, a message is shown to nearby people. This also happens upon undisguising." + - tweak: "Morphs now have an attack sound and message." + - tweak: "The Spawn Morph event now plays a sound to the chosen candidate." + - tweak: "Slaughter Demons (and other creatures with blood crawl) now take two seconds to emerge from blood pools. Entering is still instantaneous." + - tweak: "The demon heart's sprite has been updated." + - tweak: "Blood Crawl no longer has a 1-second cooldown, instead having none." + - tweak: "Creatures that can Blood Crawl now take two seconds to emerge from blood pools." + - tweak: "Slaughter demons now store devoured creatures, and will drop them upon death." + - tweak: "The Spawn Slaughter Demon event now plays a sound to the chosen candidate." \ No newline at end of file diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi index 23f5e04c7db..343654c5810 100644 Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi index eefdb1ad455..bfb8378f049 100644 Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index e1f7fe92119..53e3b56f76c 100644 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ