diff --git a/code/game/gamemodes/changeling/powers/headcrab.dm b/code/game/gamemodes/changeling/powers/headslug.dm similarity index 88% rename from code/game/gamemodes/changeling/powers/headcrab.dm rename to code/game/gamemodes/changeling/powers/headslug.dm index b39a2bba0d5..f29ec02db54 100644 --- a/code/game/gamemodes/changeling/powers/headcrab.dm +++ b/code/game/gamemodes/changeling/powers/headslug.dm @@ -1,4 +1,4 @@ -/datum/action/changeling/headcrab +/datum/action/changeling/headslug name = "Last Resort" desc = "We sacrifice our current body in a moment of need, placing us in control of a vessel that can plant our likeness in a new host. Costs 20 chemicals." helptext = "We will be placed in control of a small, fragile creature. We may attack a corpse like this to plant an egg which will slowly mature into a new form for us." @@ -7,12 +7,12 @@ dna_cost = 1 req_human = 1 -/datum/action/changeling/headcrab/try_to_sting(mob/user, mob/target) +/datum/action/changeling/headslug/try_to_sting(mob/user, mob/target) if(alert("Are you sure you wish to do this? This action cannot be undone.",,"Yes","No")=="No") return ..() -/datum/action/changeling/headcrab/sting_action(mob/user) +/datum/action/changeling/headslug/sting_action(mob/user) var/datum/mind/M = user.mind var/list/organs = user.get_organs_zone("head", 1) @@ -33,7 +33,7 @@ S.Weaken(3) var/new_location = user.drop_location() spawn(5) // So it's not killed in explosion - var/mob/living/simple_animal/hostile/headcrab/crab = new(new_location) + var/mob/living/simple_animal/hostile/headslug/crab = new(new_location) for(var/obj/item/organ/internal/I in organs) I.loc = crab crab.origin = M diff --git a/code/modules/events/headcrabs.dm b/code/modules/events/headcrabs.dm new file mode 100644 index 00000000000..58c3e918b0a --- /dev/null +++ b/code/modules/events/headcrabs.dm @@ -0,0 +1,63 @@ +#define LOC_FPMAINT 0 +#define LOC_FPMAINT1 1 + +#define HEADCRAB_NORMAL 0 +#define HEADCRAB_SPECIAL 1 +#define HEADCRAB_CLOWN 2 + +/datum/event/headcrabs + announceWhen = 10 + endWhen = 11 + var/location + var/locstring + var/headcrab + +/datum/event/headcrabs/start() + + location = rand(0,1) + var/list/turf/simulated/floor/turfs = list() + var/spawn_area_type + switch(location) + if(LOC_FPMAINT) + spawn_area_type = /area/maintenance/fpmaint2 + locstring = "Arrivals North Maintenance" + if(LOC_FPMAINT1) + spawn_area_type = /area/maintenance/fpmaint2 + locstring = "Arrivals North Maintenance" + + for(var/areapath in typesof(spawn_area_type)) + var/area/A = locate(areapath) + for(var/turf/simulated/floor/F in A.contents) + if(turf_clear(F)) + turfs += F + + var/list/spawn_types = list() + var/max_number + headcrab = rand(0,1) + switch(headcrab) + if(HEADCRAB_NORMAL) + spawn_types = list(/mob/living/simple_animal/hostile/headcrab) + max_number = 12 + if(HEADCRAB_SPECIAL) + spawn_types = list(/mob/living/simple_animal/hostile/headcrab) + max_number = 12 + + spawn(0) + var/num = rand(2,max_number) + while(turfs.len > 0 && num > 0) + var/turf/simulated/floor/T = pick(turfs) + turfs.Remove(T) + num-- + var/spawn_type = pick(spawn_types) + new spawn_type(T) + + +/datum/event/headcrabs/announce() + event_announcement.Announce("Bioscans indicate that creatues have been breeding in [locstring]. Clear them out, before this starts to affect productivity.", "Lifesign Alert") + +#undef LOC_FPMAINT +#undef LOC_FPMAINT1 + +#undef HEADCRAB_NORMAL +#undef HEADCRAB_SPECIAL +#undef HEADCRAB_CLOWN \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/headcrab.dm b/code/modules/mob/living/simple_animal/hostile/headcrab.dm index c82a0ee7806..d80e6df1ef9 100644 --- a/code/modules/mob/living/simple_animal/hostile/headcrab.dm +++ b/code/modules/mob/living/simple_animal/hostile/headcrab.dm @@ -1,100 +1,73 @@ -#define EGG_INCUBATION_TIME 120 - /mob/living/simple_animal/hostile/headcrab - name = "headslug" - desc = "Absolutely not de-beaked or harmless. Keep away from corpses." + name = "headcrab" + desc = "A headcrab. Run!" + icon = 'icons/mob/headcrab.dmi' icon_state = "headcrab" icon_living = "headcrab" - icon_dead = "headcrab_dead" - icon = 'icons/mob/mob.dmi' - health = 50 - maxHealth = 50 - melee_damage_lower = 5 - melee_damage_upper = 5 - attacktext = "chomps" - attack_sound = 'sound/weapons/bite.ogg' - faction = list("creature") - robust_searching = 1 - stat_attack = 2 - obj_damage = 0 - environment_smash = 0 - speak_emote = list("squeaks") - ventcrawler = 2 - var/datum/mind/origin - var/egg_lain = 0 + health = 40 + maxHealth = 40 + melee_damage_lower = 8 + melee_damage_upper = 16 + attacktext = "bites" + attack_sound = 'sound/effects/bite.ogg' + speak_emote = list("hisses") + var/is_zombie = 0 + stat_attack = 1 //so they continue to attack when they are on the ground. + var/list/human_overlays = list() -/mob/living/simple_animal/hostile/headcrab/examine(mob/user) + +/mob/living/simple_animal/hostile/headcrab/Life(seconds, times_fired) + if(!is_zombie && isturf(src.loc)) + for(var/mob/living/carbon/human/H in oview(src, 1)) //Only for corpse right next to/on same tile + if(H.stat == DEAD || (!H.check_death_method() && H.health <= HEALTH_THRESHOLD_DEAD)) + Zombify(H) + break ..() - if(stat == DEAD) - to_chat(desc = "It appears to be dead.") -/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/internal/I in src) - I.loc = egg - visible_message("[src] plants something in [victim]'s flesh!", \ - "We inject our egg into [victim]'s body!") - egg_lain = 1 +/mob/living/simple_animal/hostile/headcrab/proc/Zombify(mob/living/carbon/human/H) + if(!H.check_death_method()) + H.death() + var/obj/item/organ/external/head/head_organ = H.get_organ("head") + is_zombie = TRUE + if(H.wear_suit) + var/obj/item/clothing/suit/armor/A = H.wear_suit + if(A.armor && A.armor["melee"]) + maxHealth += A.armor["melee"] //That zombie's got armor, I want armor! + maxHealth += 40 + health = maxHealth + name = "zombie" + desc = "A corpse animated by the alien being on its head." + melee_damage_lower = 10 + melee_damage_upper = 15 + icon = H.icon + speak_emote = list("groans") + attack_sound = 'sound/weapons/genhit1.ogg' + icon_state = "zombie2_s" + if(head_organ) + head_organ.h_style = null + H.update_hair() + human_overlays = H.overlays + update_icons() + H.forceMove(src) + visible_message("The corpse of [H.name] suddenly rises!") -/mob/living/simple_animal/hostile/headcrab/AttackingTarget() - if(egg_lain) - target.attack_animal(src) - return - if(iscarbon(target) && !issmall(target)) - // Changeling egg can survive in aliens! - var/mob/living/carbon/C = target - if(C.stat == DEAD) - if(C.status_flags & XENO_HOST) - to_chat(src, "A foreign presence repels us from this body. Perhaps we should try to infest another?") - return - Infect(target) - to_chat(src, "With our egg laid, our death approaches rapidly...") - spawn(100) - death() - return - target.attack_animal(src) +/mob/living/simple_animal/hostile/headcrab/death(gibbed) + // Only execute the below if we successfuly died + . = ..() + // Setup up the smoke spreader and start it. + qdel(src) -/obj/item/organ/internal/body_egg/changeling_egg - name = "changeling egg" - desc = "Twitching and disgusting." - origin_tech = "biotech=7" // You need to be really lucky to obtain it. - var/datum/mind/origin - var/time +/mob/living/simple_animal/hostile/headcrab/Destroy() + if(contents) + for(var/mob/M in contents) + M.loc = get_turf(src) + return ..() -/obj/item/organ/internal/body_egg/changeling_egg/egg_process() - // Changeling eggs grow in dead people - time++ - if(time >= EGG_INCUBATION_TIME) - Pop() - remove(owner) - qdel(src) -/obj/item/organ/internal/body_egg/changeling_egg/proc/Pop() - var/mob/living/carbon/human/monkey/M = new(owner) - owner.stomach_contents += M - - for(var/obj/item/organ/internal/I in src) - I.insert(M, 1) - - if(origin && origin.current && (origin.current.stat == DEAD)) - origin.transfer_to(M) - if(!origin.changeling) - M.make_changeling() - if(origin.changeling.can_absorb_dna(M, owner)) - origin.changeling.absorb_dna(owner, M) - - var/datum/action/changeling/humanform/HF = new - HF.Grant(M) - for(var/power in origin.changeling.purchasedpowers) - var/datum/action/changeling/S = power - if(istype(S) && S.needs_button) - S.Grant(M) - M.key = origin.key - owner.gib() - -#undef EGG_INCUBATION_TIME +/mob/living/simple_animal/hostile/headcrab/update_icons() + ..() + if(is_zombie) + overlays.Cut() + overlays = human_overlays + var/image/I = image('icons/mob/headcrab.dmi', icon_state = "headcrabpod") + overlays += I diff --git a/code/modules/mob/living/simple_animal/hostile/headslug.dm b/code/modules/mob/living/simple_animal/hostile/headslug.dm new file mode 100644 index 00000000000..e2fc98c483f --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/headslug.dm @@ -0,0 +1,100 @@ +#define EGG_INCUBATION_TIME 120 + +/mob/living/simple_animal/hostile/headslug + name = "headslug" + desc = "Absolutely not de-beaked or harmless. Keep away from corpses." + icon_state = "headslug" + icon_living = "headslug" + icon_dead = "headslug_dead" + icon = 'icons/mob/mob.dmi' + health = 50 + maxHealth = 50 + melee_damage_lower = 5 + melee_damage_upper = 5 + attacktext = "chomps" + attack_sound = 'sound/weapons/bite.ogg' + faction = list("creature") + robust_searching = 1 + stat_attack = 2 + obj_damage = 0 + environment_smash = 0 + speak_emote = list("squeaks") + ventcrawler = 2 + var/datum/mind/origin + var/egg_lain = 0 + +/mob/living/simple_animal/hostile/headslug/examine(mob/user) + ..() + if(stat == DEAD) + to_chat(desc = "It appears to be dead.") + +/mob/living/simple_animal/hostile/headslug/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/internal/I in src) + I.loc = egg + visible_message("[src] plants something in [victim]'s flesh!", \ + "We inject our egg into [victim]'s body!") + egg_lain = 1 + +/mob/living/simple_animal/hostile/headslug/AttackingTarget() + if(egg_lain) + target.attack_animal(src) + return + if(iscarbon(target) && !issmall(target)) + // Changeling egg can survive in aliens! + var/mob/living/carbon/C = target + if(C.stat == DEAD) + if(C.status_flags & XENO_HOST) + to_chat(src, "A foreign presence repels us from this body. Perhaps we should try to infest another?") + return + Infect(target) + to_chat(src, "With our egg laid, our death approaches rapidly...") + spawn(100) + death() + return + target.attack_animal(src) + +/obj/item/organ/internal/body_egg/changeling_egg + name = "changeling egg" + desc = "Twitching and disgusting." + origin_tech = "biotech=7" // You need to be really lucky to obtain it. + var/datum/mind/origin + var/time + +/obj/item/organ/internal/body_egg/changeling_egg/egg_process() + // Changeling eggs grow in dead people + time++ + if(time >= EGG_INCUBATION_TIME) + Pop() + remove(owner) + qdel(src) + +/obj/item/organ/internal/body_egg/changeling_egg/proc/Pop() + var/mob/living/carbon/human/monkey/M = new(owner) + owner.stomach_contents += M + + for(var/obj/item/organ/internal/I in src) + I.insert(M, 1) + + if(origin && origin.current && (origin.current.stat == DEAD)) + origin.transfer_to(M) + if(!origin.changeling) + M.make_changeling() + if(origin.changeling.can_absorb_dna(M, owner)) + origin.changeling.absorb_dna(owner, M) + + var/datum/action/changeling/humanform/HF = new + HF.Grant(M) + for(var/power in origin.changeling.purchasedpowers) + var/datum/action/changeling/S = power + if(istype(S) && S.needs_button) + S.Grant(M) + M.key = origin.key + owner.gib() + +#undef EGG_INCUBATION_TIME diff --git a/icons/mob/headcrab.dmi b/icons/mob/headcrab.dmi new file mode 100644 index 00000000000..27d05247da4 Binary files /dev/null and b/icons/mob/headcrab.dmi differ diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi index 014242b9d90..ed193927004 100644 Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ diff --git a/paradise.dme b/paradise.dme index c49361b8e20..24320509982 100644 --- a/paradise.dme +++ b/paradise.dme @@ -477,7 +477,7 @@ #include "code\game\gamemodes\changeling\powers\epinephrine.dm" #include "code\game\gamemodes\changeling\powers\fakedeath.dm" #include "code\game\gamemodes\changeling\powers\fleshmend.dm" -#include "code\game\gamemodes\changeling\powers\headcrab.dm" +#include "code\game\gamemodes\changeling\powers\headslug.dm" #include "code\game\gamemodes\changeling\powers\hivemind.dm" #include "code\game\gamemodes\changeling\powers\humanform.dm" #include "code\game\gamemodes\changeling\powers\lesserform.dm" @@ -1436,6 +1436,7 @@ #include "code\modules\events\false_alarm.dm" #include "code\modules\events\floorcluwne.dm" #include "code\modules\events\grid_check.dm" +#include "code\modules\events\headcrabs.dm" #include "code\modules\events\immovable_rod.dm" #include "code\modules\events\infestation.dm" #include "code\modules\events\ion_storm.dm" @@ -1903,6 +1904,7 @@ #include "code\modules\mob\living\simple_animal\hostile\floorcluwne.dm" #include "code\modules\mob\living\simple_animal\hostile\giant_spider.dm" #include "code\modules\mob\living\simple_animal\hostile\headcrab.dm" +#include "code\modules\mob\living\simple_animal\hostile\headslug.dm" #include "code\modules\mob\living\simple_animal\hostile\hellhound.dm" #include "code\modules\mob\living\simple_animal\hostile\hivebot.dm" #include "code\modules\mob\living\simple_animal\hostile\hostile.dm"