diff --git a/code/datums/disease.dm b/code/datums/disease.dm index 3f5288071ca..9410a798d7d 100644 --- a/code/datums/disease.dm +++ b/code/datums/disease.dm @@ -174,8 +174,8 @@ var/list/diseases = typesof(/datum/disease) - /datum/disease if(resistance && !(type in affected_mob.resistances)) var/saved_type = "[type]" affected_mob.resistances += text2path(saved_type) - if(istype(src, /datum/disease/alien_embryo)) //Get rid of the infection flag if it's a xeno embryo. - affected_mob.status_flags &= ~(XENO_HOST) + /*if(istype(src, /datum/disease/alien_embryo)) //Get rid of the infection flag if it's a xeno embryo. + affected_mob.status_flags &= ~(XENO_HOST)*/ affected_mob.viruses -= src //remove the datum from the list del(src) //delete the datum to stop it processing return diff --git a/code/datums/diseases/alien_embryo.dm b/code/datums/diseases/alien_embryo.dm index 1da982aa550..25dfc3fb292 100644 --- a/code/datums/diseases/alien_embryo.dm +++ b/code/datums/diseases/alien_embryo.dm @@ -1,5 +1,7 @@ //affected_mob.contract_disease(new /datum/disease/alien_embryo) +//cael - retained this file for legacy reference, see code\modules\mob\living\carbon\alien\special\alien_embryo.dm for replacement + //Our own special process so that dead hosts still chestburst /datum/disease/alien_embryo/process() if(!holder) return @@ -97,6 +99,9 @@ gibbed = 1 return +/datum/disease/alien_embryo/stage_change(var/old_stage) + RefreshInfectionImage() + /*---------------------------------------- Proc: RefreshInfectionImage() Des: Removes all infection images from aliens and places an infection image on all infected mobs for aliens. @@ -106,7 +111,7 @@ Des: Removes all infection images from aliens and places an infection image on a for (var/mob/living/carbon/alien/alien in player_list) if (alien.client) for(var/image/I in alien.client.images) - if(I.icon_state == "infected") + if(dd_hasprefix_case(I.icon_state, "infected")) del(I) for (var/mob/living/carbon/alien/alien in player_list) @@ -114,7 +119,7 @@ Des: Removes all infection images from aliens and places an infection image on a for (var/mob/living/carbon/C in mob_list) if(C) if (C.status_flags & XENO_HOST) - var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected") + var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[stage]") alien.client.images += I return @@ -127,7 +132,7 @@ Des: Checks if the passed mob (C) is infected with the alien egg, then gives eac for (var/mob/living/carbon/alien/alien in player_list) if (alien.client) if (C.status_flags & XENO_HOST) - var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected") + var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[stage]") alien.client.images += I return @@ -142,6 +147,6 @@ Des: Removes the alien infection image from all aliens in the world located in p if (alien.client) for(var/image/I in alien.client.images) if(I.loc == C) - if(I.icon_state == "infected") + if(dd_hasprefix_case(I.icon_state, "infected")) del(I) return diff --git a/code/game/objects/effects/aliens.dm b/code/game/objects/effects/aliens.dm index 4fc53b92664..b86bf3404dd 100644 --- a/code/game/objects/effects/aliens.dm +++ b/code/game/objects/effects/aliens.dm @@ -358,8 +358,9 @@ Alien plants should do something if theres a lot of poison */ /var/const //for the status var BURST = 0 - GROWING = 1 - GROWN = 2 + BURSTING = 1 + GROWING = 2 + GROWN = 3 MIN_GROWTH_TIME = 1800 //time it takes to grow a hugger MAX_GROWTH_TIME = 3000 @@ -394,8 +395,7 @@ Alien plants should do something if theres a lot of poison return if(GROWN) user << "\red You retrieve the child." - loc.contents += GetFacehugger()//need to write the code for giving it to the alien later - Burst() + Burst(0) return else return attack_hand(user) @@ -416,12 +416,20 @@ Alien plants should do something if theres a lot of poison proc/Burst(var/kill = 1) //drops and kills the hugger if any is remaining var/obj/item/clothing/mask/facehugger/child = GetFacehugger() - if(kill && istype(child)) - loc.contents += child - child.Die() - icon_state = "egg_hatched" - status = BURST + flick("egg_opening", src) + status = BURSTING + spawn(15) + status = BURST + loc.contents += child//need to write the code for giving it to the alien later + if(kill && istype(child)) + child.Die() + else + for(var/mob/M in range(1,src)) + if(CanHug(M)) + child.Attach(M) + break + return @@ -465,19 +473,9 @@ Alien plants should do something if theres a lot of poison if(status == GROWN) if(!CanHug(AM)) return + var/mob/living/carbon/C = AM - if(C.stat == CONSCIOUS && C.has_disease(new /datum/disease/alien_embryo(0))) + if(C.stat == CONSCIOUS && C.status_flags & XENO_HOST) return - status = BURST - flick("egg_opening", src) //Play animation - var/turf/pos = get_turf(src) - spawn(18) // Wait until the animation finishes - Burst(0) - var/obj/item/clothing/mask/facehugger/child = GetFacehugger() - child.loc = pos - if(!CanHug(AM)) - return - if(AM && in_range(AM, pos)) - child.Attach(AM) - + Burst(0) diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm index 3045159a625..8ba88796363 100644 --- a/code/game/objects/items/stacks/sheets/leather.dm +++ b/code/game/objects/items/stacks/sheets/leather.dm @@ -33,6 +33,36 @@ icon_state = "sheet-lizard" origin_tech = "" +/obj/item/stack/sheet/animalhide/xeno + name = "alien hide" + desc = "The skin of a terrible creature." + singular_name = "alien hide piece" + icon_state = "sheet-xeno" + origin_tech = "" + +//don't see anywhere else to put these, maybe together they could be used to make the xenos suit? +/obj/item/stack/sheet/xenochitin + name = "alien chitin" + desc = "A piece of the hide of a terrible creature." + singular_name = "alien hide piece" + icon = 'icons/mob/alien.dmi' + icon_state = "chitin" + origin_tech = "" + +/obj/item/xenos_claw + name = "alien claw" + desc = "The claw of a terrible creature." + icon = 'icons/mob/alien.dmi' + icon_state = "claw" + origin_tech = "" + +/obj/item/weed_extract + name = "weed extract" + desc = "A piece of slimy, purplish weed." + icon = 'icons/mob/alien.dmi' + icon_state = "weed_extract" + origin_tech = "" + /obj/item/stack/sheet/hairlesshide name = "hairless hide" desc = "This hide was stripped of it's hair, but still needs tanning." diff --git a/code/game/objects/items/weapons/surgery_tools.dm b/code/game/objects/items/weapons/surgery_tools.dm index d8e0f1db995..cc08b275e60 100644 --- a/code/game/objects/items/weapons/surgery_tools.dm +++ b/code/game/objects/items/weapons/surgery_tools.dm @@ -87,6 +87,45 @@ M:eye_op_stage = 2.0 + else if(user.zone_sel.selecting == "chest") + switch(M:alien_op_stage) + if(3.0) + var/mob/living/carbon/human/H = M + if(!istype(H)) + return ..() + + if(H.wear_suit || H.w_uniform) + user << "\red You're going to need to remove that suit/jumpsuit first." + return + + var/obj/item/alien_embryo/A = locate() in M.contents + if(!A) + return ..() + user.visible_message("\red [user] begins to pull something out of [M]'s chest.", "\red You begin to pull the alien organism out of [M]'s chest.") + + spawn(20 + rand(0,50)) + if(!A || A.loc != M) + return + + if(M == user && prob(25)) + user << "\red You mess up!" + if(istype(M, /mob/living/carbon/human)) + var/datum/organ/external/affecting = M:get_organ("chest") + if(affecting.take_damage(30)) + M:UpdateDamageIcon() + else + M.take_organ_damage(30) + + if(A.stage > 3) + var/chance = 15 + max(0, A.stage - 3) * 10 + if(prob(chance)) + A.AttemptGrow(0) + M:alien_op_stage = 4.0 + + if(M) + user.visible_message("\red [user] pulls an alien organism out of [M]'s chest.", "\red You pull the alien organism out of [M]'s chest.") + A.loc = M.loc //alien embryo handles cleanup + else if((!(user.zone_sel.selecting == "head")) || (!(user.zone_sel.selecting == "groin")) || (!(istype(M, /mob/living/carbon/human)))) return ..() @@ -184,6 +223,42 @@ M.take_organ_damage(15) M:eye_op_stage = 3.0 + else if(user.zone_sel.selecting == "chest") + if(M:alien_op_stage == 2.0 || M:alien_op_stage == 3.0) + var/mob/living/carbon/human/H = M + if(!istype(H)) + return ..() + + if(H.wear_suit || H.w_uniform) + user << "\red You're going to need to remove that suit/jumpsuit first." + return + + user.visible_message("\red [user] begins to dig around in [M]'s chest.", "\red You begin to dig around in [M]'s chest.") + + spawn(20 + (M:alien_op_stage == 3 ? 0 : rand(0,50))) + if(M == user && prob(25)) + user << "\red You mess up!" + if(istype(M, /mob/living/carbon/human)) + var/datum/organ/external/affecting = M:get_organ("chest") + if(affecting.take_damage(30)) + M:UpdateDamageIcon() + else + M.take_organ_damage(30) + + var/obj/item/alien_embryo/A = locate() in M.contents + if(A) + var/dat = "\blue You found an unknown alien organism in [M]'s chest!" + if(A.stage < 4) + dat += " It's small and weak, barely the size of a foetus." + if(A.stage > 3) + dat += " It's grown quite large, and writhes slightly as you look at it." + if(prob(10)) + A.AttemptGrow() + user << dat + M:alien_op_stage = 3.0 + else + user << "\blue You find nothing of interest." + else if((!(user.zone_sel.selecting == "head")) || (!(user.zone_sel.selecting == "groin")) || (!(istype(M, /mob/living/carbon/human)))) return ..() @@ -513,6 +588,33 @@ M.updatehealth() M:eye_op_stage = 1.0 user << "\blue So far so good after." + + else if(user.zone_sel.selecting == "chest") + switch(M:alien_op_stage) + if(0.0) + var/mob/living/carbon/human/H = M + if(!istype(H)) + return ..() + + if(H.wear_suit || H.w_uniform) + user << "\red You're going to need to remove that suit/jumpsuit first." + return + + user.visible_message("\red [user] begins to slice open [M]'s chest.", "\red You begin to slice open [M]'s chest.") + + spawn(rand(20,50)) + if(M == user && prob(25)) + user << "\red You mess up!" + if(istype(M, /mob/living/carbon/human)) + var/datum/organ/external/affecting = M:get_organ("chest") + if(affecting.take_damage(15)) + M:UpdateDamageIcon() + else + M.take_organ_damage(15) + + M:alien_op_stage = 1.0 + user << "\blue So far so good." + else return ..() /* wat @@ -657,6 +759,32 @@ ..() return + else if(user.zone_sel.selecting == "chest") + switch(M:alien_op_stage) + if(1.0) + var/mob/living/carbon/human/H = M + if(!istype(H)) + return ..() + + if(H.wear_suit || H.w_uniform) + user << "\red You're going to need to remove that suit/jumpsuit first." + return + + user.visible_message("\red [user] begins to slice through the bone of [M]'s chest.", "\red You begin to slice through the bone of [M]'s chest.") + + spawn(20 + rand(0,50)) + if(M == user && prob(25)) + user << "\red You mess up!" + if(istype(M, /mob/living/carbon/human)) + var/datum/organ/external/affecting = M:get_organ("chest") + if(affecting.take_damage(15)) + M:UpdateDamageIcon() + else + M.take_organ_damage(15) + + M:alien_op_stage = 2.0 + user << "\blue So far so good." + else return ..() /* diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 349022ba729..3cd4d43caec 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -240,73 +240,59 @@ return -/obj/structure/table/attack_paw(mob/user as mob) - if ((HULK in usr.mutations)) - usr << "\blue You destroy the table." - usr.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - visible_message("\red [user] smashes the table apart!") +/obj/structure/table/attack_paw(mob/user) + if(HULK in user.mutations) + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + visible_message("[user] smashes the table apart!") if(istype(src, /obj/structure/table/reinforced)) - new /obj/item/weapon/table_parts/reinforced( src.loc ) + new /obj/item/weapon/table_parts/reinforced(loc) else if(istype(src, /obj/structure/table/woodentable)) - new/obj/item/weapon/table_parts/wood( src.loc ) + new/obj/item/weapon/table_parts/wood(loc) else - new /obj/item/weapon/table_parts( src.loc ) - src.density = 0 + new /obj/item/weapon/table_parts(loc) + density = 0 del(src) - if (!( locate(/obj/structure/table, user.loc) )) - step(user, get_dir(user, src)) - if (user.loc == src.loc) - user.layer = TURF_LAYER - visible_message("[user] hides under the table!") - //Foreach goto(69) - return -/obj/structure/table/attack_alien(mob/user as mob) //Removed code for larva since it doesn't work. Previous code is now a larva ability. /N - usr << "\green You destroy the table." - visible_message("\red [user] slices the table apart!") +/obj/structure/table/attack_alien(mob/user) + visible_message("[user] slices [src] apart!") if(istype(src, /obj/structure/table/reinforced)) - new /obj/item/weapon/table_parts/reinforced( src.loc ) + new /obj/item/weapon/table_parts/reinforced(loc) else if(istype(src, /obj/structure/table/woodentable)) - new/obj/item/weapon/table_parts/wood( src.loc ) + new/obj/item/weapon/table_parts/wood(loc) else - new /obj/item/weapon/table_parts( src.loc ) - src.density = 0 + new /obj/item/weapon/table_parts(loc) + density = 0 del(src) - return -/obj/structure/table/attack_animal(mob/living/simple_animal/user as mob) +/obj/structure/table/attack_animal(mob/living/simple_animal/user) if(user.wall_smash) - usr << "\red You destroy the table." - visible_message("\red [user] smashes the table apart!") + visible_message("[user] smashes [src] apart!") if(istype(src, /obj/structure/table/reinforced)) - new /obj/item/weapon/table_parts/reinforced( src.loc ) + new /obj/item/weapon/table_parts/reinforced(loc) else if(istype(src, /obj/structure/table/woodentable)) - new/obj/item/weapon/table_parts/wood( src.loc ) + new/obj/item/weapon/table_parts/wood(loc) else - new /obj/item/weapon/table_parts( src.loc ) - src.density = 0 + new /obj/item/weapon/table_parts(loc) + density = 0 del(src) - return -/obj/structure/table/attack_hand(mob/user as mob) - if ((HULK in usr.mutations) || (SUPRSTR in usr.augmentations)) - usr << "\blue You destroy the table." - visible_message("\red [user] smashes the table apart!") - usr.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) +/obj/structure/table/attack_hand(mob/user) + if(HULK in user.mutations || SUPRSTR in user.augmentations) + visible_message("[user] smashes [src] apart!") + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) if(istype(src, /obj/structure/table/reinforced)) - new /obj/item/weapon/table_parts/reinforced( src.loc ) + new /obj/item/weapon/table_parts/reinforced(loc) else if(istype(src, /obj/structure/table/woodentable)) - new/obj/item/weapon/table_parts/wood( src.loc ) + new/obj/item/weapon/table_parts/wood(loc) else - new /obj/item/weapon/table_parts( src.loc ) - src.density = 0 + new /obj/item/weapon/table_parts(loc) + density = 0 del(src) - return /obj/structure/table/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) @@ -554,7 +540,6 @@ if (istype(W, /obj/item/weapon/wrench)) new /obj/item/weapon/rack_parts( src.loc ) playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - //SN src = null del(src) return if(isrobot(user)) @@ -564,4 +549,37 @@ return /obj/structure/rack/meteorhit(obj/O as obj) - del(src) \ No newline at end of file + del(src) + + +/obj/structure/table/attack_hand(mob/user) + if(HULK in user.mutations || SUPRSTR in user.augmentations) + visible_message("[user] smashes [src] apart!") + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + new /obj/item/weapon/rack_parts(loc) + density = 0 + del(src) + + +/obj/structure/rack/attack_paw(mob/user) + if(HULK in user.mutations) + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + visible_message("[user] smashes [src] apart!") + new /obj/item/weapon/rack_parts(loc) + density = 0 + del(src) + + +/obj/structure/rack/attack_alien(mob/user) + visible_message("[user] slices [src] apart!") + new /obj/item/weapon/rack_parts(loc) + density = 0 + del(src) + + +/obj/structure/rack/attack_animal(mob/living/simple_animal/user) + if(user.wall_smash) + visible_message("[user] smashes [src] apart!") + new /obj/item/weapon/rack_parts(loc) + density = 0 + del(src) \ No newline at end of file diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index 13aac3e7d75..f441e44adc7 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -171,3 +171,11 @@ icon_state = "bearpelt" item_state = "bearpelt" flags = FPRINT | TABLEPASS | BLOCKHAIR + +/obj/item/clothing/head/xenos + name = "xenos helmet" + icon_state = "xenos" + item_state = "xenos_helm" + desc = "A helmet made out of chitinous alien hide." + flags = FPRINT | TABLEPASS | BLOCKHAIR + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index f18a0020907..f3872473e71 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -211,4 +211,12 @@ else usr << "You button-up some imaginary buttons on your [src]." return - usr.update_inv_wear_suit() \ No newline at end of file + usr.update_inv_wear_suit() + +/obj/item/clothing/suit/xenos + name = "xenos suit" + desc = "A suit made out of chitinous alien hide." + icon_state = "xenos" + item_state = "xenos_helm" + body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 9aca088240e..21c6fc73e0f 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -185,9 +185,10 @@ Des: Gives the client of the alien an image on each infected mob. ----------------------------------------*/ /mob/living/carbon/alien/proc/AddInfectionImages() if (client) - for (var/mob/living/carbon/C in mob_list) + for (var/mob/living/C in mob_list) if(C.status_flags & XENO_HOST) - var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected") + var/obj/item/alien_embryo/A = locate() in C + var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[A.stage]") client.images += I return @@ -199,11 +200,10 @@ Des: Removes all infected images from the alien. /mob/living/carbon/alien/proc/RemoveInfectionImages() if (client) for(var/image/I in client.images) - if(I.icon_state == "infected") + if(dd_hasprefix_case(I.icon_state, "infected")) del(I) return - #undef HEAT_DAMAGE_LEVEL_1 #undef HEAT_DAMAGE_LEVEL_2 #undef HEAT_DAMAGE_LEVEL_3 diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index e2b7c404d73..77b306f89ba 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -142,7 +142,7 @@ Doesn't work on other aliens/AI.*/ if(!istype(U, /turf)) return - var/obj/item/projectile/energy/dart/A = new /obj/item/projectile/energy/dart(usr.loc) + var/obj/item/projectile/energy/neurotoxin/A = new /obj/item/projectile/energy/neurotoxin(usr.loc) A.current = U A.yo = U.y - T.y diff --git a/code/modules/mob/living/carbon/alien/humanoid/death.dm b/code/modules/mob/living/carbon/alien/humanoid/death.dm index 62324f75336..91138a43090 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/death.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/death.dm @@ -9,6 +9,7 @@ O.show_message("[src] lets out a waning guttural screech, green blood bubbling from its maw...", 1) update_canmove() if(client) blind.layer = 0 + update_icons() tod = worldtime2text() //weasellos time of death patch if(mind) mind.store_memory("Time of death: [tod]", 0) diff --git a/code/modules/mob/living/carbon/alien/humanoid/life.dm b/code/modules/mob/living/carbon/alien/humanoid/life.dm index d53ac234782..4eec8d5f3da 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/life.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/life.dm @@ -359,6 +359,8 @@ //Other if(stunned) AdjustStunned(-1) + if(!stunned) + update_icons() if(weakened) weakened = max(weakened-1,0) //before you get mad Rockdtben: I done this so update_canmove isn't called multiple times diff --git a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm index b647c5d714f..00c2d5b4075 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm @@ -14,9 +14,21 @@ lying_prev = lying //so we don't update overlays for lying/standing unless our stance changes again update_hud() //TODO: remove the need for this to be here overlays.Cut() - if(lying) - if(resting) icon_state = "alien[caste]_sleep" - else icon_state = "alien[caste]_l" + if(stat == DEAD) + //If we mostly took damage from fire + if(fireloss > 125) + icon_state = "alien[caste]_husked" + else + icon_state = "alien[caste]_dead" + for(var/image/I in overlays_lying) + overlays += I + else if(lying) + if(resting) + icon_state = "alien[caste]_sleep" + else if(stat == UNCONSCIOUS) + icon_state = "alien[caste]_unconscious" + else + icon_state = "alien[caste]_l" for(var/image/I in overlays_lying) overlays += I else diff --git a/code/modules/mob/living/carbon/alien/larva/death.dm b/code/modules/mob/living/carbon/alien/larva/death.dm index 4334a375774..27f49e3ad9e 100644 --- a/code/modules/mob/living/carbon/alien/larva/death.dm +++ b/code/modules/mob/living/carbon/alien/larva/death.dm @@ -2,7 +2,7 @@ if(stat == DEAD) return if(healths) healths.icon_state = "health6" stat = DEAD - icon_state = "larva_l" + icon_state = "larva_dead" if(!gibbed) update_canmove() diff --git a/code/modules/mob/living/carbon/alien/larva/emote.dm b/code/modules/mob/living/carbon/alien/larva/emote.dm index 4e812c74379..2be246fe8fb 100644 --- a/code/modules/mob/living/carbon/alien/larva/emote.dm +++ b/code/modules/mob/living/carbon/alien/larva/emote.dm @@ -88,6 +88,9 @@ if("jump") message = "The [src.name] jumps!" m_type = 1 + if("hiss_") + message = "The [src.name] hisses softly." + m_type = 1 if("collapse") Paralyse(2) message = text("[] collapses!", src) diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm index c52c63bed9d..b5fbf23bef2 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva.dm @@ -1,7 +1,7 @@ /mob/living/carbon/alien/larva name = "alien larva" real_name = "alien larva" - icon_state = "larva" + icon_state = "larva0" pass_flags = PASSTABLE maxHealth = 25 @@ -11,6 +11,7 @@ var/amount_grown = 0 var/max_grown = 200 + var/time_of_birth //This is fine right now, if we're adding organ specific damage this needs to be updated /mob/living/carbon/alien/larva/New() diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm index b2cb0ca4d75..f5d1d0c274e 100644 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ b/code/modules/mob/living/carbon/alien/larva/life.dm @@ -55,6 +55,9 @@ for(var/obj/item/weapon/grab/G in src) G.process() + //some kind of bug in canmove() isn't properly calling update_icons, so this is here as a placeholder + update_icons() + if(client) handle_regular_hud_updates() @@ -226,7 +229,7 @@ return 1 //UNCONSCIOUS. NO-ONE IS HOME - if( (getOxyLoss() > 50) || (0 > health) ) + if( (getOxyLoss() > 25) || (0 > health) ) //if( health <= 20 && prob(1) ) // spawn(0) // emote("gasp") @@ -244,7 +247,7 @@ stat = UNCONSCIOUS if( prob(10) && health ) spawn(0) - emote("hiss") + emote("hiss_") //CONSCIOUS else stat = CONSCIOUS diff --git a/code/modules/mob/living/carbon/alien/larva/powers.dm b/code/modules/mob/living/carbon/alien/larva/powers.dm index 2fb0625d921..a1806692dfa 100644 --- a/code/modules/mob/living/carbon/alien/larva/powers.dm +++ b/code/modules/mob/living/carbon/alien/larva/powers.dm @@ -28,12 +28,16 @@ if(stat != CONSCIOUS) return + if(handcuffed || legcuffed) + src << "\red You cannot evolve when you are cuffed." + if(amount_grown >= max_grown) //TODO ~Carn - src << "\green You are growing into a beautiful alien! It is time to choose a caste." - src << "\green There are three to choose from:" - src << "\green Hunters are strong and agile, able to hunt away from the hive and rapidly move through ventilation shafts. Hunters generate plasma slowly and have low reserves." - src << "\green Sentinels are tasked with protecting the hive and are deadly up close and at a range. They are not as physically imposing nor fast as the hunters." - src << "\green Drones are the working class, offering the largest plasma storage and generation. They are the only caste which may evolve again, turning into the dreaded alien queen." + //green is impossible to read, so i made these blue and changed the formatting slightly + src << "\blue You are growing into a beautiful alien! It is time to choose a caste." + src << "\blue There are three to choose from:" + src << "Hunters \blue are strong and agile, able to hunt away from the hive and rapidly move through ventilation shafts. Hunters generate plasma slowly and have low reserves." + src << "Sentinels \blue are tasked with protecting the hive and are deadly up close and at a range. They are not as physically imposing nor fast as the hunters." + src << "Drones \blue are the working class, offering the largest plasma storage and generation. They are the only caste which may evolve again, turning into the dreaded alien queen." var/alien_caste = alert(src, "Please choose which alien caste you shall belong to.",,"Hunter","Sentinel","Drone") var/mob/living/carbon/alien/humanoid/new_xeno diff --git a/code/modules/mob/living/carbon/alien/larva/update_icons.dm b/code/modules/mob/living/carbon/alien/larva/update_icons.dm index 00befb6379b..3ab3fb3b382 100644 --- a/code/modules/mob/living/carbon/alien/larva/update_icons.dm +++ b/code/modules/mob/living/carbon/alien/larva/update_icons.dm @@ -1 +1,22 @@ -//No special icons processing + +/mob/living/carbon/alien/larva/regenerate_icons() + overlays = list() + update_icons() + +/mob/living/carbon/alien/larva/update_icons() + var/state = 0 + if(amount_grown > 150) + state = 2 + else if(amount_grown > 50) + state = 1 + + if(stat == DEAD) + icon_state = "larva[state]_dead" + else if (handcuffed || legcuffed) + icon_state = "larva[state]_cuff" + else if (stunned) + icon_state = "larva[state]_stun" + else if(lying || resting) + icon_state = "larva[state]_sleep" + else + icon_state = "larva[state]" diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm new file mode 100644 index 00000000000..9cf49ce607b --- /dev/null +++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm @@ -0,0 +1,154 @@ +// This is to replace the previous datum/disease/alien_embryo for slightly improved handling and maintainability +// It functions almost identically (see code/datums/diseases/alien_embryo.dm) + +/obj/item/alien_embryo + name = "alien embryo" + desc = "All slimy and yuck." + icon = 'icons/mob/alien.dmi' + icon_state = "larva0_dead" + var/mob/living/affected_mob + var/stage = 0 + +/obj/item/alien_embryo/New() + if(istype(loc, /mob/living)) + affected_mob = loc + processing_objects.Add(src) + spawn(0) + AddInfectionImages(affected_mob) + else + del(src) + +/obj/item/alien_embryo/Del() + if(affected_mob) + affected_mob.status_flags &= ~(XENO_HOST) + spawn(0) + RemoveInfectionImages(affected_mob) + ..() + +/obj/item/alien_embryo/process() + if(loc != affected_mob) + affected_mob.status_flags &= ~(XENO_HOST) + processing_objects.Remove(src) + affected_mob = null + spawn(0) + RemoveInfectionImages(affected_mob) + return + + if(stage < 5 && prob(3)) + stage++ + spawn(0) + RefreshInfectionImage(affected_mob) + + switch(stage) + if(2, 3) + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + affected_mob << "\red Your throat feels sore." + if(prob(1)) + affected_mob << "\red Mucous runs down the back of your throat." + if(4) + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(2)) + affected_mob << "\red Your muscles ache." + if(prob(20)) + affected_mob.take_organ_damage(1) + if(prob(2)) + affected_mob << "\red Your stomach hurts." + if(prob(20)) + affected_mob.adjustToxLoss(1) + affected_mob.updatehealth() + if(5) + affected_mob << "\red You feel something tearing its way out of your stomach..." + affected_mob.adjustToxLoss(10) + affected_mob.updatehealth() + if(prob(50)) + AttemptGrow() + +/obj/item/alien_embryo/proc/AttemptGrow(var/gib_on_success = 1) + var/list/candidates = get_alien_candidates() + var/picked = null + + // To stop clientless larva, we will check that our host has a client + // if we find no ghosts to become the alien. If the host has a client + // he will become the alien but if he doesn't then we will set the stage + // to 2, so we don't do a process heavy check everytime. + + if(candidates.len) + picked = pick(candidates) + else if(affected_mob.client) + picked = affected_mob.key + else + stage = 4 // Let's try again later. + return + + if(affected_mob.lying) + affected_mob.overlays += image('icons/mob/alien.dmi', loc = affected_mob, icon_state = "burst_lie") + else + affected_mob.overlays += image('icons/mob/alien.dmi', loc = affected_mob, icon_state = "burst_stand") + spawn(6) + var/mob/living/carbon/alien/larva/new_xeno = new(affected_mob.loc) + new_xeno.key = picked + new_xeno << sound('sound/voice/hiss5.ogg',0,0,0,100) //To get the player's attention + if(gib_on_success) + affected_mob.gib() + del(src) + +/*---------------------------------------- +Proc: RefreshInfectionImage() +Des: Removes all infection images from aliens and places an infection image on all infected mobs for aliens. +----------------------------------------*/ +/obj/item/alien_embryo/proc/RefreshInfectionImage() + spawn(0) + for (var/mob/living/carbon/alien/alien in player_list) + if (alien.client) + for(var/image/I in alien.client.images) + if(dd_hasprefix_case(I.icon_state, "infected")) + del(I) + + for (var/mob/living/carbon/alien/alien in player_list) + if (alien.client) + for (var/mob/living/carbon/C in mob_list) + if(C) + if (C.status_flags & XENO_HOST) + var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[stage]") + alien.client.images += I + for (var/mob/living/simple_animal/corgi/C in mob_list) + if(C) + if (C.status_flags & XENO_HOST) + var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[stage]") + alien.client.images += I + return + +/*---------------------------------------- +Proc: AddInfectionImages(C) +Des: Checks if the passed mob (C) is infected with the alien egg, then gives each alien client an infected image at C. +----------------------------------------*/ +/obj/item/alien_embryo/proc/AddInfectionImages(var/mob/living/C) + if (C) + for (var/mob/living/carbon/alien/alien in player_list) + if (alien.client) + if (C.status_flags & XENO_HOST) + var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[stage]") + alien.client.images += I + return + +/*---------------------------------------- +Proc: RemoveInfectionImage(C) +Des: Removes the alien infection image from all aliens in the world located in passed mob (C). +----------------------------------------*/ + +/obj/item/alien_embryo/proc/RemoveInfectionImages(var/mob/living/C) + if (C) + for (var/mob/living/carbon/alien/alien in player_list) + if (alien.client) + for(var/image/I in alien.client.images) + if(I.loc == C) + if(dd_hasprefix_case(I.icon_state, "infected")) + del(I) + return diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm index ca87bea126a..f1561344386 100644 --- a/code/modules/mob/living/carbon/alien/special/facehugger.dm +++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm @@ -94,12 +94,22 @@ var/const/MAX_ACTIVE_TIME = 400 if(CanHug(AM)) Attach(AM) +/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed) + ..() + if(stat == CONSCIOUS) + icon_state = "[initial(icon_state)]_thrown" + spawn(15) + if(icon_state == "[initial(icon_state)]_thrown") + icon_state = "[initial(icon_state)]" + /obj/item/clothing/mask/facehugger/throw_impact(atom/hit_atom) - Attach(hit_atom) - return + ..() + if(stat == CONSCIOUS) + icon_state = "[initial(icon_state)]" + Attach(hit_atom) /obj/item/clothing/mask/facehugger/proc/Attach(M as mob) - if(!iscarbon(M) || isalien(M)) + if( (!iscorgi(M) && !iscarbon(M)) || isalien(M)) return if(attached) return @@ -114,49 +124,61 @@ var/const/MAX_ACTIVE_TIME = 400 if(stat != CONSCIOUS) return if(!sterile) L.take_organ_damage(strength,0) //done here so that even borgs and humans in helmets take damage - var/mob/living/carbon/target = L + L.visible_message("\red \b [src] leaps at [L]'s face!") - target.visible_message("\red \b [src] leaps at [target]'s face!") - - if(ishuman(target)) - var/mob/living/carbon/human/H = target + if(ishuman(L)) + var/mob/living/carbon/human/H = L if(H.head && H.head.flags & HEADCOVERSMOUTH) H.visible_message("\red \b [src] smashes against [H]'s [H.head]!") Die() return - if(target.wear_mask) - if(prob(20)) return - var/obj/item/clothing/W = target.wear_mask - if(!W.canremove) return - target.drop_from_inventory(W) + if(iscarbon(M)) + var/mob/living/carbon/target = L - target.visible_message("\red \b [src] tears [W] off of [target]'s face!") + if(target.wear_mask) + if(prob(20)) return + var/obj/item/clothing/W = target.wear_mask + if(!W.canremove) return + target.drop_from_inventory(W) - target.equip_to_slot(src, slot_wear_mask) + target.visible_message("\red \b [src] tears [W] off of [target]'s face!") + + target.equip_to_slot(src, slot_wear_mask) + + if(!sterile) L.Paralyse(MAX_IMPREGNATION_TIME/6) //something like 25 ticks = 20 seconds with the default settings + else if (iscorgi(M)) + var/mob/living/simple_animal/corgi/C = M + src.loc = C + C.facehugger = src + C.wear_mask = src + //C.regenerate_icons() GoIdle() //so it doesn't jump the people that tear it off - if(!sterile) target.Paralyse(MAX_IMPREGNATION_TIME/6) //something like 25 ticks = 20 seconds with the default settings - spawn(rand(MIN_IMPREGNATION_TIME,MAX_IMPREGNATION_TIME)) - Impregnate(target) + Impregnate(L) return -/obj/item/clothing/mask/facehugger/proc/Impregnate(mob/living/carbon/target as mob) +/obj/item/clothing/mask/facehugger/proc/Impregnate(mob/living/target as mob) if(!target || target.wear_mask != src || target.stat == DEAD) //was taken off or something return if(!sterile) - target.contract_disease(new /datum/disease/alien_embryo(0)) //so infection chance is same as virus infection chance - for(var/datum/disease/alien_embryo/A in target.viruses) - target.status_flags |= XENO_HOST - break + //target.contract_disease(new /datum/disease/alien_embryo(0)) //so infection chance is same as virus infection chance + new /obj/item/alien_embryo(target) + target.status_flags |= XENO_HOST target.visible_message("\red \b [src] falls limp after violating [target]'s face!") Die() + icon_state = "[initial(icon_state)]_impregnated" + + if(iscorgi(target)) + var/mob/living/simple_animal/corgi/C = target + src.loc = get_turf(C) + C.facehugger = null else target.visible_message("\red \b [src] violates [target]'s face!") return @@ -204,6 +226,9 @@ var/const/MAX_ACTIVE_TIME = 400 /proc/CanHug(var/mob/M) + if(iscorgi(M)) + return 1 + if(!iscarbon(M) || isalien(M)) return 0 var/mob/living/carbon/C = M @@ -211,4 +236,4 @@ var/const/MAX_ACTIVE_TIME = 400 var/mob/living/carbon/human/H = C if(H.head && H.head.flags & HEADCOVERSMOUTH) return 0 - return 1 \ No newline at end of file + return 1 diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 986178ef229..1a1907fd8ee 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -5,6 +5,7 @@ var/brain_op_stage = 0.0 var/eye_op_stage = 0.0 var/appendix_op_stage = 0.0 + var/alien_op_stage = 0.0 var/antibodies = 0 diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm index f0ca40054a2..365b93bb817 100644 --- a/code/modules/mob/living/simple_animal/friendly/corgi.dm +++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm @@ -20,6 +20,7 @@ see_in_dark = 5 var/obj/item/inventory_head var/obj/item/inventory_back + var/facehugger /mob/living/simple_animal/corgi/Life() ..() @@ -375,7 +376,7 @@ if(health <= 0) head_icon_state += "2" - var/icon/head_icon = icon('icons/mob/corgi_head.dmi',head_icon_state) + var/icon/head_icon = image('icons/mob/corgi_head.dmi',head_icon_state) if(head_icon) overlays += head_icon @@ -384,9 +385,16 @@ if(health <= 0) back_icon_state += "2" - var/icon/back_icon = icon('icons/mob/corgi_back.dmi',back_icon_state) + var/icon/back_icon = image('icons/mob/corgi_back.dmi',back_icon_state) if(back_icon) overlays += back_icon + + if(facehugger) + if(istype(src, /mob/living/simple_animal/corgi/puppy)) + overlays += image('icons/mob/mask.dmi',"facehugger_corgipuppy") + else + overlays += image('icons/mob/mask.dmi',"facehugger_corgi") + return diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index 07ecdcb710b..f6d50227446 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -46,6 +46,12 @@ damage = 20 +/obj/item/projectile/energy/neurotoxin + name = "neuro" + icon_state = "neurotoxin" + damage = 5 + damage_type = TOX + weaken = 5 diff --git a/html/changelog.html b/html/changelog.html index 6e41d81a284..80328658fc8 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -49,10 +49,20 @@ should be listed in the changelog upon commit tho. Thanks. -->