[MIRROR] Turns Changeling Headslugs into a Basic Mob [MDB IGNORE] (#21690)

* Turns Changeling Headslugs into a Basic Mob

* fix

---------

Co-authored-by: san7890 <the@san7890.com>
Co-authored-by: ghost sheep <sheepwiththemask@gmail.com>
This commit is contained in:
SkyratBot
2023-06-07 16:01:15 +00:00
committed by GitHub
co-authored by san7890 ghost sheep
parent 85c31e1256
commit c968dca9b2
11 changed files with 147 additions and 128 deletions
+2 -2
View File
@@ -255,7 +255,9 @@
/mob/living/basic/cow/wisdom,
/mob/living/basic/giant_spider,
/mob/living/basic/giant_spider/hunter,
/mob/living/basic/headslug,
/mob/living/basic/killer_tomato,
/mob/living/basic/lizard,
/mob/living/basic/mouse,
/mob/living/basic/pet/dog/breaddog,
/mob/living/basic/pet/dog/corgi,
@@ -269,8 +271,6 @@
/mob/living/simple_animal/hostile/bear,
/mob/living/simple_animal/hostile/blob/blobbernaut/independent,
/mob/living/simple_animal/hostile/gorilla,
/mob/living/simple_animal/hostile/headcrab,
/mob/living/basic/lizard,
/mob/living/simple_animal/hostile/megafauna/dragon/lesser,
/mob/living/simple_animal/hostile/morph,
/mob/living/simple_animal/hostile/mushroom,
@@ -0,0 +1,43 @@
#define EGG_INCUBATION_TIME (4 MINUTES)
/// The actual organ that the changeling headslug implants into a dead host.
/obj/item/organ/internal/body_egg/changeling_egg
name = "changeling egg"
desc = "Twitching and disgusting."
/// The mind of the original changeling that gave forth to the headslug mob.
var/datum/mind/origin
/// Tracks how long the egg has been growing.
var/time = 0
/obj/item/organ/internal/body_egg/changeling_egg/egg_process(seconds_per_tick, times_fired)
// Changeling eggs grow in dead people
time += seconds_per_tick * 10
if(time >= EGG_INCUBATION_TIME)
pop()
/// Once the egg is fully grown, we gib the host and spawn a monkey (with the changeling's player controlling it). Very descriptive proc name.
/obj/item/organ/internal/body_egg/changeling_egg/proc/pop()
var/mob/living/carbon/human/spawned_monkey = new(owner)
spawned_monkey.set_species(/datum/species/monkey)
for(var/obj/item/organ/insertable in src)
insertable.Insert(spawned_monkey, 1)
if(origin && (origin.current ? (origin.current.stat == DEAD) : origin.get_ghost()))
origin.transfer_to(spawned_monkey)
spawned_monkey.key = origin.key
var/datum/antagonist/changeling/changeling_datum = origin.has_antag_datum(/datum/antagonist/changeling)
if(!changeling_datum)
changeling_datum = origin.add_antag_datum(/datum/antagonist/changeling/headslug)
if(changeling_datum.can_absorb_dna(owner))
changeling_datum.add_new_profile(owner)
var/datum/action/changeling/lesserform/transform = new()
changeling_datum.purchased_powers[transform.type] = transform
changeling_datum.regain_powers()
owner.investigate_log("has been gibbed by a changeling egg burst.", INVESTIGATE_DEATHS)
owner.gib()
qdel(src)
#undef EGG_INCUBATION_TIME
@@ -40,13 +40,10 @@
addtimer(CALLBACK(src, PROC_REF(spawn_headcrab), stored_mind, user_turf, organs), 3 SECONDS)
/datum/action/changeling/headcrab/proc/spawn_headcrab(datum/mind/stored_mind, turf/spawn_location, list/organs)
var/mob/living/simple_animal/hostile/headcrab/crab = new(spawn_location)
var/mob/living/basic/headslug/crab = new(spawn_location)
for(var/obj/item/organ/I in organs)
I.forceMove(crab)
crab.origin = stored_mind
if(!crab.origin)
return
crab.origin.active = TRUE
crab.origin.transfer_to(crab)
stored_mind.transfer_to(crab)
spawn_location.transfer_observers_to(crab)
to_chat(crab, span_warning("You burst out of the remains of your former body in a shower of gore!"))
+1 -1
View File
@@ -56,7 +56,7 @@
if(contents.len >= max_occupants)
to_chat(user, span_warning("[src] are full!"))
return
if(istype(target, /mob/living/simple_animal/hostile/retaliate/snake) || istype(target, /mob/living/simple_animal/hostile/headcrab) || islarva(target))
if(istype(target, /mob/living/simple_animal/hostile/retaliate/snake) || istype(target, /mob/living/basic/headslug) || islarva(target))
target.forceMove(src)
to_chat(user, span_notice("[target] slithers into [src]."))
@@ -0,0 +1,92 @@
/**
* ## Headslugs
*
* Player-controlled slugs that arise from a changeling ability in order to live on in an extremely limited capacity until they can find a suitable corpse to inhabit.
*/
/mob/living/basic/headslug
name = "headslug"
desc = "A small, slug-like creature with a large, gaping maw. It's covered in a thick, slimy mucus."
icon_state = "headslug"
icon_living = "headslug"
icon_dead = "headslug_dead"
gender = NEUTER
health = 50
maxHealth = 50
melee_damage_lower = 5
melee_damage_upper = 5
attack_verb_continuous = "chomps"
attack_verb_simple = "chomp"
attack_sound = 'sound/weapons/bite.ogg'
attack_vis_effect = ATTACK_EFFECT_BITE
faction = list(FACTION_CREATURE)
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
speak_emote = list("squeaks")
ai_controller = /datum/ai_controller/basic_controller/headslug
/// Set to true once we've implanted our egg
var/egg_lain = FALSE
/mob/living/basic/headslug/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
RegisterSignal(src, COMSIG_HOSTILE_POST_ATTACKINGTARGET, PROC_REF(check_and_implant))
/mob/living/basic/headslug/Destroy()
UnregisterSignal(src, COMSIG_HOSTILE_POST_ATTACKINGTARGET)
return ..()
/mob/living/basic/headslug/examine(mob/user)
. = ..()
if(isnull(client))
. += span_notice("It appears to be moving around listlessly.")
else
. += span_warning("It's moving around intelligently!")
/// Signal Handler proc that runs on every attack and checks to see if this is a valid target for implantation. If so, it implants the egg and starts the countdown to death.
/mob/living/basic/headslug/proc/check_and_implant(mob/living/basic/attacker, atom/target)
SIGNAL_HANDLER
if (egg_lain || !iscarbon(target) || ismonkey(target))
return
var/mob/living/carbon/victim = target
if(victim.stat == DEAD)
return
if(HAS_TRAIT(victim, TRAIT_XENO_HOST))
target.balloon_alert(src, "already pregnant!") // Maybe the worst balloon alert in the codebase
return
if(!infect(victim))
target.balloon_alert(src, "failed to implant egg!")
stack_trace("[key] in [src] failed to implant egg in [victim], despite all checks suggesting it should have worked!")
return
egg_lain = TRUE
to_chat(src, span_userdanger("With our egg laid, our death approaches rapidly..."))
addtimer(CALLBACK(src, PROC_REF(death)), 10 SECONDS)
/// Simply infects the target corpse with our changeling eggs. This shouldn't fail, because all checks should have been done in check_and_implant()
/// Just to be super-duper safe to the player, we do return TRUE if all goes well and read that value in check_and_implant() to be nice to the player.
/mob/living/basic/headslug/proc/infect(mob/living/carbon/victim)
var/obj/item/organ/internal/body_egg/changeling_egg/egg = new(victim)
egg.Insert(victim)
egg.origin = mind
for(var/obj/item/organ/target in src)
target.forceMove(egg)
visible_message(
span_warning("[src] plants something in [victim]'s flesh!"),
span_danger("We inject our egg into [victim]'s body!"),
)
return TRUE
/// This is a bit neutered since these aren't intended to exist outside of player control, but it's a bit weird to just have these guys be completely stationary.
/// No attacking or anything like that, though. Just something so they seem alive.
/datum/ai_controller/basic_controller/headslug
ai_movement = /datum/ai_movement/basic_avoidance
idle_behavior = /datum/idle_behavior/idle_random_walk
+1 -1
View File
@@ -1445,6 +1445,7 @@
/mob/living/basic/cow,
/mob/living/basic/giant_spider,
/mob/living/basic/giant_spider/hunter,
/mob/living/basic/headslug,
/mob/living/basic/killer_tomato,
/mob/living/basic/lizard,
/mob/living/basic/mouse,
@@ -1460,7 +1461,6 @@
/mob/living/simple_animal/hostile/bear,
/mob/living/simple_animal/hostile/blob/blobbernaut/independent,
/mob/living/simple_animal/hostile/gorilla,
/mob/living/simple_animal/hostile/headcrab,
/mob/living/simple_animal/hostile/megafauna/dragon/lesser,
/mob/living/simple_animal/hostile/morph,
/mob/living/simple_animal/hostile/mushroom,
@@ -1,113 +0,0 @@
#define EGG_INCUBATION_TIME (4 MINUTES)
/mob/living/simple_animal/hostile/headcrab
name = "headslug"
desc = "Absolutely not de-beaked or harmless. Keep away from corpses."
icon_state = "headcrab"
icon_living = "headcrab"
icon_dead = "headcrab_dead"
gender = NEUTER
health = 50
maxHealth = 50
melee_damage_lower = 5
melee_damage_upper = 5
attack_verb_continuous = "chomps"
attack_verb_simple = "chomp"
attack_sound = 'sound/weapons/bite.ogg'
attack_vis_effect = ATTACK_EFFECT_BITE
faction = list(FACTION_CREATURE)
robust_searching = 1
stat_attack = DEAD
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
speak_emote = list("squeaks")
/// The mind to transfer to our egg when it hatches
var/datum/mind/origin
/// Set to true once we've implanted our egg
var/egg_lain = FALSE
/mob/living/simple_animal/hostile/headcrab/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
/mob/living/simple_animal/hostile/headcrab/proc/Infect(mob/living/carbon/victim)
var/obj/item/organ/internal/body_egg/changeling_egg/egg = new(victim)
egg.Insert(victim)
if(origin)
egg.origin = origin
else if(mind) // Let's make this a feature
egg.origin = mind
for(var/obj/item/organ/I in src)
I.forceMove(egg)
visible_message(span_warning("[src] plants something in [victim]'s flesh!"), \
span_danger("We inject our egg into [victim]'s body!"))
egg_lain = TRUE
/mob/living/simple_animal/hostile/headcrab/AttackingTarget()
. = ..()
if (!. || egg_lain || !iscarbon(target) || ismonkey(target))
return
var/mob/living/carbon/victim = target
if(victim.stat != DEAD)
return
if(HAS_TRAIT(victim, TRAIT_XENO_HOST))
target.balloon_alert(src, "already pregnant!") // Maybe the worst balloon alert in the codebase
return
Infect(target)
to_chat(src, span_userdanger("With our egg laid, our death approaches rapidly..."))
addtimer(CALLBACK(src, PROC_REF(death)), 10 SECONDS)
/obj/item/organ/internal/body_egg/changeling_egg
name = "changeling egg"
desc = "Twitching and disgusting."
var/datum/mind/origin
var/time = 0
/obj/item/organ/internal/body_egg/changeling_egg/egg_process(seconds_per_tick, times_fired)
// Changeling eggs grow in dead people
time += seconds_per_tick * 10
if(time >= EGG_INCUBATION_TIME)
Pop()
Remove(owner)
qdel(src)
/obj/item/organ/internal/body_egg/changeling_egg/proc/Pop()
// SKYRAT EDIT START
var/mob/living/carbon/human/species/monkey/spawned_monkey = new(owner)
var/datum/dna/current_dna = spawned_monkey.dna
for(var/key in current_dna.mutant_bodyparts)
LAZYSET(current_dna.mutant_bodyparts, key, "None")
for(var/key in current_dna.body_markings)
LAZYSET(current_dna.body_markings, key, null)
if(current_dna.features["body_size"])
LAZYSET(current_dna.features, "body_size", 1)
if(current_dna.features["legs"])
LAZYREMOVE(current_dna.features, "legs")
spawned_monkey.set_species(/datum/species/monkey)
for(var/scar in spawned_monkey.all_scars)
var/datum/scar/iter_scar = scar
if(iter_scar.fake)
qdel(iter_scar)
spawned_monkey.regenerate_icons()
// SKYRAT EDIT END
for(var/obj/item/organ/I in src)
I.Insert(spawned_monkey, 1)
if(origin && (origin.current ? (origin.current.stat == DEAD) : origin.get_ghost()))
origin.transfer_to(spawned_monkey)
spawned_monkey.key = origin.key
var/datum/antagonist/changeling/changeling_datum = origin.has_antag_datum(/datum/antagonist/changeling)
if(!changeling_datum)
changeling_datum = origin.add_antag_datum(/datum/antagonist/changeling/headslug)
if(changeling_datum.can_absorb_dna(owner))
changeling_datum.add_new_profile(owner)
var/datum/action/changeling/lesserform/transform = new()
changeling_datum.purchased_powers[transform.type] = transform
changeling_datum.regain_powers()
owner.investigate_log("has been gibbed by a changeling egg burst.", INVESTIGATE_DEATHS)
owner.gib()
#undef EGG_INCUBATION_TIME
@@ -48,10 +48,10 @@
/// Dead headcrab for changeling-themed ruins
/obj/effect/mob_spawn/corpse/headcrab
mob_type = /mob/living/simple_animal/hostile/headcrab
mob_type = /mob/living/basic/headslug
icon = 'icons/mob/simple/animal.dmi'
icon_state = "headcrab_dead"
icon_state = "headslug_dead"
/obj/effect/mob_spawn/corpse/headcrab/special(mob/living/simple_animal/hostile/headcrab/crab)
/obj/effect/mob_spawn/corpse/headcrab/special(mob/living/basic/headslug/crab)
. = ..()
crab.egg_lain = TRUE // Prevents using mad science to become a changeling
@@ -156,7 +156,6 @@
/mob/living/simple_animal/hostile/guardian/ranged,
/mob/living/simple_animal/hostile/guardian/standard,
/mob/living/simple_animal/hostile/guardian/support,
/mob/living/simple_animal/hostile/headcrab,
/mob/living/simple_animal/hostile/heretic_summon,
/mob/living/simple_animal/hostile/heretic_summon/armsy,
/mob/living/simple_animal/hostile/heretic_summon/armsy/prime,
Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 KiB

After

Width:  |  Height:  |  Size: 276 KiB

+2 -1
View File
@@ -2595,6 +2595,7 @@
#include "code\modules\antagonists\changeling\changeling.dm"
#include "code\modules\antagonists\changeling\changeling_power.dm"
#include "code\modules\antagonists\changeling\fallen_changeling.dm"
#include "code\modules\antagonists\changeling\headslug_eggs.dm"
#include "code\modules\antagonists\changeling\powers\absorb.dm"
#include "code\modules\antagonists\changeling\powers\adrenaline.dm"
#include "code\modules\antagonists\changeling\powers\augmented_eyesight.dm"
@@ -4052,6 +4053,7 @@
#include "code\modules\mob\living\basic\space_fauna\faithless.dm"
#include "code\modules\mob\living\basic\space_fauna\garden_gnome.dm"
#include "code\modules\mob\living\basic\space_fauna\ghost.dm"
#include "code\modules\mob\living\basic\space_fauna\headslug.dm"
#include "code\modules\mob\living\basic\space_fauna\killer_tomato.dm"
#include "code\modules\mob\living\basic\space_fauna\lightgeist.dm"
#include "code\modules\mob\living\basic\space_fauna\carp\carp.dm"
@@ -4297,7 +4299,6 @@
#include "code\modules\mob\living\simple_animal\hostile\blobspore.dm"
#include "code\modules\mob\living\simple_animal\hostile\dark_wizard.dm"
#include "code\modules\mob\living\simple_animal\hostile\eyeballs.dm"
#include "code\modules\mob\living\simple_animal\hostile\headcrab.dm"
#include "code\modules\mob\living\simple_animal\hostile\heretic_monsters.dm"
#include "code\modules\mob\living\simple_animal\hostile\hivebot.dm"
#include "code\modules\mob\living\simple_animal\hostile\hostile.dm"