diff --git a/baystation12.dme b/baystation12.dme index f620ad475e..2b31f2fb17 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -40,7 +40,6 @@ #include "code\_onclick\other_mobs.dm" #include "code\_onclick\telekinesis.dm" #include "code\_onclick\hud\_defines.dm" -#include "code\_onclick\hud\alien.dm" #include "code\_onclick\hud\alien_larva.dm" #include "code\_onclick\hud\hud.dm" #include "code\_onclick\hud\human.dm" @@ -292,6 +291,7 @@ #include "code\game\machinery\Beacon.dm" #include "code\game\machinery\bees_apiary.dm" #include "code\game\machinery\bees_items.dm" +#include "code\game\machinery\bioprinter.dm" #include "code\game\machinery\buttons.dm" #include "code\game\machinery\cell_charger.dm" #include "code\game\machinery\cloning.dm" @@ -897,7 +897,6 @@ #include "code\modules\mining\drilling\distribution.dm" #include "code\modules\mining\drilling\drill.dm" #include "code\modules\mining\drilling\scanner.dm" -#include "code\modules\mob\abilities.dm" #include "code\modules\mob\death.dm" #include "code\modules\mob\emote.dm" #include "code\modules\mob\hear_say.dm" @@ -925,42 +924,35 @@ #include "code\modules\mob\living\living.dm" #include "code\modules\mob\living\living_defense.dm" #include "code\modules\mob\living\living_defines.dm" +#include "code\modules\mob\living\living_powers.dm" #include "code\modules\mob\living\login.dm" #include "code\modules\mob\living\logout.dm" #include "code\modules\mob\living\say.dm" #include "code\modules\mob\living\blob\blob.dm" #include "code\modules\mob\living\carbon\carbon.dm" #include "code\modules\mob\living\carbon\carbon_defines.dm" +#include "code\modules\mob\living\carbon\carbon_powers.dm" #include "code\modules\mob\living\carbon\give.dm" #include "code\modules\mob\living\carbon\shock.dm" -#include "code\modules\mob\living\carbon\species.dm" #include "code\modules\mob\living\carbon\alien\alien.dm" +#include "code\modules\mob\living\carbon\alien\alien_attacks.dm" +#include "code\modules\mob\living\carbon\alien\alien_damage.dm" #include "code\modules\mob\living\carbon\alien\death.dm" -#include "code\modules\mob\living\carbon\alien\login.dm" -#include "code\modules\mob\living\carbon\alien\logout.dm" -#include "code\modules\mob\living\carbon\alien\powers.dm" +#include "code\modules\mob\living\carbon\alien\emote.dm" +#include "code\modules\mob\living\carbon\alien\life.dm" +#include "code\modules\mob\living\carbon\alien\progression.dm" #include "code\modules\mob\living\carbon\alien\say.dm" -#include "code\modules\mob\living\carbon\alien\humanoid\alien_powers.dm" -#include "code\modules\mob\living\carbon\alien\humanoid\death.dm" -#include "code\modules\mob\living\carbon\alien\humanoid\emote.dm" -#include "code\modules\mob\living\carbon\alien\humanoid\humanoid.dm" -#include "code\modules\mob\living\carbon\alien\humanoid\inventory.dm" -#include "code\modules\mob\living\carbon\alien\humanoid\life.dm" -#include "code\modules\mob\living\carbon\alien\humanoid\login.dm" -#include "code\modules\mob\living\carbon\alien\humanoid\queen.dm" -#include "code\modules\mob\living\carbon\alien\humanoid\update_icons.dm" -#include "code\modules\mob\living\carbon\alien\humanoid\caste\drone.dm" -#include "code\modules\mob\living\carbon\alien\humanoid\caste\hunter.dm" -#include "code\modules\mob\living\carbon\alien\humanoid\caste\sentinel.dm" -#include "code\modules\mob\living\carbon\alien\larva\death.dm" -#include "code\modules\mob\living\carbon\alien\larva\emote.dm" -#include "code\modules\mob\living\carbon\alien\larva\inventory.dm" +#include "code\modules\mob\living\carbon\alien\update_icons.dm" +#include "code\modules\mob\living\carbon\alien\diona\diona.dm" +#include "code\modules\mob\living\carbon\alien\diona\diona_attacks.dm" +#include "code\modules\mob\living\carbon\alien\diona\diona_powers.dm" +#include "code\modules\mob\living\carbon\alien\diona\life.dm" +#include "code\modules\mob\living\carbon\alien\diona\progression.dm" +#include "code\modules\mob\living\carbon\alien\diona\say_understands.dm" +#include "code\modules\mob\living\carbon\alien\diona\update_icons.dm" #include "code\modules\mob\living\carbon\alien\larva\larva.dm" #include "code\modules\mob\living\carbon\alien\larva\life.dm" -#include "code\modules\mob\living\carbon\alien\larva\powers.dm" -#include "code\modules\mob\living\carbon\alien\larva\update_icons.dm" -#include "code\modules\mob\living\carbon\alien\special\alien_embryo.dm" -#include "code\modules\mob\living\carbon\alien\special\facehugger.dm" +#include "code\modules\mob\living\carbon\alien\larva\progression.dm" #include "code\modules\mob\living\carbon\brain\brain.dm" #include "code\modules\mob\living\carbon\brain\brain_item.dm" #include "code\modules\mob\living\carbon\brain\death.dm" @@ -974,19 +966,27 @@ #include "code\modules\mob\living\carbon\human\emote.dm" #include "code\modules\mob\living\carbon\human\examine.dm" #include "code\modules\mob\living\carbon\human\human.dm" -#include "code\modules\mob\living\carbon\human\human_attackalien.dm" #include "code\modules\mob\living\carbon\human\human_attackhand.dm" #include "code\modules\mob\living\carbon\human\human_attackpaw.dm" #include "code\modules\mob\living\carbon\human\human_damage.dm" #include "code\modules\mob\living\carbon\human\human_defense.dm" #include "code\modules\mob\living\carbon\human\human_defines.dm" #include "code\modules\mob\living\carbon\human\human_movement.dm" +#include "code\modules\mob\living\carbon\human\human_powers.dm" +#include "code\modules\mob\living\carbon\human\human_species.dm" #include "code\modules\mob\living\carbon\human\inventory.dm" #include "code\modules\mob\living\carbon\human\life.dm" #include "code\modules\mob\living\carbon\human\login.dm" +#include "code\modules\mob\living\carbon\human\logout.dm" #include "code\modules\mob\living\carbon\human\say.dm" +#include "code\modules\mob\living\carbon\human\species.dm" #include "code\modules\mob\living\carbon\human\update_icons.dm" #include "code\modules\mob\living\carbon\human\whisper.dm" +#include "code\modules\mob\living\carbon\human\alien\alien.dm" +#include "code\modules\mob\living\carbon\human\alien\alien_embryo.dm" +#include "code\modules\mob\living\carbon\human\alien\alien_facehugger.dm" +#include "code\modules\mob\living\carbon\human\alien\alien_powers.dm" +#include "code\modules\mob\living\carbon\human\alien\alien_species.dm" #include "code\modules\mob\living\carbon\metroid\death.dm" #include "code\modules\mob\living\carbon\metroid\emote.dm" #include "code\modules\mob\living\carbon\metroid\examine.dm" @@ -999,14 +999,12 @@ #include "code\modules\mob\living\carbon\metroid\subtypes.dm" #include "code\modules\mob\living\carbon\metroid\update_icons.dm" #include "code\modules\mob\living\carbon\monkey\death.dm" -#include "code\modules\mob\living\carbon\monkey\diona.dm" #include "code\modules\mob\living\carbon\monkey\emote.dm" #include "code\modules\mob\living\carbon\monkey\examine.dm" #include "code\modules\mob\living\carbon\monkey\inventory.dm" #include "code\modules\mob\living\carbon\monkey\life.dm" #include "code\modules\mob\living\carbon\monkey\login.dm" #include "code\modules\mob\living\carbon\monkey\monkey.dm" -#include "code\modules\mob\living\carbon\monkey\powers.dm" #include "code\modules\mob\living\carbon\monkey\update_icons.dm" #include "code\modules\mob\living\silicon\alarm.dm" #include "code\modules\mob\living\silicon\death.dm" @@ -1052,6 +1050,7 @@ #include "code\modules\mob\living\silicon\robot\robot_items.dm" #include "code\modules\mob\living\silicon\robot\robot_modules.dm" #include "code\modules\mob\living\silicon\robot\robot_movement.dm" +#include "code\modules\mob\living\silicon\robot\robot_powers.dm" #include "code\modules\mob\living\silicon\robot\wires.dm" #include "code\modules\mob\living\silicon\robot\drone\drone.dm" #include "code\modules\mob\living\silicon\robot\drone\drone_abilities.dm" @@ -1060,13 +1059,16 @@ #include "code\modules\mob\living\silicon\robot\drone\drone_items.dm" #include "code\modules\mob\living\silicon\robot\drone\drone_manufacturer.dm" #include "code\modules\mob\living\simple_animal\bees.dm" -#include "code\modules\mob\living\simple_animal\borer.dm" #include "code\modules\mob\living\simple_animal\constructs.dm" #include "code\modules\mob\living\simple_animal\corpse.dm" #include "code\modules\mob\living\simple_animal\parrot.dm" #include "code\modules\mob\living\simple_animal\shade.dm" #include "code\modules\mob\living\simple_animal\simple_animal.dm" #include "code\modules\mob\living\simple_animal\worm.dm" +#include "code\modules\mob\living\simple_animal\borer\borer.dm" +#include "code\modules\mob\living\simple_animal\borer\borer_captive.dm" +#include "code\modules\mob\living\simple_animal\borer\borer_powers.dm" +#include "code\modules\mob\living\simple_animal\borer\say.dm" #include "code\modules\mob\living\simple_animal\friendly\cat.dm" #include "code\modules\mob\living\simple_animal\friendly\corgi.dm" #include "code\modules\mob\living\simple_animal\friendly\crab.dm" @@ -1109,8 +1111,10 @@ #include "code\modules\nano\nanoui.dm" #include "code\modules\organs\blood.dm" #include "code\modules\organs\organ.dm" +#include "code\modules\organs\organ_alien.dm" #include "code\modules\organs\organ_external.dm" #include "code\modules\organs\organ_internal.dm" +#include "code\modules\organs\organ_objects.dm" #include "code\modules\organs\pain.dm" #include "code\modules\organs\wound.dm" #include "code\modules\paperwork\carbonpaper.dm" @@ -1345,17 +1349,18 @@ #include "code\modules\shuttles\shuttle_supply.dm" #include "code\modules\shuttles\shuttles_multi.dm" #include "code\modules\supermatter\supermatter.dm" -#include "code\modules\surgery\appendix.dm" #include "code\modules\surgery\bones.dm" -#include "code\modules\surgery\braincore.dm" +#include "code\modules\surgery\brainrepair.dm" +#include "code\modules\surgery\encased.dm" #include "code\modules\surgery\eye.dm" #include "code\modules\surgery\face.dm" #include "code\modules\surgery\generic.dm" #include "code\modules\surgery\headreattach.dm" #include "code\modules\surgery\implant.dm" +#include "code\modules\surgery\organs_internal.dm" #include "code\modules\surgery\other.dm" -#include "code\modules\surgery\ribcage.dm" #include "code\modules\surgery\robolimbs.dm" +#include "code\modules\surgery\slimes.dm" #include "code\modules\surgery\surgery.dm" #include "code\modules\vehicles\cargo_train.dm" #include "code\modules\vehicles\train.dm" diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm index 80b168aabd..925994546e 100644 --- a/code/ATMOSPHERICS/components/unary/vent_pump.dm +++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm @@ -425,14 +425,16 @@ return /* - Alt-click to ventcrawl - Monkeys, aliens, slimes and mice. + Alt-click to vent crawl - Monkeys, aliens, slimes and mice. This is a little buggy but somehow that just seems to plague ventcrawl. I am sorry, I don't know why. */ -/obj/machinery/atmospherics/unary/vent_pump/AltClick(var/mob/living/ML) +// Commenting this out for now, it's not critical, stated to be buggy, and seems like +// a really clumsy way of doing this. ~Z +/*/obj/machinery/atmospherics/unary/vent_pump/AltClick(var/mob/living/ML) if(istype(ML)) var/list/ventcrawl_verbs = list(/mob/living/carbon/monkey/verb/ventcrawl, /mob/living/carbon/alien/verb/ventcrawl, /mob/living/carbon/slime/verb/ventcrawl,/mob/living/simple_animal/mouse/verb/ventcrawl) if(length(ML.verbs & ventcrawl_verbs)) // alien queens have this removed, an istype would be complicated ML.handle_ventcrawl(src) return - ..() + ..()*/ \ No newline at end of file diff --git a/code/ZAS/Phoron.dm b/code/ZAS/Phoron.dm index 98ab127825..6cd983732b 100644 --- a/code/ZAS/Phoron.dm +++ b/code/ZAS/Phoron.dm @@ -117,13 +117,17 @@ obj/var/contaminated = 0 /mob/living/carbon/human/proc/burn_eyes() //The proc that handles eye burning. - if(prob(20)) src << "\red Your eyes burn!" + if(!species.has_organ["eyes"]) + return + var/datum/organ/internal/eyes/E = internal_organs_by_name["eyes"] - E.damage += 2.5 - eye_blurry = min(eye_blurry+1.5,50) - if (prob(max(0,E.damage - 15) + 1) &&!eye_blind) - src << "\red You are blinded!" - eye_blind += 20 + if(E) + if(prob(20)) src << "\red Your eyes burn!" + E.damage += 2.5 + eye_blurry = min(eye_blurry+1.5,50) + if (prob(max(0,E.damage - 15) + 1) &&!eye_blind) + src << "\red You are blinded!" + eye_blind += 20 /mob/living/carbon/human/proc/pl_head_protected() //Checks if the head is adequately sealed. diff --git a/code/_onclick/hud/alien.dm b/code/_onclick/hud/alien.dm deleted file mode 100644 index 01b1058527..0000000000 --- a/code/_onclick/hud/alien.dm +++ /dev/null @@ -1,241 +0,0 @@ -/datum/hud/proc/alien_hud() - - src.adding = list( ) - src.other = list( ) - - var/obj/screen/using - var/obj/screen/inventory/inv_box - - using = new /obj/screen() - using.name = "act_intent" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_alien.dmi' - using.icon_state = (mymob.a_intent == "hurt" ? "harm" : mymob.a_intent) - using.screen_loc = ui_acti - using.layer = 20 - src.adding += using - action_intent = using - -//intent small hud objects - var/icon/ico - - ico = new('icons/mob/screen1_alien.dmi', "black") - ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) - ico.DrawBox(rgb(255,255,255,1),1,ico.Height()/2,ico.Width()/2,ico.Height()) - using = new /obj/screen( src ) - using.name = "help" - using.icon = ico - using.screen_loc = ui_acti - using.layer = 21 - src.adding += using - help_intent = using - - ico = new('icons/mob/screen1_alien.dmi', "black") - ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) - ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,ico.Height()/2,ico.Width(),ico.Height()) - using = new /obj/screen( src ) - using.name = "disarm" - using.icon = ico - using.screen_loc = ui_acti - using.layer = 21 - src.adding += using - disarm_intent = using - - ico = new('icons/mob/screen1_alien.dmi', "black") - ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) - ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,1,ico.Width(),ico.Height()/2) - using = new /obj/screen( src ) - using.name = "grab" - using.icon = ico - using.screen_loc = ui_acti - using.layer = 21 - src.adding += using - grab_intent = using - - ico = new('icons/mob/screen1_alien.dmi', "black") - ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) - ico.DrawBox(rgb(255,255,255,1),1,1,ico.Width()/2,ico.Height()/2) - using = new /obj/screen( src ) - using.name = "harm" - using.icon = ico - using.screen_loc = ui_acti - using.layer = 21 - src.adding += using - hurt_intent = using - -//end intent small hud objects - - using = new /obj/screen() - using.name = "mov_intent" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_alien.dmi' - using.icon_state = (mymob.m_intent == "run" ? "running" : "walking") - using.screen_loc = ui_movi - using.layer = 20 - src.adding += using - move_intent = using - - using = new /obj/screen() - using.name = "drop" - using.icon = 'icons/mob/screen1_alien.dmi' - using.icon_state = "act_drop" - using.screen_loc = ui_drop_throw - using.layer = 19 - src.adding += using - -//equippable shit - //suit - inv_box = new /obj/screen/inventory() - inv_box.name = "o_clothing" - inv_box.dir = SOUTH - inv_box.icon = 'icons/mob/screen1_alien.dmi' - inv_box.icon_state = "equip" - inv_box.screen_loc = ui_alien_oclothing - inv_box.slot_id = slot_wear_suit - inv_box.layer = 19 - src.adding += inv_box - - inv_box = new /obj/screen/inventory() - inv_box.name = "r_hand" - inv_box.dir = WEST - inv_box.icon = 'icons/mob/screen1_alien.dmi' - inv_box.icon_state = "hand_inactive" - if(mymob && !mymob.hand) //This being 0 or null means the right hand is in use - using.icon_state = "hand_active" - inv_box.screen_loc = ui_rhand - inv_box.layer = 19 - src.r_hand_hud_object = inv_box - inv_box.slot_id = slot_r_hand - src.adding += inv_box - - inv_box = new /obj/screen/inventory() - inv_box.name = "l_hand" - inv_box.dir = EAST - inv_box.icon = 'icons/mob/screen1_alien.dmi' - inv_box.icon_state = "hand_inactive" - if(mymob && mymob.hand) //This being 1 means the left hand is in use - inv_box.icon_state = "hand_active" - inv_box.screen_loc = ui_lhand - inv_box.layer = 19 - inv_box.slot_id = slot_l_hand - src.l_hand_hud_object = inv_box - src.adding += inv_box - - using = new /obj/screen/inventory() - using.name = "hand" - using.dir = SOUTH - using.icon = 'icons/mob/screen1_alien.dmi' - using.icon_state = "hand1" - using.screen_loc = ui_swaphand1 - using.layer = 19 - src.adding += using - - using = new /obj/screen/inventory() - using.name = "hand" - using.dir = SOUTH - using.icon = 'icons/mob/screen1_alien.dmi' - using.icon_state = "hand2" - using.screen_loc = ui_swaphand2 - using.layer = 19 - src.adding += using - - //pocket 1 - inv_box = new /obj/screen/inventory() - inv_box.name = "storage1" - inv_box.icon = 'icons/mob/screen1_alien.dmi' - inv_box.icon_state = "pocket" - inv_box.screen_loc = ui_storage1 - inv_box.slot_id = slot_l_store - inv_box.layer = 19 - src.adding += inv_box - - //pocket 2 - inv_box = new /obj/screen/inventory() - inv_box.name = "storage2" - inv_box.icon = 'icons/mob/screen1_alien.dmi' - inv_box.icon_state = "pocket" - inv_box.screen_loc = ui_storage2 - inv_box.slot_id = slot_r_store - inv_box.layer = 19 - src.adding += inv_box - - //head - inv_box = new /obj/screen/inventory() - inv_box.name = "head" - inv_box.icon = 'icons/mob/screen1_alien.dmi' - inv_box.icon_state = "hair" - inv_box.screen_loc = ui_alien_head - inv_box.slot_id = slot_head - inv_box.layer = 19 - src.adding += inv_box -//end of equippable shit - -/* - using = new /obj/screen() - using.name = "resist" - using.icon = 'icons/mob/screen1_alien.dmi' - using.icon_state = "act_resist" - using.screen_loc = ui_resist - using.layer = 19 - src.adding += using -*/ - - mymob.throw_icon = new /obj/screen() - mymob.throw_icon.icon = 'icons/mob/screen1_alien.dmi' - mymob.throw_icon.icon_state = "act_throw_off" - mymob.throw_icon.name = "throw" - mymob.throw_icon.screen_loc = ui_drop_throw - - mymob.oxygen = new /obj/screen() - mymob.oxygen.icon = 'icons/mob/screen1_alien.dmi' - mymob.oxygen.icon_state = "oxy0" - mymob.oxygen.name = "oxygen" - mymob.oxygen.screen_loc = ui_alien_oxygen - - mymob.toxin = new /obj/screen() - mymob.toxin.icon = 'icons/mob/screen1_alien.dmi' - mymob.toxin.icon_state = "tox0" - mymob.toxin.name = "toxin" - mymob.toxin.screen_loc = ui_alien_toxin - - mymob.fire = new /obj/screen() - mymob.fire.icon = 'icons/mob/screen1_alien.dmi' - mymob.fire.icon_state = "fire0" - mymob.fire.name = "fire" - mymob.fire.screen_loc = ui_alien_fire - - mymob.healths = new /obj/screen() - mymob.healths.icon = 'icons/mob/screen1_alien.dmi' - mymob.healths.icon_state = "health0" - mymob.healths.name = "health" - mymob.healths.screen_loc = ui_alien_health - - mymob.pullin = new /obj/screen() - mymob.pullin.icon = 'icons/mob/screen1_alien.dmi' - mymob.pullin.icon_state = "pull0" - mymob.pullin.name = "pull" - mymob.pullin.screen_loc = ui_pull_resist - - mymob.blind = new /obj/screen() - mymob.blind.icon = 'icons/mob/screen1_full.dmi' - mymob.blind.icon_state = "blackimageoverlay" - mymob.blind.name = " " - mymob.blind.screen_loc = "1,1" - mymob.blind.layer = 0 - - mymob.flash = new /obj/screen() - mymob.flash.icon = 'icons/mob/screen1_alien.dmi' - mymob.flash.icon_state = "blank" - mymob.flash.name = "flash" - mymob.flash.screen_loc = "1,1 to 15,15" - mymob.flash.layer = 17 - - mymob.zone_sel = new /obj/screen/zone_sel() - mymob.zone_sel.icon = 'icons/mob/screen1_alien.dmi' - mymob.zone_sel.overlays.Cut() - mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]") - - mymob.client.screen = null - - mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.toxin, mymob.fire, mymob.healths, mymob.pullin, mymob.blind, mymob.flash) //, mymob.hands, mymob.rest, mymob.sleep, mymob.mach ) - mymob.client.screen += src.adding + src.other \ No newline at end of file diff --git a/code/_onclick/hud/alien_larva.dm b/code/_onclick/hud/alien_larva.dm index 4e29827e89..5037353ff1 100644 --- a/code/_onclick/hud/alien_larva.dm +++ b/code/_onclick/hud/alien_larva.dm @@ -5,58 +5,22 @@ var/obj/screen/using - using = new /obj/screen() - using.name = "act_intent" - using.dir = SOUTHWEST - using.icon = 'icons/mob/screen1_alien.dmi' - using.icon_state = (mymob.a_intent == "hurt" ? "harm" : mymob.a_intent) - using.screen_loc = ui_acti - using.layer = 20 - src.adding += using - action_intent = using - using = new /obj/screen() using.name = "mov_intent" using.dir = SOUTHWEST using.icon = 'icons/mob/screen1_alien.dmi' using.icon_state = (mymob.m_intent == "run" ? "running" : "walking") - using.screen_loc = ui_movi + using.screen_loc = ui_acti using.layer = 20 src.adding += using move_intent = using - mymob.oxygen = new /obj/screen() - mymob.oxygen.icon = 'icons/mob/screen1_alien.dmi' - mymob.oxygen.icon_state = "oxy0" - mymob.oxygen.name = "oxygen" - mymob.oxygen.screen_loc = ui_alien_oxygen - - mymob.toxin = new /obj/screen() - mymob.toxin.icon = 'icons/mob/screen1_alien.dmi' - mymob.toxin.icon_state = "tox0" - mymob.toxin.name = "toxin" - mymob.toxin.screen_loc = ui_alien_toxin - - - mymob.fire = new /obj/screen() - mymob.fire.icon = 'icons/mob/screen1_alien.dmi' - mymob.fire.icon_state = "fire0" - mymob.fire.name = "fire" - mymob.fire.screen_loc = ui_alien_fire - - mymob.healths = new /obj/screen() mymob.healths.icon = 'icons/mob/screen1_alien.dmi' mymob.healths.icon_state = "health0" mymob.healths.name = "health" mymob.healths.screen_loc = ui_alien_health - mymob.pullin = new /obj/screen() - mymob.pullin.icon = 'icons/mob/screen1_alien.dmi' - mymob.pullin.icon_state = "pull0" - mymob.pullin.name = "pull" - mymob.pullin.screen_loc = ui_pull_resist - mymob.blind = new /obj/screen() mymob.blind.icon = 'icons/mob/screen1_full.dmi' mymob.blind.icon_state = "blackimageoverlay" @@ -71,11 +35,12 @@ mymob.flash.screen_loc = "1,1 to 15,15" mymob.flash.layer = 17 - mymob.zone_sel = new /obj/screen/zone_sel() - mymob.zone_sel.overlays.Cut() - mymob.zone_sel.overlays += image("icon" = 'icons/mob/zone_sel.dmi', "icon_state" = text("[]", mymob.zone_sel.selecting)) + mymob.fire = new /obj/screen() + mymob.fire.icon = 'icons/mob/screen1_alien.dmi' + mymob.fire.icon_state = "fire0" + mymob.fire.name = "fire" + mymob.fire.screen_loc = ui_fire mymob.client.screen = null - - mymob.client.screen += list( mymob.zone_sel, mymob.oxygen, mymob.toxin, mymob.fire, mymob.healths, mymob.pullin, mymob.blind, mymob.flash) //, mymob.rest, mymob.sleep, mymob.mach ) - mymob.client.screen += src.adding + src.other + mymob.client.screen += list( mymob.healths, mymob.blind, mymob.flash, mymob.fire) //, mymob.rest, mymob.sleep, mymob.mach ) + mymob.client.screen += src.adding + src.other \ No newline at end of file diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 221eef2a1d..9ea0cb2bff 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -194,15 +194,13 @@ datum/hud/New(mob/owner) var/ui_alpha = mymob.client.prefs.UI_style_alpha if(ishuman(mymob)) - human_hud(ui_style, ui_color, ui_alpha) // Pass the player the UI style chosen in preferences + human_hud(ui_style, ui_color, ui_alpha, mymob) // Pass the player the UI style chosen in preferences else if(ismonkey(mymob)) monkey_hud(ui_style) else if(isbrain(mymob)) brain_hud(ui_style) - else if(islarva(mymob)) - larva_hud() else if(isalien(mymob)) - alien_hud() + larva_hud() else if(isAI(mymob)) ai_hud() else if(isrobot(mymob)) diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 82a9d79c47..7425716cd9 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -1,416 +1,305 @@ -/datum/hud/proc/human_hud(var/ui_style='icons/mob/screen1_White.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255) +/datum/hud/proc/human_hud(var/ui_style='icons/mob/screen1_White.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255, var/mob/living/carbon/human/target) + + var/datum/hud_data/hud_data + if(!istype(target)) + hud_data = new() + else + hud_data = target.species.hud + + if(hud_data.icon) + ui_style = hud_data.icon src.adding = list() src.other = list() src.hotkeybuttons = list() //These can be disabled for hotkey usersx + var/list/hud_elements = list() var/obj/screen/using var/obj/screen/inventory/inv_box - using = new /obj/screen() - using.name = "act_intent" - using.dir = SOUTHWEST - using.icon = ui_style - using.icon_state = "intent_"+mymob.a_intent - using.screen_loc = ui_acti - using.color = ui_color - using.alpha = ui_alpha - using.layer = 20 - src.adding += using - action_intent = using + // Draw the various inventory equipment slots. + var/has_hidden_gear + for(var/gear_slot in hud_data.gear) -//intent small hud objects - var/icon/ico + inv_box = new /obj/screen/inventory() + inv_box.icon = ui_style + inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha - ico = new(ui_style, "black") - ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) - ico.DrawBox(rgb(255,255,255,1),1,ico.Height()/2,ico.Width()/2,ico.Height()) - using = new /obj/screen( src ) - using.name = "help" - using.icon = ico - using.screen_loc = ui_acti - using.alpha = ui_alpha - using.layer = 21 - src.adding += using - help_intent = using + var/list/slot_data = hud_data.gear[gear_slot] + inv_box.name = gear_slot + inv_box.screen_loc = slot_data["loc"] + inv_box.slot_id = slot_data["slot"] + inv_box.icon_state = slot_data["state"] - ico = new(ui_style, "black") - ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) - ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,ico.Height()/2,ico.Width(),ico.Height()) - using = new /obj/screen( src ) - using.name = "disarm" - using.icon = ico - using.screen_loc = ui_acti - using.alpha = ui_alpha - using.layer = 21 - src.adding += using - disarm_intent = using + if(slot_data["dir"]) + inv_box.dir = slot_data["dir"] - ico = new(ui_style, "black") - ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) - ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,1,ico.Width(),ico.Height()/2) - using = new /obj/screen( src ) - using.name = "grab" - using.icon = ico - using.screen_loc = ui_acti - using.alpha = ui_alpha - using.layer = 21 - src.adding += using - grab_intent = using + if(slot_data["toggle"]) + src.other += inv_box + has_hidden_gear = 1 + else + src.adding += inv_box - ico = new(ui_style, "black") - ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) - ico.DrawBox(rgb(255,255,255,1),1,1,ico.Width()/2,ico.Height()/2) - using = new /obj/screen( src ) - using.name = "harm" - using.icon = ico - using.screen_loc = ui_acti - using.alpha = ui_alpha - using.layer = 21 - src.adding += using - hurt_intent = using + if(has_hidden_gear) + using = new /obj/screen() + using.name = "toggle" + using.icon = ui_style + using.icon_state = "other" + using.screen_loc = ui_inventory + using.layer = 20 + using.color = ui_color + using.alpha = ui_alpha + src.adding += using -//end intent small hud objects + // Draw the attack intent dialogue. + if(hud_data.has_a_intent) - using = new /obj/screen() - using.name = "mov_intent" - using.dir = SOUTHWEST - using.icon = ui_style - using.icon_state = (mymob.m_intent == "run" ? "running" : "walking") - using.screen_loc = ui_movi - using.layer = 20 - using.color = ui_color - using.alpha = ui_alpha - src.adding += using - move_intent = using + using = new /obj/screen() + using.name = "act_intent" + using.dir = SOUTHWEST + using.icon = ui_style + using.icon_state = "intent_"+mymob.a_intent + using.screen_loc = ui_acti + using.color = ui_color + using.alpha = ui_alpha + using.layer = 20 + src.adding += using + action_intent = using - using = new /obj/screen() - using.name = "drop" - using.icon = ui_style - using.icon_state = "act_drop" - using.screen_loc = ui_drop_throw - using.layer = 19 - using.color = ui_color - using.alpha = ui_alpha - src.hotkeybuttons += using + hud_elements |= using - inv_box = new /obj/screen/inventory() - inv_box.name = "i_clothing" - inv_box.dir = SOUTH - inv_box.icon = ui_style - inv_box.slot_id = slot_w_uniform - inv_box.icon_state = "center" - inv_box.screen_loc = ui_iclothing - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.other += inv_box + //intent small hud objects + var/icon/ico - inv_box = new /obj/screen/inventory() - inv_box.name = "o_clothing" - inv_box.dir = SOUTH - inv_box.icon = ui_style - inv_box.slot_id = slot_wear_suit - inv_box.icon_state = "equip" - inv_box.screen_loc = ui_oclothing - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.other += inv_box + ico = new(ui_style, "black") + ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) + ico.DrawBox(rgb(255,255,255,1),1,ico.Height()/2,ico.Width()/2,ico.Height()) + using = new /obj/screen( src ) + using.name = "help" + using.icon = ico + using.screen_loc = ui_acti + using.alpha = ui_alpha + using.layer = 21 + src.adding += using + help_intent = using - inv_box = new /obj/screen/inventory() - inv_box.name = "r_hand" - inv_box.dir = WEST - inv_box.icon = ui_style - inv_box.icon_state = "hand_inactive" - if(mymob && !mymob.hand) //This being 0 or null means the right hand is in use - inv_box.icon_state = "hand_active" - inv_box.screen_loc = ui_rhand - inv_box.slot_id = slot_r_hand - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha + ico = new(ui_style, "black") + ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) + ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,ico.Height()/2,ico.Width(),ico.Height()) + using = new /obj/screen( src ) + using.name = "disarm" + using.icon = ico + using.screen_loc = ui_acti + using.alpha = ui_alpha + using.layer = 21 + src.adding += using + disarm_intent = using - src.r_hand_hud_object = inv_box - src.adding += inv_box + ico = new(ui_style, "black") + ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) + ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,1,ico.Width(),ico.Height()/2) + using = new /obj/screen( src ) + using.name = "grab" + using.icon = ico + using.screen_loc = ui_acti + using.alpha = ui_alpha + using.layer = 21 + src.adding += using + grab_intent = using - inv_box = new /obj/screen/inventory() - inv_box.name = "l_hand" - inv_box.dir = EAST - inv_box.icon = ui_style - inv_box.icon_state = "hand_inactive" - if(mymob && mymob.hand) //This being 1 means the left hand is in use - inv_box.icon_state = "hand_active" - inv_box.screen_loc = ui_lhand - inv_box.slot_id = slot_l_hand - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.l_hand_hud_object = inv_box - src.adding += inv_box + ico = new(ui_style, "black") + ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) + ico.DrawBox(rgb(255,255,255,1),1,1,ico.Width()/2,ico.Height()/2) + using = new /obj/screen( src ) + using.name = "harm" + using.icon = ico + using.screen_loc = ui_acti + using.alpha = ui_alpha + using.layer = 21 + src.adding += using + hurt_intent = using + //end intent small hud objects - using = new /obj/screen/inventory() - using.name = "hand" - using.dir = SOUTH - using.icon = ui_style - using.icon_state = "hand1" - using.screen_loc = ui_swaphand1 - using.layer = 19 - using.color = ui_color - using.alpha = ui_alpha - src.adding += using + if(hud_data.has_m_intent) + using = new /obj/screen() + using.name = "mov_intent" + using.dir = SOUTHWEST + using.icon = ui_style + using.icon_state = (mymob.m_intent == "run" ? "running" : "walking") + using.screen_loc = ui_movi + using.layer = 20 + using.color = ui_color + using.alpha = ui_alpha + src.adding += using + move_intent = using - using = new /obj/screen/inventory() - using.name = "hand" - using.dir = SOUTH - using.icon = ui_style - using.icon_state = "hand2" - using.screen_loc = ui_swaphand2 - using.layer = 19 - using.color = ui_color - using.alpha = ui_alpha - src.adding += using + if(hud_data.has_drop) + using = new /obj/screen() + using.name = "drop" + using.icon = ui_style + using.icon_state = "act_drop" + using.screen_loc = ui_drop_throw + using.layer = 19 + using.color = ui_color + using.alpha = ui_alpha + src.hotkeybuttons += using - inv_box = new /obj/screen/inventory() - inv_box.name = "id" - inv_box.dir = NORTH - inv_box.icon = ui_style - inv_box.icon_state = "id" - inv_box.screen_loc = ui_id - inv_box.slot_id = slot_wear_id - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.adding += inv_box + if(hud_data.has_hands) - inv_box = new /obj/screen/inventory() - inv_box.name = "mask" - inv_box.dir = NORTH - inv_box.icon = ui_style - inv_box.icon_state = "equip" - inv_box.screen_loc = ui_mask - inv_box.slot_id = slot_wear_mask - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.other += inv_box + using = new /obj/screen() + using.name = "equip" + using.icon = ui_style + using.icon_state = "act_equip" + using.screen_loc = ui_equip + using.layer = 20 + using.color = ui_color + using.alpha = ui_alpha + src.adding += using - inv_box = new /obj/screen/inventory() - inv_box.name = "back" - inv_box.dir = NORTH - inv_box.icon = ui_style - inv_box.icon_state = "back" - inv_box.screen_loc = ui_back - inv_box.slot_id = slot_back - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.adding += inv_box + inv_box = new /obj/screen/inventory() + inv_box.name = "r_hand" + inv_box.dir = WEST + inv_box.icon = ui_style + inv_box.icon_state = "hand_inactive" + if(mymob && !mymob.hand) //This being 0 or null means the right hand is in use + inv_box.icon_state = "hand_active" + inv_box.screen_loc = ui_rhand + inv_box.slot_id = slot_r_hand + inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha - inv_box = new /obj/screen/inventory() - inv_box.name = "storage1" - inv_box.icon = ui_style - inv_box.icon_state = "pocket" - inv_box.screen_loc = ui_storage1 - inv_box.slot_id = slot_l_store - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.adding += inv_box + src.r_hand_hud_object = inv_box + src.adding += inv_box - inv_box = new /obj/screen/inventory() - inv_box.name = "storage2" - inv_box.icon = ui_style - inv_box.icon_state = "pocket" - inv_box.screen_loc = ui_storage2 - inv_box.slot_id = slot_r_store - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.adding += inv_box + inv_box = new /obj/screen/inventory() + inv_box.name = "l_hand" + inv_box.dir = EAST + inv_box.icon = ui_style + inv_box.icon_state = "hand_inactive" + if(mymob && mymob.hand) //This being 1 means the left hand is in use + inv_box.icon_state = "hand_active" + inv_box.screen_loc = ui_lhand + inv_box.slot_id = slot_l_hand + inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha + src.l_hand_hud_object = inv_box + src.adding += inv_box - inv_box = new /obj/screen/inventory() - inv_box.name = "suit storage" - inv_box.icon = ui_style - inv_box.dir = 8 //The sprite at dir=8 has the background whereas the others don't. - inv_box.icon_state = "belt" - inv_box.screen_loc = ui_sstore1 - inv_box.slot_id = slot_s_store - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.adding += inv_box + using = new /obj/screen/inventory() + using.name = "hand" + using.dir = SOUTH + using.icon = ui_style + using.icon_state = "hand1" + using.screen_loc = ui_swaphand1 + using.layer = 19 + using.color = ui_color + using.alpha = ui_alpha + src.adding += using - using = new /obj/screen() - using.name = "resist" - using.icon = ui_style - using.icon_state = "act_resist" - using.screen_loc = ui_pull_resist - using.layer = 19 - using.color = ui_color - using.alpha = ui_alpha - src.hotkeybuttons += using + using = new /obj/screen/inventory() + using.name = "hand" + using.dir = SOUTH + using.icon = ui_style + using.icon_state = "hand2" + using.screen_loc = ui_swaphand2 + using.layer = 19 + using.color = ui_color + using.alpha = ui_alpha + src.adding += using - using = new /obj/screen() - using.name = "toggle" - using.icon = ui_style - using.icon_state = "other" - using.screen_loc = ui_inventory - using.layer = 20 - using.color = ui_color - using.alpha = ui_alpha - src.adding += using + if(hud_data.has_resist) + using = new /obj/screen() + using.name = "resist" + using.icon = ui_style + using.icon_state = "act_resist" + using.screen_loc = ui_pull_resist + using.layer = 19 + using.color = ui_color + using.alpha = ui_alpha + src.hotkeybuttons += using - using = new /obj/screen() - using.name = "equip" - using.icon = ui_style - using.icon_state = "act_equip" - using.screen_loc = ui_equip - using.layer = 20 - using.color = ui_color - using.alpha = ui_alpha - src.adding += using + if(hud_data.has_throw) + mymob.throw_icon = new /obj/screen() + mymob.throw_icon.icon = ui_style + mymob.throw_icon.icon_state = "act_throw_off" + mymob.throw_icon.name = "throw" + mymob.throw_icon.screen_loc = ui_drop_throw + mymob.throw_icon.color = ui_color + mymob.throw_icon.alpha = ui_alpha + src.hotkeybuttons += mymob.throw_icon + hud_elements |= mymob.throw_icon - inv_box = new /obj/screen/inventory() - inv_box.name = "gloves" - inv_box.icon = ui_style - inv_box.icon_state = "gloves" - inv_box.screen_loc = ui_gloves - inv_box.slot_id = slot_gloves - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.other += inv_box + mymob.pullin = new /obj/screen() + mymob.pullin.icon = ui_style + mymob.pullin.icon_state = "pull0" + mymob.pullin.name = "pull" + mymob.pullin.screen_loc = ui_pull_resist + src.hotkeybuttons += mymob.pullin + hud_elements |= mymob.pullin - inv_box = new /obj/screen/inventory() - inv_box.name = "eyes" - inv_box.icon = ui_style - inv_box.icon_state = "glasses" - inv_box.screen_loc = ui_glasses - inv_box.slot_id = slot_glasses - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.other += inv_box + if(hud_data.has_internals) + mymob.internals = new /obj/screen() + mymob.internals.icon = ui_style + mymob.internals.icon_state = "internal0" + mymob.internals.name = "internal" + mymob.internals.screen_loc = ui_internal - inv_box = new /obj/screen/inventory() - inv_box.name = "l_ear" - inv_box.icon = ui_style - inv_box.icon_state = "ears" - inv_box.screen_loc = ui_l_ear - inv_box.slot_id = slot_l_ear - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.other += inv_box + if(hud_data.has_warnings) + mymob.oxygen = new /obj/screen() + mymob.oxygen.icon = ui_style + mymob.oxygen.icon_state = "oxy0" + mymob.oxygen.name = "oxygen" + mymob.oxygen.screen_loc = ui_oxygen + hud_elements |= mymob.oxygen - inv_box = new /obj/screen/inventory() - inv_box.name = "r_ear" - inv_box.icon = ui_style - inv_box.icon_state = "ears" - inv_box.screen_loc = ui_r_ear - inv_box.slot_id = slot_r_ear - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.other += inv_box + mymob.toxin = new /obj/screen() + mymob.toxin.icon = ui_style + mymob.toxin.icon_state = "tox0" + mymob.toxin.name = "toxin" + mymob.toxin.screen_loc = ui_toxin + hud_elements |= mymob.toxin - inv_box = new /obj/screen/inventory() - inv_box.name = "head" - inv_box.icon = ui_style - inv_box.icon_state = "hair" - inv_box.screen_loc = ui_head - inv_box.slot_id = slot_head - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.other += inv_box + mymob.fire = new /obj/screen() + mymob.fire.icon = ui_style + mymob.fire.icon_state = "fire0" + mymob.fire.name = "fire" + mymob.fire.screen_loc = ui_fire + hud_elements |= mymob.fire - inv_box = new /obj/screen/inventory() - inv_box.name = "shoes" - inv_box.icon = ui_style - inv_box.icon_state = "shoes" - inv_box.screen_loc = ui_shoes - inv_box.slot_id = slot_shoes - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.other += inv_box + mymob.healths = new /obj/screen() + mymob.healths.icon = ui_style + mymob.healths.icon_state = "health0" + mymob.healths.name = "health" + mymob.healths.screen_loc = ui_health + hud_elements |= mymob.healths - inv_box = new /obj/screen/inventory() - inv_box.name = "belt" - inv_box.icon = ui_style - inv_box.icon_state = "belt" - inv_box.screen_loc = ui_belt - inv_box.slot_id = slot_belt - inv_box.layer = 19 - inv_box.color = ui_color - inv_box.alpha = ui_alpha - src.adding += inv_box + if(hud_data.has_pressure) + mymob.pressure = new /obj/screen() + mymob.pressure.icon = ui_style + mymob.pressure.icon_state = "pressure0" + mymob.pressure.name = "pressure" + mymob.pressure.screen_loc = ui_pressure + hud_elements |= mymob.pressure - mymob.throw_icon = new /obj/screen() - mymob.throw_icon.icon = ui_style - mymob.throw_icon.icon_state = "act_throw_off" - mymob.throw_icon.name = "throw" - mymob.throw_icon.screen_loc = ui_drop_throw - mymob.throw_icon.color = ui_color - mymob.throw_icon.alpha = ui_alpha - src.hotkeybuttons += mymob.throw_icon + if(hud_data.has_bodytemp) + mymob.bodytemp = new /obj/screen() + mymob.bodytemp.icon = ui_style + mymob.bodytemp.icon_state = "temp1" + mymob.bodytemp.name = "body temperature" + mymob.bodytemp.screen_loc = ui_temp + hud_elements |= mymob.bodytemp - mymob.oxygen = new /obj/screen() - mymob.oxygen.icon = ui_style - mymob.oxygen.icon_state = "oxy0" - mymob.oxygen.name = "oxygen" - mymob.oxygen.screen_loc = ui_oxygen - - mymob.pressure = new /obj/screen() - mymob.pressure.icon = ui_style - mymob.pressure.icon_state = "pressure0" - mymob.pressure.name = "pressure" - mymob.pressure.screen_loc = ui_pressure - - mymob.toxin = new /obj/screen() - mymob.toxin.icon = ui_style - mymob.toxin.icon_state = "tox0" - mymob.toxin.name = "toxin" - mymob.toxin.screen_loc = ui_toxin - - mymob.internals = new /obj/screen() - mymob.internals.icon = ui_style - mymob.internals.icon_state = "internal0" - mymob.internals.name = "internal" - mymob.internals.screen_loc = ui_internal - - mymob.fire = new /obj/screen() - mymob.fire.icon = ui_style - mymob.fire.icon_state = "fire0" - mymob.fire.name = "fire" - mymob.fire.screen_loc = ui_fire - - mymob.bodytemp = new /obj/screen() - mymob.bodytemp.icon = ui_style - mymob.bodytemp.icon_state = "temp1" - mymob.bodytemp.name = "body temperature" - mymob.bodytemp.screen_loc = ui_temp - - mymob.healths = new /obj/screen() - mymob.healths.icon = ui_style - mymob.healths.icon_state = "health0" - mymob.healths.name = "health" - mymob.healths.screen_loc = ui_health - - mymob.nutrition_icon = new /obj/screen() - mymob.nutrition_icon.icon = ui_style - mymob.nutrition_icon.icon_state = "nutrition0" - mymob.nutrition_icon.name = "nutrition" - mymob.nutrition_icon.screen_loc = ui_nutrition - - mymob.pullin = new /obj/screen() - mymob.pullin.icon = ui_style - mymob.pullin.icon_state = "pull0" - mymob.pullin.name = "pull" - mymob.pullin.screen_loc = ui_pull_resist - src.hotkeybuttons += mymob.pullin + if(hud_data.has_nutrition) + mymob.nutrition_icon = new /obj/screen() + mymob.nutrition_icon.icon = ui_style + mymob.nutrition_icon.icon_state = "nutrition0" + mymob.nutrition_icon.name = "nutrition" + mymob.nutrition_icon.screen_loc = ui_nutrition + hud_elements |= mymob.nutrition_icon mymob.blind = new /obj/screen() mymob.blind.icon = 'icons/mob/screen1_full.dmi' @@ -419,6 +308,7 @@ mymob.blind.screen_loc = "1,1" mymob.blind.mouse_opacity = 0 mymob.blind.layer = 0 + hud_elements |= mymob.blind mymob.damageoverlay = new /obj/screen() mymob.damageoverlay.icon = 'icons/mob/screen1_full.dmi' @@ -427,6 +317,7 @@ mymob.damageoverlay.screen_loc = "1,1" mymob.damageoverlay.mouse_opacity = 0 mymob.damageoverlay.layer = 18.1 //The black screen overlay sets layer to 18 to display it, this one has to be just on top. + hud_elements |= mymob.damageoverlay mymob.flash = new /obj/screen() mymob.flash.icon = ui_style @@ -434,6 +325,7 @@ mymob.flash.name = "flash" mymob.flash.screen_loc = "1,1 to 15,15" mymob.flash.layer = 17 + hud_elements |= mymob.flash mymob.pain = new /obj/screen( null ) @@ -443,11 +335,13 @@ mymob.zone_sel.alpha = ui_alpha mymob.zone_sel.overlays.Cut() mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]") + hud_elements |= mymob.zone_sel //Handle the gun settings buttons mymob.gun_setting_icon = new /obj/screen/gun/mode(null) //mymob.gun_setting_icon.color = ui_color mymob.gun_setting_icon.alpha = ui_alpha + hud_elements |= mymob.gun_setting_icon mymob.item_use_icon = new /obj/screen/gun/item(null) //mymob.item_use_icon.color = ui_color @@ -468,7 +362,7 @@ mymob.client.screen = null - mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.pressure, mymob.toxin, mymob.bodytemp, mymob.internals, mymob.fire, mymob.healths, mymob.nutrition_icon, mymob.pullin, mymob.blind, mymob.flash, mymob.damageoverlay, mymob.gun_setting_icon) //, mymob.hands, mymob.rest, mymob.sleep) //, mymob.mach ) + mymob.client.screen += hud_elements mymob.client.screen += src.adding + src.hotkeybuttons inventory_shown = 0; diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 079c551ebf..8a10310b3d 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -235,8 +235,6 @@ if("walk") usr.m_intent = "run" usr.hud_used.move_intent.icon_state = "running" - if(istype(usr,/mob/living/carbon/alien/humanoid)) - usr.update_icons() if("m_intent") if(!usr.m_int) switch(usr.m_intent) diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index b84b9f467c..3c1cb43727 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -90,21 +90,10 @@ Aliens Defaults to same as monkey in most places */ -/mob/living/carbon/alien/UnarmedAttack(var/atom/A) - A.attack_alien(src) -/atom/proc/attack_alien(mob/user as mob) - attack_paw(user) - return + /mob/living/carbon/alien/RestrainedClickOn(var/atom/A) return -// Babby aliens -/mob/living/carbon/alien/larva/UnarmedAttack(var/atom/A) - A.attack_larva(src) -/atom/proc/attack_larva(mob/user as mob) - return - - /* Slimes Nothing happening here diff --git a/code/controllers/hooks-defs.dm b/code/controllers/hooks-defs.dm index 1cd7c4aad8..001372b4e3 100644 --- a/code/controllers/hooks-defs.dm +++ b/code/controllers/hooks-defs.dm @@ -33,7 +33,7 @@ /** * Debrained hook. * Called in brain_item.dm when someone gets debrained. - * Parameters: var/obj/item/brain + * Parameters: var/obj/item/organ/brain */ /hook/debrain @@ -47,7 +47,7 @@ /** * Podman hook. * Called in podmen.dm when someone is brought back as a Diona. - * Parameters: var/mob/living/carbon/monkey/diona + * Parameters: var/mob/living/carbon/alien/diona */ /hook/harvest_podman diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 4c01933dbe..1e6d9790eb 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -259,6 +259,8 @@ client body += "" body += "" body += "" + body += "" + body += "" body += "" @@ -495,7 +497,7 @@ client src.give_disease(M) href_list["datumrefresh"] = href_list["give_spell"] - + else if(href_list["give_disease2"]) if(!check_rights(R_ADMIN|R_FUN)) return @@ -777,6 +779,9 @@ client usr << "Mob doesn't exist anymore" return + // Clear out their species abilities. + H.species.remove_inherent_verbs(H) + if(H.set_species(new_species)) usr << "Set species of [H] to [H.species]." H.regenerate_icons() @@ -827,9 +832,9 @@ client else if(href_list["addverb"]) if(!check_rights(R_DEBUG)) return - + var/mob/living/H = locate(href_list["addverb"]) - + if(!istype(H)) usr << "This can only be done to instances of type /mob/living" return @@ -845,7 +850,7 @@ client possibleverbs += typesof(/mob/living/silicon/proc,/mob/living/silicon/ai/proc,/mob/living/silicon/ai/verb) possibleverbs -= H.verbs possibleverbs += "Cancel" // ...And one for the bottom - + var/verb = input("Select a verb!", "Verbs",null) as anything in possibleverbs if(!H) usr << "Mob doesn't exist anymore" @@ -854,7 +859,7 @@ client return else H.verbs += verb - + else if(href_list["remverb"]) if(!check_rights(R_DEBUG)) return @@ -872,7 +877,75 @@ client else H.verbs -= verb - + else if(href_list["addorgan"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/M = locate(href_list["addorgan"]) + if(!istype(M)) + usr << "This can only be done to instances of type /mob/living/carbon" + return + + var/new_organ = input("Please choose an organ to add.","Organ",null) as null|anything in typesof(/datum/organ/internal)-/datum/organ/internal + + if(!M) + usr << "Mob doesn't exist anymore" + return + + if(locate(new_organ) in M.internal_organs) + usr << "Mob already has that organ." + return + + if(istype(M,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + var/datum/organ/internal/I = new new_organ(H) + + var/organ_slot = input(usr, "Which slot do you want the organ to go in ('default' for default)?") as text|null + + if(!organ_slot) + return + + if(organ_slot != "default") + organ_slot = sanitize(copytext(organ_slot,1,MAX_MESSAGE_LEN)) + else + if(I.removed_type) + var/obj/item/organ/O = new I.removed_type() + organ_slot = O.organ_tag + del(O) + else + organ_slot = "unknown organ" + + if(H.internal_organs_by_name[organ_slot]) + usr << "[H] already has an organ in that slot." + del(I) + return + + H.internal_organs_by_name[organ_slot] = I + usr << "Added new [new_organ] to [H] as slot [organ_slot]." + else + new new_organ(M) + usr << "Added new [new_organ] to [M]." + + else if(href_list["remorgan"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/M = locate(href_list["remorgan"]) + if(!istype(M)) + usr << "This can only be done to instances of type /mob/living/carbon" + return + + var/rem_organ = input("Please choose an organ to remove.","Organ",null) as null|anything in M.internal_organs + + if(!M) + usr << "Mob doesn't exist anymore" + return + + if(!(locate(rem_organ) in M.internal_organs)) + usr << "Mob does not have that organ." + return + + usr << "Removed [rem_organ] from [M]." + del(rem_organ) + else if(href_list["fix_nano"]) if(!check_rights(R_DEBUG)) return @@ -881,18 +954,14 @@ client if(!istype(H) || !H.client) usr << "This can only be done on mobs with clients" return - - nanomanager.send_resources(H.client) - + usr << "Resource files sent" H << "Your NanoUI Resource files have been refreshed" log_admin("[key_name(usr)] resent the NanoUI resource files to [key_name(H)] ") - - else if(href_list["regenerateicons"]) if(!check_rights(0)) return diff --git a/code/datums/diseases/appendicitis.dm b/code/datums/diseases/appendicitis.dm index dba42d74d6..a9959ef063 100644 --- a/code/datums/diseases/appendicitis.dm +++ b/code/datums/diseases/appendicitis.dm @@ -19,7 +19,8 @@ if(istype(affected_mob,/mob/living/carbon/human)) var/mob/living/carbon/human/H = affected_mob - if(H.species.name == "Diona" || H.species.name == "Machine" || H.species.name == "Vox") src.cure() + if(!H.internal_organs_by_name["appendix"]) + src.cure() if(stage == 1) if(affected_mob.op_stage.appendix == 2.0) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 34dc2e1344..cc22ce05d3 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -1234,27 +1234,6 @@ datum/mind ..() mind.assigned_role = "slime" -//XENO -/mob/living/carbon/alien/mind_initialize() - ..() - mind.assigned_role = "Alien" - //XENO HUMANOID -/mob/living/carbon/alien/humanoid/queen/mind_initialize() - ..() - mind.special_role = "Queen" - -/mob/living/carbon/alien/humanoid/hunter/mind_initialize() - ..() - mind.special_role = "Hunter" - -/mob/living/carbon/alien/humanoid/drone/mind_initialize() - ..() - mind.special_role = "Drone" - -/mob/living/carbon/alien/humanoid/sentinel/mind_initialize() - ..() - mind.special_role = "Sentinel" - //XENO LARVA /mob/living/carbon/alien/larva/mind_initialize() ..() mind.special_role = "Larva" diff --git a/code/datums/spells/inflict_handler.dm b/code/datums/spells/inflict_handler.dm index ac85b18ae3..496eac9195 100644 --- a/code/datums/spells/inflict_handler.dm +++ b/code/datums/spells/inflict_handler.dm @@ -26,8 +26,8 @@ if("gib_brain") if(ishuman(target) || ismonkey(target)) var/mob/living/carbon/C = target - if(C.brain_op_stage != 4) // Their brain is already taken out - var/obj/item/brain/B = new(C.loc) + if(!C.has_brain()) // Their brain is already taken out + var/obj/item/organ/brain/B = new(C.loc) B.transfer_identity(C) target.gib() if("disintegrate") diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index be2bb88a17..d08679bbc1 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -111,7 +111,7 @@ src.visible_message("[src] transforms!") src.verbs -= /mob/proc/changeling_change_species - H.set_species(S,null,1) //Until someone moves body colour into DNA, they're going to have to use the default. + H.set_species(S,1) //Until someone moves body colour into DNA, they're going to have to use the default. spawn(10) src.verbs += /mob/proc/changeling_change_species diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index e883c93577..53ac2ee2d5 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -570,8 +570,8 @@ var/list/sacrificed = list() if(!(iscultist(V))) victims += V//Checks for cult status and mob type for(var/obj/item/I in src.loc)//Checks for MMIs/brains/Intellicards - if(istype(I,/obj/item/brain)) - var/obj/item/brain/B = I + if(istype(I,/obj/item/organ/brain)) + var/obj/item/organ/brain/B = I victims += B.brainmob else if(istype(I,/obj/item/device/mmi)) var/obj/item/device/mmi/B = I @@ -583,7 +583,15 @@ var/list/sacrificed = list() if(iscultist(C) && !C.stat) cultsinrange += C C.say("Barhah hra zar[pick("'","`")]garis!") + for(var/mob/H in victims) + + var/worth = 0 + if(istype(H,/mob/living/carbon/human)) + var/mob/living/carbon/human/lamb = H + if(lamb.species.rarity_value > 3) + worth = 1 + if (ticker.mode.name == "cult") if(H.mind == ticker.mode:sacrifice_target) if(cultsinrange.len >= 3) @@ -598,8 +606,8 @@ var/list/sacrificed = list() else if(cultsinrange.len >= 3) if(H.stat !=2) - if(prob(80)) - usr << "\red The Geometer of Blood accepts this sacrifice." + if(prob(80) || worth) + usr << "\red The Geometer of Blood accepts this [worth ? "exotic " : ""]sacrifice." ticker.mode:grant_runeword(usr) else usr << "\red The Geometer of blood accepts this sacrifice." @@ -609,8 +617,8 @@ var/list/sacrificed = list() else H.gib() else - if(prob(40)) - usr << "\red The Geometer of blood accepts this sacrifice." + if(prob(40) || worth) + usr << "\red The Geometer of blood accepts this [worth ? "exotic " : ""]sacrifice." ticker.mode:grant_runeword(usr) else usr << "\red The Geometer of blood accepts this sacrifice." @@ -692,21 +700,6 @@ var/list/sacrificed = list() if(prob(20)) ticker.mode.grant_runeword(usr) M.gib() -/* for(var/mob/living/carbon/alien/A) - for(var/mob/K in cultsinrange) - K.say("Barhah hra zar'garis!") - A.dust() /// A.gib() doesnt work for some reason, and dust() leaves that skull and bones thingy which we dont really need. - if (ticker.mode.name == "cult") - if(prob(75)) - usr << "\red The Geometer of Blood accepts your exotic sacrifice." - ticker.mode:grant_runeword(usr) - else - usr << "\red The Geometer of Blood accepts your exotic sacrifice." - usr << "\red However, this alien is not enough to gain His favor." - else - usr << "\red The Geometer of Blood accepts your exotic sacrifice." - return - return fizzle() */ /////////////////////////////////////////SIXTEENTH RUNE diff --git a/code/game/gamemodes/events/ninja_equipment.dm b/code/game/gamemodes/events/ninja_equipment.dm index b36eb64d8b..ded12b2da8 100644 --- a/code/game/gamemodes/events/ninja_equipment.dm +++ b/code/game/gamemodes/events/ninja_equipment.dm @@ -1451,32 +1451,34 @@ It is possible to destroy the net by the occupant or someone else. return attack_hand() + if (HULK in usr.mutations) usr << text("\blue You easily destroy the energy net.") for(var/mob/O in oviewers(src)) O.show_message(text("\red [] rips the energy net apart!", usr), 1) health-=50 + else if(istype(usr,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = usr + if(H.species.can_shred(H)) + + H << text("\green You claw at the net.") + for(var/mob/O in oviewers(src)) + O.show_message(text("\red [] claws at the energy net!", H), 1) + + playsound(src.loc, 'sound/weapons/slash.ogg', 80, 1) + health -= rand(10, 20) + + if(health <= 0) + H << text("\green You slice the energy net to pieces.") + for(var/mob/O in oviewers(src)) + O.show_message(text("\red [] slices the energy net apart!", H), 1) + healthcheck() return attack_paw() return attack_hand() - attack_alien() - if (islarva(usr)) - return - usr << text("\green You claw at the net.") - for(var/mob/O in oviewers(src)) - O.show_message(text("\red [] claws at the energy net!", usr), 1) - playsound(src.loc, 'sound/weapons/slash.ogg', 80, 1) - health -= rand(10, 20) - if(health <= 0) - usr << text("\green You slice the energy net to pieces.") - for(var/mob/O in oviewers(src)) - O.show_message(text("\red [] slices the energy net apart!", usr), 1) - healthcheck() - return - attackby(obj/item/weapon/W as obj, mob/user as mob) var/aforce = W.force health = max(0, health - aforce) diff --git a/code/game/gamemodes/events/space_ninja.dm b/code/game/gamemodes/events/space_ninja.dm index c1fd9b219f..5dae9e6e4b 100644 --- a/code/game/gamemodes/events/space_ninja.dm +++ b/code/game/gamemodes/events/space_ninja.dm @@ -219,8 +219,8 @@ Malf AIs/silicons aren't added. Monkeys aren't added. Messes with objective comp //Xenos and deathsquads take precedence over everything else. //Unless the xenos are hiding in a locker somewhere, this'll find em. - for(var/mob/living/carbon/alien/humanoid/xeno in player_list) - if(istype(xeno)) + for(var/mob/living/carbon/human/xeno in player_list) + if(istype(xeno.species,/datum/species/xenos)) xeno_list += xeno if(assign_mission) @@ -230,11 +230,11 @@ Malf AIs/silicons aren't added. Monkeys aren't added. Messes with objective comp if(xeno_list.len>3)//If there are more than three humanoid xenos on the station, time to get dangerous. //Here we want the ninja to murder all the queens. The other aliens don't really matter. var/xeno_queen_list[] = list() - for(var/mob/living/carbon/alien/humanoid/queen/xeno_queen in xeno_list) - if(xeno_queen.mind&&xeno_queen.stat!=2) + for(var/mob/living/carbon/human/xeno_queen in xeno_list) + if(xeno_queen.species.name == "Xenomorph Queen" && xeno_queen.mind && xeno_queen.stat!=2) xeno_queen_list += xeno_queen if(xeno_queen_list.len&&side=="face")//If there are queen about and the probability is 50. - for(var/mob/living/carbon/alien/humanoid/queen/xeno_queen in xeno_queen_list) + for(var/mob/living/carbon/human/xeno_queen in xeno_queen_list) var/datum/objective/assassinate/ninja_objective = new ninja_objective.owner = ninja_mind //We'll do some manual overrides to properly set it up. diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index 320e89d9b2..1f05a64fad 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -112,15 +112,9 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' for(var/datum/organ/external/limb in vox.organs) limb.status &= ~(ORGAN_DESTROYED | ORGAN_ROBOT) - //Generate cortical stack. - var/datum/organ/external/affected = vox.get_organ("head") - - var/obj/item/weapon/implant/cortical/I = new(vox) - I.imp_in = vox - I.implanted = 1 - affected.implants += I - I.part = affected - cortical_stacks += I + // Keep track of their stack. + if(vox.internal_organs_by_name["stack"]) + cortical_stacks |= vox.internal_organs_by_name["stack"] vox.equip_vox_raider() vox.regenerate_icons() @@ -130,8 +124,8 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' if(cortical_stacks.len == 0) return 0 - for(var/obj/stack in cortical_stacks) - if (get_area(stack) != locate(/area/shuttle/vox/station)) + for(var/datum/organ/internal/stack/vox/stack in cortical_stacks) + if(stack.organ_holder && get_area(stack.organ_holder) != locate(/area/shuttle/vox/station)) return 0 return 1 diff --git a/code/game/gamemodes/mutiny/directives/ipc_virus_directive.dm b/code/game/gamemodes/mutiny/directives/ipc_virus_directive.dm index 63c3f7d3c8..e035b665c9 100644 --- a/code/game/gamemodes/mutiny/directives/ipc_virus_directive.dm +++ b/code/game/gamemodes/mutiny/directives/ipc_virus_directive.dm @@ -62,11 +62,11 @@ datum/directive/ipc_virus/get_remaining_orders() return text -/hook/debrain/proc/debrain_directive(obj/item/brain/B) +/hook/debrain/proc/debrain_directive(var/obj/item/organ/brain/B) var/datum/directive/ipc_virus/D = get_directive("ipc_virus") if (!D) return 1 - if(D.brains_to_enslave.Find(B.brainmob.mind)) + if(B && B.brainmob && B.brainmob.mind && D.brains_to_enslave.Find(B.brainmob.mind)) D.brains_to_enslave.Remove(B.brainmob.mind) return 1 diff --git a/code/game/gamemodes/mutiny/mutiny_hooks.dm b/code/game/gamemodes/mutiny/mutiny_hooks.dm index 5bcddade43..9e64bd2e70 100644 --- a/code/game/gamemodes/mutiny/mutiny_hooks.dm +++ b/code/game/gamemodes/mutiny/mutiny_hooks.dm @@ -12,7 +12,7 @@ mode.update_icon(H.mind) return 1 -/hook/harvest_podman/proc/update_icon(mob/living/carbon/monkey/diona/D) +/hook/harvest_podman/proc/update_icon(mob/living/carbon/alien/diona/D) var/datum/game_mode/mutiny/mode = get_mutiny_mode() if (!mode) return 1 diff --git a/code/game/gamemodes/newobjective.dm b/code/game/gamemodes/newobjective.dm index 70901add18..c2608cfa3d 100644 --- a/code/game/gamemodes/newobjective.dm +++ b/code/game/gamemodes/newobjective.dm @@ -1376,7 +1376,7 @@ datum var/list/all_items = owner.current.get_contents() for(var/obj/item/device/mmi/mmi in all_items) if(mmi.brainmob&&mmi.brainmob.mind==target) return 1 - for(var/obj/item/brain/brain in all_items) + for(var/obj/item/organ/brain/brain in all_items) if(brain.brainmob&&brain.brainmob.mind==target) return 1 return 0 diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 9ff5608e2d..e2cc152c8e 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -637,29 +637,24 @@ datum/objective/capture check_completion()//Basically runs through all the mobs in the area to determine how much they are worth. var/captured_amount = 0 var/area/centcom/holding/A = locate() - for(var/mob/living/carbon/human/M in A)//Humans. + + for(var/mob/living/carbon/human/M in A) // Humans (and subtypes). + var/worth = M.species.rarity_value if(M.stat==2)//Dead folks are worth less. - captured_amount+=0.5 + worth*=0.5 continue - captured_amount+=1 + captured_amount += worth + for(var/mob/living/carbon/monkey/M in A)//Monkeys are almost worthless, you failure. captured_amount+=0.1 + for(var/mob/living/carbon/alien/larva/M in A)//Larva are important for research. if(M.stat==2) captured_amount+=0.5 continue captured_amount+=1 - for(var/mob/living/carbon/alien/humanoid/M in A)//Aliens are worth twice as much as humans. - if(istype(M, /mob/living/carbon/alien/humanoid/queen))//Queens are worth three times as much as humans. - if(M.stat==2) - captured_amount+=1.5 - else - captured_amount+=3 - continue - if(M.stat==2) - captured_amount+=1 - continue - captured_amount+=2 + + if(captured_amount= products[choice][2]) + + stored_matter -= products[choice][2] + var/new_organ = products[choice][1] + var/obj/item/organ/O = new new_organ(get_turf(src)) + + if(prints_prosthetics) + O.robotic = 2 + else if(loaded_dna) + visible_message("The printer would be using the DNA sample if it was coded.") + //TODO: Copy DNA hash or donor reference over to new organ. + + visible_message("The bioprinter spits out a new organ.") + + else + user << "There is not enough matter in the printer." + +/obj/machinery/bioprinter/attackby(obj/item/weapon/W, mob/user) + + // DNA sample from syringe. + if(!prints_prosthetics && istype(W,/obj/item/weapon/reagent_containers/syringe)) + user << "You inject the blood sample into the bioprinter, but it isn't coded yet." + return + // Meat for biomass. + else if(!prints_prosthetics && istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat)) + user << "\blue \The [src] processes \the [W]." + stored_matter += 50 + user.drop_item() + del(W) + return + // Steel for matter. + else if(prints_prosthetics && istype(W, /obj/item/stack/sheet/metal)) + var/obj/item/stack/sheet/metal/M = W + user << "\blue \The [src] processes \the [W]." + stored_matter += M.amount * 10 + user.drop_item() + del(W) + return + else + return..() \ No newline at end of file diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm index 85bd575817..4c859c7ede 100644 --- a/code/game/machinery/bots/bots.dm +++ b/code/game/machinery/bots/bots.dm @@ -51,15 +51,6 @@ usr << "[src]'s parts look very loose!" return -/obj/machinery/bot/attack_alien(var/mob/living/carbon/alien/user as mob) - src.health -= rand(15,30)*brute_dam_coeff - src.visible_message("\red [user] has slashed [src]!") - playsound(src.loc, 'sound/weapons/slice.ogg', 25, 1, -1) - if(prob(10)) - new /obj/effect/decal/cleanable/blood/oil(src.loc) - healthcheck() - - /obj/machinery/bot/attack_animal(var/mob/living/simple_animal/M as mob) if(M.melee_damage_upper == 0) return src.health -= M.melee_damage_upper @@ -155,6 +146,19 @@ /obj/machinery/bot/attack_ai(mob/user as mob) src.attack_hand(user) +/obj/machinery/bot/attack_hand(var/mob/living/carbon/human/user) + + if(!istype(user)) + return ..() + + if(user.species.can_shred(user)) + src.health -= rand(15,30)*brute_dam_coeff + src.visible_message("\red [user] has slashed [src]!") + playsound(src.loc, 'sound/weapons/slice.ogg', 25, 1, -1) + if(prob(10)) + new /obj/effect/decal/cleanable/blood/oil(src.loc) + healthcheck() + /******************************************************************/ // Navigation procs // Used for A-star pathfinding diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm index 1762225088..ce76680b0d 100644 --- a/code/game/machinery/bots/mulebot.dm +++ b/code/game/machinery/bots/mulebot.dm @@ -803,10 +803,7 @@ H.apply_damage(0.5*damage, BRUTE, "l_arm") H.apply_damage(0.5*damage, BRUTE, "r_arm") - var/obj/effect/decal/cleanable/blood/B = new(src.loc) - B.blood_DNA = list() - B.blood_DNA[H.dna.unique_enzymes] = H.dna.b_type - + blood_splatter(src,H,1) bloodiness += 4 // player on mulebot attempted to move diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm index 19bc7d3b91..a8e670bf12 100644 --- a/code/game/machinery/bots/secbot.dm +++ b/code/game/machinery/bots/secbot.dm @@ -787,12 +787,6 @@ Auto Patrol: []"}, if(prob(50)) new /obj/item/robot_parts/l_arm(Tsec) -/obj/machinery/bot/secbot/attack_alien(var/mob/living/carbon/alien/user as mob) - ..() - if(!isalien(target)) - src.target = user - src.mode = SECBOT_HUNT - //Secbot Construction /obj/item/clothing/head/helmet/attackby(var/obj/item/device/assembly/signaler/S, mob/user as mob) diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 14f8f93e56..1c8298bd0b 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -88,15 +88,18 @@ src.view_range = num cameranet.updateVisibility(src, 0) -/obj/machinery/camera/attack_paw(mob/living/carbon/alien/humanoid/user as mob) +/obj/machinery/camera/attack_hand(mob/living/carbon/human/user as mob) + if(!istype(user)) return - status = 0 - visible_message("\The [user] slashes at [src]!") - playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1) - icon_state = "[initial(icon_state)]1" - add_hiddenprint(user) - deactivate(user,0) + + if(user.species.can_shred(user)) + status = 0 + visible_message("\The [user] slashes at [src]!") + playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1) + icon_state = "[initial(icon_state)]1" + add_hiddenprint(user) + deactivate(user,0) /obj/machinery/camera/attackby(W as obj, mob/living/user as mob) diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 8cc6220ad0..88646814b2 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -72,14 +72,15 @@ return var/mob/selected = null - for(var/mob/M in player_list) + for(var/mob/living/M in player_list) //Dead people only thanks! if ((M.stat != 2) || (!M.client)) continue //They need a brain! - if ((istype(M, /mob/living/carbon/human)) && (M:brain_op_stage >= 4.0)) - continue - + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + if(H.species.has_organ["brain"] && !H.has_brain()) + continue if (M.ckey == find_key) selected = M break diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm index 5887e0bc32..65871a67b3 100644 --- a/code/game/machinery/computer/HolodeckControl.dm +++ b/code/game/machinery/computer/HolodeckControl.dm @@ -339,10 +339,7 @@ var/global/list/holodeck_programs = list( /obj/structure/table/holotable/attack_paw(mob/user as mob) return attack_hand(user) -/obj/structure/table/holotable/attack_alien(mob/user as mob) //Removed code for larva since it doesn't work. Previous code is now a larva ability. /N - return attack_hand(user) - -/obj/structure/table/holotable/attack_animal(mob/living/simple_animal/user as mob) //Removed code for larva since it doesn't work. Previous code is now a larva ability. /N +/obj/structure/table/holotable/attack_animal(mob/living/user as mob) //Removed code for larva since it doesn't work. Previous code is now a larva ability. /N return attack_hand(user) /obj/structure/table/holotable/attack_hand(mob/user as mob) @@ -594,9 +591,6 @@ var/global/list/holodeck_programs = list( icon = 'icons/obj/objects.dmi' icon_state = "rack" -/obj/structure/rack/holorack/attack_alien(mob/user as mob) //Removed code for larva since it doesn't work. Previous code is now a larva ability. /N - return attack_hand(user) - /obj/structure/rack/holorack/attack_hand(mob/user as mob) return diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 70a0bb5009..adb4d24b54 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -337,8 +337,13 @@ if ((isnull(subject)) || (!(ishuman(subject))) || (!subject.dna)) scantemp = "Error: Unable to locate valid genetic data." return - if (subject.brain_op_stage == 4.0) - scantemp = "Error: No signs of intelligence detected." + if (!subject.has_brain()) + if(istype(subject, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = subject + if(H.species.has_organ["brain"]) + scantemp = "Error: No signs of intelligence detected." + else + scantemp = "Error: No signs of intelligence detected." return if (subject.suiciding == 1) scantemp = "Error: Subject's brain is not responding to scanning stimuli." diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 288465a160..473bd973ed 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -172,18 +172,15 @@ /obj/machinery/door/window/attack_ai(mob/user as mob) return src.attack_hand(user) -/obj/machinery/door/window/attack_paw(mob/user as mob) - if(istype(user, /mob/living/carbon/alien/humanoid)) - if(src.operating) - return - playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) - visible_message("\red [user] smashes against the [src.name].", 1) - take_damage(25) - else - return src.attack_hand(user) - - /obj/machinery/door/window/attack_hand(mob/user as mob) + + if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + if(H.species.can_shred(H)) + playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) + visible_message("\red [user] smashes against the [src.name].", 1) + take_damage(25) + return return src.attackby(user, user) /obj/machinery/door/window/attackby(obj/item/weapon/I as obj, mob/user as mob) diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index cf05308e40..345d9f44d5 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -81,7 +81,7 @@ if (istype(O, /mob/living/carbon/human)) var/mob/living/carbon/human/H = O var/datum/organ/internal/eyes/E = H.internal_organs_by_name["eyes"] - if ((E.damage > E.min_bruised_damage && prob(E.damage + 50))) + if (E && (E.damage > E.min_bruised_damage && prob(E.damage + 50))) flick("e_flash", O:flash) E.damage += rand(1, 5) else diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm index 5ad0ecae56..af5b67c16d 100644 --- a/code/game/machinery/turrets.dm +++ b/code/game/machinery/turrets.dm @@ -71,6 +71,27 @@ var/targeting_active = 0 var/area/turret_protected/protected_area +/obj/machinery/turret/proc/take_damage(damage) + src.health -= damage + if(src.health<=0) + del src + return + +/obj/machinery/turret/attack_hand(var/mob/living/carbon/human/user) + + if(!istype(user)) + return ..() + + if(user.species.can_shred(user) && !(stat & BROKEN)) + playsound(src.loc, 'sound/weapons/slash.ogg', 25, 1, -1) + visible_message("\red [user] has slashed at [src]!") + src.take_damage(15) + return + +/obj/machinery/turret/bullet_act(var/obj/item/projectile/Proj) + take_damage(Proj.damage) + ..() + return /obj/machinery/turret/New() spark_system = new /datum/effect/effect/system/spark_spread @@ -80,6 +101,11 @@ ..() return +/obj/machinery/turret/proc/update_health() + if(src.health<=0) + del src + return + /obj/machinery/turretcover name = "pop-up turret cover" icon = 'icons/obj/turrets.dmi' @@ -407,7 +433,7 @@ onclose(user, "turretid") -/obj/machinery/turret/attack_animal(mob/living/simple_animal/M as mob) +/obj/machinery/turret/attack_animal(mob/living/M as mob) if(M.melee_damage_upper == 0) return if(!(stat & BROKEN)) visible_message("\red [M] [M.attacktext] [src]!") @@ -420,22 +446,6 @@ M << "\red That object is useless to you." return - - - -/obj/machinery/turret/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - if(!(stat & BROKEN)) - playsound(src.loc, 'sound/weapons/slash.ogg', 25, 1, -1) - visible_message("\red [] has slashed at []!", M, src) - src.health -= 15 - if (src.health <= 0) - src.die() - else - M << "\green That object is useless to you." - return - - - /obj/machinery/turretid/Topic(href, href_list, var/nowindow = 0) if(..(href, href_list)) return @@ -494,6 +504,18 @@ icon = 'icons/obj/turrets.dmi' icon_state = "gun_turret" + proc/take_damage(damage) + src.health -= damage + if(src.health<=0) + del src + return + + + bullet_act(var/obj/item/projectile/Proj) + take_damage(Proj.damage) + ..() + return + ex_act() del src @@ -507,24 +529,6 @@ del src return - proc/update_health() - if(src.health<=0) - del src - return - - proc/take_damage(damage) - src.health -= damage - if(src.health<=0) - del src - return - - - bullet_act(var/obj/item/projectile/Proj) - src.take_damage(Proj.damage) - ..() - return - - attack_hand(mob/user as mob) user.set_machine(src) var/dat = {" @@ -546,12 +550,6 @@ attack_ai(mob/user as mob) return attack_hand(user) - - attack_alien(mob/user as mob) - user.visible_message("[user] slashes at [src]", "You slash at [src]") - src.take_damage(15) - return - Topic(href, href_list) if(href_list["power"]) src.on = !src.on diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 78ee794b53..decf7afb43 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -418,7 +418,26 @@ /obj/mecha/attack_hand(mob/user as mob) src.log_message("Attack by hand/paw. Attacker - [user].",1) - if ((HULK in user.mutations) && !prob(src.deflect_chance)) + if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + if(H.species.can_shred(user)) + if(!prob(src.deflect_chance)) + src.take_damage(15) + src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) + playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) + user << "\red You slash at the armored suit!" + visible_message("\red The [user] slashes at [src.name]'s armor!") + else + src.log_append_to_last("Armor saved.") + playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) + user << "\green Your claws had no effect!" + src.occupant_message("\blue The [user]'s claws are stopped by the armor.") + visible_message("\blue The [user] rebounds off [src.name]'s armor!") + else + user.visible_message("[user] hits [src.name]. Nothing happens","You hit [src.name] with no visible effect.") + src.log_append_to_last("Armor saved.") + return + else if ((HULK in user.mutations) && !prob(src.deflect_chance)) src.take_damage(15) src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) user.visible_message("[user] hits [src.name], doing some damage.", "You hit [src.name] with all your might. The metal creaks and bends.") @@ -430,25 +449,7 @@ /obj/mecha/attack_paw(mob/user as mob) return src.attack_hand(user) - -/obj/mecha/attack_alien(mob/user as mob) - src.log_message("Attack by alien. Attacker - [user].",1) - if(!prob(src.deflect_chance)) - src.take_damage(15) - src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) - user << "\red You slash at the armored suit!" - visible_message("\red The [user] slashes at [src.name]'s armor!") - else - src.log_append_to_last("Armor saved.") - playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) - user << "\green Your claws had no effect!" - src.occupant_message("\blue The [user]'s claws are stopped by the armor.") - visible_message("\blue The [user] rebounds off [src.name]'s armor!") - return - - -/obj/mecha/attack_animal(mob/living/simple_animal/user as mob) +/obj/mecha/attack_animal(mob/living/user as mob) src.log_message("Attack by simple animal. Attacker - [user].",1) if(user.melee_damage_upper == 0) user.emote("[user.friendly] [src]") diff --git a/code/game/objects/effects/aliens.dm b/code/game/objects/effects/aliens.dm index 5e3ba542bf..9983eff1ac 100644 --- a/code/game/objects/effects/aliens.dm +++ b/code/game/objects/effects/aliens.dm @@ -14,8 +14,6 @@ name = "alien thing" desc = "theres something alien about this" icon = 'icons/mob/alien.dmi' -// unacidable = 1 //Aliens won't ment their own. - /* * Resin @@ -31,17 +29,17 @@ var/health = 200 //var/mob/living/affecting = null - wall - name = "resin wall" - desc = "Purple slime solidified into a wall." - icon_state = "resinwall" //same as resin, but consistency ho! +/obj/effect/alien/resin/wall + name = "resin wall" + desc = "Purple slime solidified into a wall." + icon_state = "resinwall" //same as resin, but consistency ho! - membrane - name = "resin membrane" - desc = "Purple slime just thin enough to let light pass through." - icon_state = "resinmembrane" - opacity = 0 - health = 120 +/obj/effect/alien/resin/membrane + name = "resin membrane" + desc = "Purple slime just thin enough to let light pass through." + icon_state = "resinmembrane" + opacity = 0 + health = 120 /obj/effect/alien/resin/New() ..() @@ -121,42 +119,7 @@ /obj/effect/alien/resin/attack_paw() return attack_hand() -/obj/effect/alien/resin/attack_alien() - if (islarva(usr))//Safety check for larva. /N - return - usr << "\green You claw at the [name]." - for(var/mob/O in oviewers(src)) - O.show_message("\red [usr] claws at the resin!", 1) - playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) - health -= rand(40, 60) - if(health <= 0) - usr << "\green You slice the [name] to pieces." - for(var/mob/O in oviewers(src)) - O.show_message("\red [usr] slices the [name] apart!", 1) - healthcheck() - return - /obj/effect/alien/resin/attackby(obj/item/weapon/W as obj, mob/user as mob) - /*if (istype(W, /obj/item/weapon/grab) && get_dist(src,user)<2) - var/obj/item/weapon/grab/G = W - if(isalien(user)&&(ishuman(G.affecting)||ismonkey(G.affecting))) - //Only aliens can stick humans and monkeys into resin walls. Also, the wall must not have a person inside already. - if(!affecting) - if(G.state<2) - user << "\red You need a better grip to do that!" - return - G.affecting.loc = src - G.affecting.paralysis = 10 - for(var/mob/O in viewers(world.view, src)) - if (O.client) - O << text("\green [] places [] in the resin wall!", G.assailant, G.affecting) - affecting=G.affecting - del(W) - spawn(0) - process() - else - user << "\red This wall is already occupied." - return */ var/aforce = W.force health = max(0, health - aforce) @@ -234,7 +197,7 @@ Alien plants should do something if theres a lot of poison if(!linked_node || (get_dist(linked_node, src) > linked_node.node_range) ) return - + direction_loop: for(var/dirn in cardinal) var/turf/T = get_step(src, dirn) @@ -292,15 +255,6 @@ Alien plants should do something if theres a lot of poison health -= 5 healthcheck() -/*/obj/effect/alien/weeds/burn(fi_amount) - if (fi_amount > 18000) - spawn( 0 ) - del(src) - return - return 0 - return 1 -*/ - #undef NODERANGE @@ -382,61 +336,59 @@ Alien plants should do something if theres a lot of poison var/health = 100 var/status = GROWING //can be GROWING, GROWN or BURST; all mutually exclusive - New() - if(aliens_allowed) - ..() - spawn(rand(MIN_GROWTH_TIME,MAX_GROWTH_TIME)) - Grow() - else +/obj/effect/alien/egg/New() + if(aliens_allowed) + ..() + spawn(rand(MIN_GROWTH_TIME,MAX_GROWTH_TIME)) + Grow() + else + del(src) + +/obj/effect/alien/egg/attack_hand(user as mob) + + var/mob/living/carbon/M = user + if(!istype(M) || !(locate(/datum/organ/internal/xenos/hivenode) in M.internal_organs)) + return attack_hand(user) + + switch(status) + if(BURST) + user << "\red You clear the hatched egg." del(src) + return + if(GROWING) + user << "\red The child is not developed yet." + return + if(GROWN) + user << "\red You retrieve the child." + Burst(0) + return - attack_paw(user as mob) - if(isalien(user)) - switch(status) - if(BURST) - user << "\red You clear the hatched egg." - del(src) - return - if(GROWING) - user << "\red The child is not developed yet." - return - if(GROWN) - user << "\red You retrieve the child." - Burst(0) - return - else - return attack_hand(user) +/obj/effect/alien/egg/proc/GetFacehugger() + return locate(/obj/item/clothing/mask/facehugger) in contents - attack_hand(user as mob) - user << "It feels slimy." - return +/obj/effect/alien/egg/proc/Grow() + icon_state = "egg" + status = GROWN + new /obj/item/clothing/mask/facehugger(src) + return - proc/GetFacehugger() - return locate(/obj/item/clothing/mask/facehugger) in contents - - proc/Grow() - icon_state = "egg" - status = GROWN - new /obj/item/clothing/mask/facehugger(src) - return - - proc/Burst(var/kill = 1) //drops and kills the hugger if any is remaining - if(status == GROWN || status == GROWING) - var/obj/item/clothing/mask/facehugger/child = GetFacehugger() - icon_state = "egg_hatched" - 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 +/obj/effect/alien/egg/proc/Burst(var/kill = 1) //drops and kills the hugger if any is remaining + if(status == GROWN || status == GROWING) + var/obj/item/clothing/mask/facehugger/child = GetFacehugger() + icon_state = "egg_hatched" + flick("egg_opening", src) + status = BURSTING + spawn(15) + status = BURST + child.loc = get_turf(src) + if(kill && istype(child)) + child.Die() + else + for(var/mob/M in range(1,src)) + if(CanHug(M)) + child.Attach(M) + break /obj/effect/alien/egg/bullet_act(var/obj/item/projectile/Proj) health -= Proj.damage diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index be54a95ba1..682347669a 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -174,7 +174,7 @@ if(prob(25)) src.visible_message("\blue \the [src] skitters[pick(" away"," around","")].") else if(prob(5)) - //ventcrawl! + //vent crawl! for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(7,src)) if(!v.welded) entry_vent = v diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 6e1cc86633..c7f8fadfcb 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -53,7 +53,7 @@ Works similarly to worn sprite_sheets, except the alternate sprites are used when the clothing/refit_for_species() proc is called. */ var/list/sprite_sheets_obj = null - + /obj/item/device icon = 'icons/obj/device.dmi' @@ -155,15 +155,6 @@ /obj/item/attack_paw(mob/user as mob) - if(isalien(user)) // -- TLE - var/mob/living/carbon/alien/A = user - - if(!A.has_fine_manipulation || w_class >= 4) - if(src in A.contents) // To stop Aliens having items stuck in their pockets - A.drop_from_inventory(src) - user << "Your claws aren't capable of such fine manipulation." - return - if (istype(src.loc, /obj/item/weapon/storage)) for(var/mob/M in range(1, src.loc)) if (M.s_active == src.loc) @@ -516,8 +507,8 @@ user << "\red You're going to need to remove the eye covering first." return - if(istype(M, /mob/living/carbon/alien) || istype(M, /mob/living/carbon/slime))//Aliens don't have eyes./N slimes also don't have eyes! - user << "\red You cannot locate any eyes on this creature!" + if(!M.has_eyes()) + user << "\red You cannot locate any eyes on [M]!" return user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" @@ -533,20 +524,22 @@ M.weakened += 4 M.adjustBruteLoss(10) */ - if(M != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [M] has been stabbed in the eye with [src] by [user].", 1) - M << "\red [user] stabs you in the eye with [src]!" - user << "\red You stab [M] in the eye with [src]!" - else - user.visible_message( \ - "\red [user] has stabbed themself with [src]!", \ - "\red You stab yourself in the eyes with [src]!" \ - ) + if(istype(M, /mob/living/carbon/human)) + var/datum/organ/internal/eyes/eyes = H.internal_organs_by_name["eyes"] - if(!eyes) - return + + if(M != user) + for(var/mob/O in (viewers(M) - user - M)) + O.show_message("\red [M] has been stabbed in the eye with [src] by [user].", 1) + M << "\red [user] stabs you in the eye with [src]!" + user << "\red You stab [M] in the eye with [src]!" + else + user.visible_message( \ + "\red [user] has stabbed themself with [src]!", \ + "\red You stab yourself in the eyes with [src]!" \ + ) + eyes.damage += rand(3,4) if(eyes.damage >= eyes.min_bruised_damage) if(M.stat != 2) diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index d3149ab90f..aa7e260371 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -173,7 +173,7 @@ REAGENT SCANNER // user.show_message("\blue Bloodstream Analysis located [M.reagents:get_reagent_amount("inaprovaline")] units of rejuvenation chemicals.") if (M.has_brain_worms()) user.show_message("\red Subject suffering from aberrant brain activity. Recommend further scanning.") - else if (M.getBrainLoss() >= 100 || istype(M, /mob/living/carbon/human) && M:brain_op_stage == 4.0) + else if (M.getBrainLoss() >= 100 || !M.has_brain()) user.show_message("\red Subject is brain dead.") else if (M.getBrainLoss() >= 60) user.show_message("\red Severe brain damage detected. Subject likely to have mental retardation.") diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm index dd60f16645..f5ad4fa9fd 100644 --- a/code/game/objects/items/weapons/grenades/flashbang.dm +++ b/code/game/objects/items/weapons/grenades/flashbang.dm @@ -20,7 +20,7 @@ var/damage = round(30/(get_dist(B,get_turf(src))+1)) B.health -= damage B.update_icon() - + new/obj/effect/effect/smoke/flashbang(src.loc) del(src) return @@ -84,7 +84,7 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M var/datum/organ/internal/eyes/E = H.internal_organs_by_name["eyes"] - if (E.damage >= E.min_bruised_damage) + if (E && E.damage >= E.min_bruised_damage) M << "\red Your eyes start to burn badly!" if(!banglet && !(istype(src , /obj/item/weapon/grenade/flashbang/clusterbang))) if (E.damage >= E.min_broken_damage) diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index c474650f9a..89e265aed8 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -498,9 +498,4 @@ the implant may become unstable and either pre-maturely inject the subject or si return 1 islegal() - return 0 - -/obj/item/weapon/implant/cortical - name = "cortical stack" - desc = "A fist-sized mass of biocircuits and chips." - icon_state = "implant_evil" + return 0 \ No newline at end of file diff --git a/code/game/objects/items/weapons/shards.dm b/code/game/objects/items/weapons/shards.dm index 1eeb6dff8d..0ecbe900d2 100644 --- a/code/game/objects/items/weapons/shards.dm +++ b/code/game/objects/items/weapons/shards.dm @@ -76,7 +76,7 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M - if(H.species.flags & IS_SYNTHETIC) + if(H.species.flags & IS_SYNTHETIC || H.species.insulated) return if( !H.shoes && ( !H.wear_suit || !(H.wear_suit.body_parts_covered & FEET) ) ) diff --git a/code/game/objects/items/weapons/storage/secure.dm b/code/game/objects/items/weapons/storage/secure.dm index a30168479a..635093436f 100644 --- a/code/game/objects/items/weapons/storage/secure.dm +++ b/code/game/objects/items/weapons/storage/secure.dm @@ -32,9 +32,6 @@ ..() usr << text("The service panel is [src.open ? "open" : "closed"].") - attack_alien(mob/user as mob) - return attack_hand(user) - attack_paw(mob/user as mob) return attack_hand(user) diff --git a/code/game/objects/items/weapons/surgery_tools.dm b/code/game/objects/items/weapons/surgery_tools.dm index ddadcfddd8..d9d7ec0126 100644 --- a/code/game/objects/items/weapons/surgery_tools.dm +++ b/code/game/objects/items/weapons/surgery_tools.dm @@ -21,106 +21,6 @@ w_class = 2.0 origin_tech = "materials=1;biotech=1" -/*HAHA, SUCK IT, 2000 LINES OF SPAGHETTI CODE! - -NOW YOUR JOB IOS DONE BY ONLY 500 LINES OF SPAGHETTI CODE! - -LOOK FOR SURGERY.DM*/ - -/* -/obj/item/weapon/retractor/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - if(!istype(M)) - return - - var/mob/living/carbon/human/H = M - if(istype(H) && ( \ - (H.head && H.head.flags & HEADCOVERSEYES) || \ - (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || \ - (H.glasses && H.glasses.flags & GLASSESCOVERSEYES) \ - )) - user << "\red You're going to need to remove that mask/helmet/glasses first." - return - - var/mob/living/carbon/monkey/Mo = M - if(istype(Mo) && ( \ - (Mo.wear_mask && Mo.wear_mask.flags & MASKCOVERSEYES) \ - )) - user << "\red You're going to need to remove that mask/helmet/glasses first." - return - - if(istype(M, /mob/living/carbon/alien) || istype(M, /mob/living/carbon/slime))//Aliens don't have eyes./N - user << "\red You cannot locate any eyes on this creature!" - return - - switch(M.eye_op_stage) - if(1.0) - if(M != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [M] is having his eyes retracted by [user].", 1) - M << "\red [user] begins to seperate your eyes with [src]!" - user << "\red You seperate [M]'s eyes with [src]!" - else - user.visible_message( \ - "\red [user] begins to have his eyes retracted.", \ - "\red You begin to pry open your eyes with [src]!" \ - ) - 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("head") - if(affecting.take_damage(15)) - M:UpdateDamageIcon() - M.updatehealth() - else - M.take_organ_damage(15) - - 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 ..() - - return -*/ - /* * Hemostat */ @@ -135,126 +35,6 @@ LOOK FOR SURGERY.DM*/ origin_tech = "materials=1;biotech=1" attack_verb = list("attacked", "pinched") -/* -/obj/item/weapon/hemostat/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - if(!istype(M)) - return - - if(!((locate(/obj/machinery/optable, M.loc) && M.resting) || (locate(/obj/structure/table/, M.loc) && M.lying && prob(50)))) - return ..() - - if(user.zone_sel.selecting == "groin") - if(istype(M, /mob/living/carbon/human)) - switch(M:appendix_op_stage) - if(1.0) - if(M != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [user] is beginning to clamp bleeders in [M]'s abdomen cut open with [src].", 1) - M << "\red [user] begins to clamp bleeders in your abdomen with [src]!" - user << "\red You clamp bleeders in [M]'s abdomen with [src]!" - M:appendix_op_stage = 2.0 - if(4.0) - if(M != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [user] is removing [M]'s appendix with [src].", 1) - M << "\red [user] begins to remove your appendix with [src]!" - user << "\red You remove [M]'s appendix with [src]!" - for(var/datum/disease/D in M.viruses) - if(istype(D, /datum/disease/appendicitis)) - new /obj/item/weapon/reagent_containers/food/snacks/appendix/inflamed(get_turf(M)) - M:appendix_op_stage = 5.0 - return - new /obj/item/weapon/reagent_containers/food/snacks/appendix(get_turf(M)) - M:appendix_op_stage = 5.0 - return - - if (user.zone_sel.selecting == "eyes") - - var/mob/living/carbon/human/H = M - if(istype(H) && ( \ - (H.head && H.head.flags & HEADCOVERSEYES) || \ - (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || \ - (H.glasses && H.glasses.flags & GLASSESCOVERSEYES) \ - )) - user << "\red You're going to need to remove that mask/helmet/glasses first." - return - - var/mob/living/carbon/monkey/Mo = M - if(istype(Mo) && ( \ - (Mo.wear_mask && Mo.wear_mask.flags & MASKCOVERSEYES) \ - )) - user << "\red You're going to need to remove that mask/helmet/glasses first." - return - - if(istype(M, /mob/living/carbon/alien))//Aliens don't have eyes./N - user << "\red You cannot locate any eyes on this creature!" - return - - switch(M.eye_op_stage) - if(2.0) - if(M != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [M] is having his eyes mended by [user].", 1) - M << "\red [user] begins to mend your eyes with [src]!" - user << "\red You mend [M]'s eyes with [src]!" - else - user.visible_message( \ - "\red [user] begins to have his eyes mended.", \ - "\red You begin to mend your eyes with [src]!" \ - ) - 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("head") - if(affecting.take_damage(15)) - M:UpdateDamageIcon() - M.updatehealth() - else - 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 ..() - - return -*/ - /* * Cautery */ @@ -269,81 +49,6 @@ LOOK FOR SURGERY.DM*/ origin_tech = "materials=1;biotech=1" attack_verb = list("burnt") -/* -/obj/item/weapon/cautery/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - if(!istype(M)) - return - - if(!((locate(/obj/machinery/optable, M.loc) && M.resting) || (locate(/obj/structure/table/, M.loc) && M.lying && prob(50)))) - return ..() - - if(user.zone_sel.selecting == "groin") - if(istype(M, /mob/living/carbon/human)) - switch(M:appendix_op_stage) - if(5.0) - if(M != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [user] is beginning to cauterize the incision in [M]'s abdomen with [src].", 1) - M << "\red [user] begins to cauterize the incision in your abdomen with [src]!" - user << "\red You cauterize the incision in [M]'s abdomen with [src]!" - M:appendix_op_stage = 6.0 - for(var/datum/disease/appendicitis in M.viruses) - appendicitis.cure() - return - - if (user.zone_sel.selecting == "eyes") - - var/mob/living/carbon/human/H = M - if(istype(H) && ( \ - (H.head && H.head.flags & HEADCOVERSEYES) || \ - (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || \ - (H.glasses && H.glasses.flags & GLASSESCOVERSEYES) \ - )) - user << "\red You're going to need to remove that mask/helmet/glasses first." - return - - var/mob/living/carbon/monkey/Mo = M - if(istype(Mo) && ( \ - (Mo.wear_mask && Mo.wear_mask.flags & MASKCOVERSEYES) \ - )) - user << "\red You're going to need to remove that mask/helmet/glasses first." - return - - if(istype(M, /mob/living/carbon/alien))//Aliens don't have eyes./N - user << "\red You cannot locate any eyes on this creature!" - return - - switch(M.eye_op_stage) - if(3.0) - if(M != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [M] is having his eyes cauterized by [user].", 1) - M << "\red [user] begins to cauterize your eyes!" - user << "\red You cauterize [M]'s eyes with [src]!" - else - user.visible_message( \ - "\red [user] begins to have his eyes cauterized.", \ - "\red You begin to cauterize your eyes!" \ - ) - 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("head") - if(affecting.take_damage(15)) - M:UpdateDamageIcon() - M.updatehealth() - else - M.take_organ_damage(15) - M.sdisabilities &= ~BLIND - M.eye_stat = 0 - M:eye_op_stage = 0.0 - - else if((!(user.zone_sel.selecting == "head")) || (!(user.zone_sel.selecting == "groin")) || (!(istype(M, /mob/living/carbon/human)))) - return ..() - - return -*/ - /* * Surgical Drill */ @@ -391,232 +96,6 @@ LOOK FOR SURGERY.DM*/ "\red [user] is slitting \his stomach open with the [src.name]! It looks like \he's trying to commit seppuku.") return (BRUTELOSS) -/* -/obj/item/weapon/scalpel/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - if(!istype(M)) - return ..() - - //if(M.mutations & HUSK) return ..() - - if((CLUMSY in user.mutations) && prob(50)) - M = user - return eyestab(M,user) - - if(!((locate(/obj/machinery/optable, M.loc) && M.resting) || (locate(/obj/structure/table/, M.loc) && M.lying && prob(50)))) - return ..() - - src.add_fingerprint(user) - - if(user.zone_sel.selecting == "groin") - if(istype(M, /mob/living/carbon/human)) - switch(M:appendix_op_stage) - if(0.0) - if(M != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [M] is beginning to have his abdomen cut open with [src] by [user].", 1) - M << "\red [user] begins to cut open your abdomen with [src]!" - user << "\red You cut [M]'s abdomen open with [src]!" - M:appendix_op_stage = 1.0 - if(3.0) - if(M != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [M] is beginning to have his appendix seperated with [src] by [user].", 1) - M << "\red [user] begins to seperate your appendix with [src]!" - user << "\red You seperate [M]'s appendix with [src]!" - M:appendix_op_stage = 4.0 - return - - if(user.zone_sel.selecting == "head" || istype(M, /mob/living/carbon/slime)) - - var/mob/living/carbon/human/H = M - if(istype(H) && ( \ - (H.head && H.head.flags & HEADCOVERSEYES) || \ - (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || \ - (H.glasses && H.glasses.flags & GLASSESCOVERSEYES) \ - )) - user << "\red You're going to need to remove that mask/helmet/glasses first." - return - - var/mob/living/carbon/monkey/Mo = M - if(istype(Mo) && ( \ - (Mo.wear_mask && Mo.wear_mask.flags & MASKCOVERSEYES) \ - )) - user << "\red You're going to need to remove that mask/helmet/glasses first." - return - - switch(M:brain_op_stage) - if(0.0) - if(istype(M, /mob/living/carbon/slime)) - if(M.stat == 2) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [M.name] is beginning to have its flesh cut open with [src] by [user].", 1) - M << "\red [user] begins to cut open your flesh with [src]!" - user << "\red You cut [M]'s flesh open with [src]!" - M:brain_op_stage = 1.0 - - return - - if(M != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [M] is beginning to have his head cut open with [src] by [user].", 1) - M << "\red [user] begins to cut open your head with [src]!" - user << "\red You cut [M]'s head open with [src]!" - else - user.visible_message( \ - "\red [user] begins to cut open his skull with [src]!", \ - "\red You begin to cut open your head with [src]!" \ - ) - - 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("head") - if(affecting.take_damage(15)) - M:UpdateDamageIcon() - else - M.take_organ_damage(15) - - if(istype(M, /mob/living/carbon/human)) - var/datum/organ/external/affecting = M:get_organ("head") - affecting.take_damage(7) - else - M.take_organ_damage(7) - - M.updatehealth() - M:brain_op_stage = 1.0 - - if(1) - if(istype(M, /mob/living/carbon/slime)) - if(M.stat == 2) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [M.name] is having its silky innards cut apart with [src] by [user].", 1) - M << "\red [user] begins to cut apart your innards with [src]!" - user << "\red You cut [M]'s silky innards apart with [src]!" - M:brain_op_stage = 2.0 - return - if(2.0) - if(istype(M, /mob/living/carbon/slime)) - if(M.stat == 2) - var/mob/living/carbon/slime/slime = M - if(slime.cores > 0) - if(istype(M, /mob/living/carbon/slime)) - user << "\red You attempt to remove [M]'s core, but [src] is ineffective!" - return - - if(M != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [M] is having his connections to the brain delicately severed with [src] by [user].", 1) - M << "\red [user] begins to cut open your head with [src]!" - user << "\red You cut [M]'s head open with [src]!" - else - user.visible_message( \ - "\red [user] begin to delicately remove the connections to his brain with [src]!", \ - "\red You begin to cut open your head with [src]!" \ - ) - if(M == user && prob(25)) - user << "\red You nick an artery!" - if(istype(M, /mob/living/carbon/human)) - var/datum/organ/external/affecting = M:get_organ("head") - if(affecting.take_damage(75)) - M:UpdateDamageIcon() - else - M.take_organ_damage(75) - - if(istype(M, /mob/living/carbon/human)) - var/datum/organ/external/affecting = M:get_organ("head") - affecting.take_damage(7) - else - M.take_organ_damage(7) - - M.updatehealth() - M:brain_op_stage = 3.0 - else - ..() - return - - else if(user.zone_sel.selecting == "eyes") - user << "\blue So far so good." - - var/mob/living/carbon/human/H = M - if(istype(H) && ( \ - (H.head && H.head.flags & HEADCOVERSEYES) || \ - (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || \ - (H.glasses && H.glasses.flags & GLASSESCOVERSEYES) \ - )) - user << "\red You're going to need to remove that mask/helmet/glasses first." - return - - var/mob/living/carbon/monkey/Mo = M - if(istype(Mo) && ( \ - (Mo.wear_mask && Mo.wear_mask.flags & MASKCOVERSEYES) \ - )) - user << "\red You're going to need to remove that mask/helmet/glasses first." - return - - if(istype(M, /mob/living/carbon/alien) || istype(M, /mob/living/carbon/slime))//Aliens don't have eyes./N - user << "\red You cannot locate any eyes on this creature!" - return - - switch(M:eye_op_stage) - if(0.0) - if(M != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [M] is beginning to have his eyes incised with [src] by [user].", 1) - M << "\red [user] begins to cut open your eyes with [src]!" - user << "\red You make an incision around [M]'s eyes with [src]!" - else - user.visible_message( \ - "\red [user] begins to cut around his eyes with [src]!", \ - "\red You begin to cut open your eyes with [src]!" \ - ) - 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("head") - if(affecting.take_damage(15)) - M:UpdateDamageIcon() - else - M.take_organ_damage(15) - - user << "\blue So far so good before." - 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 - else if((!(user.zone_sel.selecting == "head")) || (!(user.zone_sel.selecting == "groin")) || (!(istype(M, /mob/living/carbon/human)))) - return ..()*/ - return -*/ - /* * Researchable Scalpels */ @@ -667,157 +146,6 @@ LOOK FOR SURGERY.DM*/ sharp = 1 edge = 1 -/* -/obj/item/weapon/circular_saw/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - if(!istype(M)) - return ..() - - if((CLUMSY in user.mutations) && prob(50)) - M = user - return eyestab(M,user) - - if(!((locate(/obj/machinery/optable, M.loc) && M.resting) || (locate(/obj/structure/table/, M.loc) && M.lying && prob(50)))) - return ..() - - src.add_fingerprint(user) - - if(user.zone_sel.selecting == "head" || istype(M, /mob/living/carbon/slime)) - - var/mob/living/carbon/human/H = M - if(istype(H) && ( \ - (H.head && H.head.flags & HEADCOVERSEYES) || \ - (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || \ - (H.glasses && H.glasses.flags & GLASSESCOVERSEYES) \ - )) - user << "\red You're going to need to remove that mask/helmet/glasses first." - return - - var/mob/living/carbon/monkey/Mo = M - if(istype(Mo) && ( \ - (Mo.wear_mask && Mo.wear_mask.flags & MASKCOVERSEYES) \ - )) - user << "\red You're going to need to remove that mask/helmet/glasses first." - return - - switch(M:brain_op_stage) - if(1.0) - if(istype(M, /mob/living/carbon/slime)) - return - if(M != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [M] has his skull sawed open with [src] by [user].", 1) - M << "\red [user] begins to saw open your head with [src]!" - user << "\red You saw [M]'s head open with [src]!" - else - user.visible_message( \ - "\red [user] saws open his skull with [src]!", \ - "\red You begin to saw open your head with [src]!" \ - ) - 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("head") - if(affecting.take_damage(40)) - M:UpdateDamageIcon() - M.updatehealth() - else - M.take_organ_damage(40) - - if(istype(M, /mob/living/carbon/human)) - var/datum/organ/external/affecting = M:get_organ("head") - affecting.take_damage(7) - else - M.take_organ_damage(7) - - M.updatehealth() - M:brain_op_stage = 2.0 - - if(2.0) - if(istype(M, /mob/living/carbon/slime)) - if(M.stat == 2) - var/mob/living/carbon/slime/slime = M - if(slime.cores > 0) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [M.name] is having one of its cores sawed out with [src] by [user].", 1) - - slime.cores-- - M << "\red [user] begins to remove one of your cores with [src]! ([slime.cores] cores remaining)" - user << "\red You cut one of [M]'s cores out with [src]! ([slime.cores] cores remaining)" - - new slime.coretype(M.loc) - - if(slime.cores <= 0) - M.icon_state = "[slime.colour] baby slime dead-nocore" - - return - - if(3.0) - /*if(M.mind && M.mind.changeling) - user << "\red The neural tissue regrows before your eyes as you cut it." - return*/ - - if(M != user) - for(var/mob/O in (viewers(M) - user - M)) - O.show_message("\red [M] has his spine's connection to the brain severed with [src] by [user].", 1) - M << "\red [user] severs your brain's connection to the spine with [src]!" - user << "\red You sever [M]'s brain's connection to the spine with [src]!" - else - user.visible_message( \ - "\red [user] severs his brain's connection to the spine with [src]!", \ - "\red You sever your brain's connection to the spine with [src]!" \ - ) - - user.attack_log += "\[[time_stamp()]\] Debrained [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" - M.attack_log += "\[[time_stamp()]\] Debrained by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" - - log_attack("[user.name] ([user.ckey]) debrained [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])") - - - var/obj/item/brain/B = new(M.loc) - B.transfer_identity(M) - - M:brain_op_stage = 4.0 - M.death()//You want them to die after the brain was transferred, so not to trigger client death() twice. - - else - ..() - 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 ..() -/* - else if((!(user.zone_sel.selecting == "head")) || (!(user.zone_sel.selecting == "groin")) || (!(istype(M, /mob/living/carbon/human)))) - return ..() -*/ - return -*/ - //misc, formerly from code/defines/weapons.dm /obj/item/weapon/bonegel name = "bone gel" diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index f4400132e8..fdb6a93b2e 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -357,6 +357,8 @@ if(istype(user, /mob/living/carbon/human)) var/mob/living/carbon/human/H = user var/datum/organ/internal/eyes/E = H.internal_organs_by_name["eyes"] + if(!E) + return if(H.species.flags & IS_SYNTHETIC) return switch(safety) diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index af06f192bc..a79860522d 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -1,11 +1,46 @@ /obj/structure icon = 'icons/obj/structures.dmi' var/climbable + var/breakable + var/parts + +/obj/structure/proc/destroy() + if(parts) + new parts(loc) + density = 0 + del(src) + +/obj/structure/attack_hand(mob/user) + if(breakable) + if(HULK in user.mutations) + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + visible_message("[user] smashes the [src] apart!") + destroy() + else if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + if(H.species.can_shred(user)) + visible_message("[H] slices [src] apart!") + destroy() + +/obj/structure/attack_animal(mob/living/user) + if(breakable) + if(user.wall_smash) + visible_message("[user] smashes [src] apart!") + destroy() + +/obj/structure/attack_paw(mob/user) + if(breakable) attack_hand(user) /obj/structure/blob_act() if(prob(50)) del(src) +/obj/structure/meteorhit(obj/O as obj) + destroy(src) + +/obj/structure/attack_tk() + return + /obj/structure/ex_act(severity) switch(severity) if(1.0) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 0a30218400..637b762706 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -172,7 +172,7 @@ return -/obj/structure/closet/attack_animal(mob/living/simple_animal/user as mob) +/obj/structure/closet/attack_animal(mob/living/user as mob) if(user.wall_smash) visible_message("\red [user] destroys the [src]. ") for(var/atom/movable/A as mob|obj in src) diff --git a/code/game/objects/structures/extinguisher.dm b/code/game/objects/structures/extinguisher.dm index cfcc3c1176..3ba3c79a37 100644 --- a/code/game/objects/structures/extinguisher.dm +++ b/code/game/objects/structures/extinguisher.dm @@ -10,7 +10,7 @@ /obj/structure/extinguisher_cabinet/attackby(obj/item/O, mob/user) - if(isrobot(user) || isalien(user)) + if(isrobot(user)) return if(istype(O, /obj/item/weapon/extinguisher)) if(!has_extinguisher && opened) @@ -26,7 +26,7 @@ /obj/structure/extinguisher_cabinet/attack_hand(mob/user) - if(isrobot(user) || isalien(user)) + if(isrobot(user)) return if (hasorgans(user)) var/datum/organ/external/temp = user:organs_by_name["r_hand"] diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 630ed6687c..e1f0804c0e 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -31,32 +31,34 @@ attack_hand(user) /obj/structure/grille/attack_hand(mob/user as mob) + playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) - user.visible_message("[user] kicks [src].", \ + + var/damage_dealt + if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + if(H.species.can_shred(H)) + damage_dealt = 5 + user.visible_message("[user] mangles [src].", \ + "You mangle [src].", \ + "You hear twisting metal.") + + if(!damage_dealt) + user.visible_message("[user] kicks [src].", \ "You kick [src].", \ "You hear twisting metal.") if(shock(user, 70)) return + if(HULK in user.mutations) - health -= 5 + damage_dealt += 5 else - health -= 1 + damage_dealt += 1 + + health -= damage_dealt healthcheck() -/obj/structure/grille/attack_alien(mob/user as mob) - if(istype(user, /mob/living/carbon/alien/larva)) return - - playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) - user.visible_message("[user] mangles [src].", \ - "You mangle [src].", \ - "You hear twisting metal.") - - if(!shock(user, 70)) - health -= 5 - healthcheck() - return - /obj/structure/grille/attack_slime(mob/user as mob) var/mob/living/carbon/slime/S = user if (!S.is_adult) @@ -199,6 +201,7 @@ // returns 1 if shocked, 0 otherwise /obj/structure/grille/proc/shock(mob/user as mob, prb) + if(!anchored || destroyed) // anchored/destroyed grilles are never connected return 0 if(!prob(prb)) diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm index cd9dfd3e8a..8b586c9461 100644 --- a/code/game/objects/structures/inflatable.dm +++ b/code/game/objects/structures/inflatable.dm @@ -83,7 +83,7 @@ return - proc/attack_generic(mob/user as mob, damage = 0) //used by attack_alien, attack_animal, and attack_slime + proc/attack_generic(mob/user as mob, damage = 0) //used by attack_animal and attack_slime health -= damage if(health <= 0) user.visible_message("[user] tears open [src]!") @@ -91,10 +91,6 @@ else //for nicer text~ user.visible_message("[user] tears at [src]!") - attack_alien(mob/user as mob) - if(islarva(user)) return - attack_generic(user, 15) - attack_animal(mob/user as mob) if(!isanimal(user)) return var/mob/living/simple_animal/M = user diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm index 4902b6a631..aa07d1621a 100644 --- a/code/game/objects/structures/mineral_doors.dm +++ b/code/game/objects/structures/mineral_doors.dm @@ -256,7 +256,9 @@ var/close_delay = 100 TryToSwitchState(atom/user) - if(isalien(user)) + + var/mob/living/carbon/M = user + if(istype(M) && locate(/datum/organ/internal/xenos/hivenode) in M.internal_organs) return ..() Open() diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 5977121973..f9b45a6075 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -10,11 +10,23 @@ /obj/structure/mirror/attack_hand(mob/user as mob) + if(shattered) return if(ishuman(user)) var/mob/living/carbon/human/H = user + if(H.a_intent == "hurt") + if(shattered) + playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + return + if(prob(30) || H.species.can_shred(H)) + user.visible_message("[user] smashes [src]!") + shatter() + else + user.visible_message("[user] hits [src] and bounces off!") + return + var/userloc = H.loc //see code/modules/mob/new_player/preferences.dm at approx line 545 for comments! @@ -83,16 +95,6 @@ visible_message("[user] hits [src] with [I]!") playsound(src.loc, 'sound/effects/Glasshit.ogg', 70, 1) - -/obj/structure/mirror/attack_alien(mob/user as mob) - if(islarva(user)) return - if(shattered) - playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) - return - user.visible_message("[user] smashes [src]!") - shatter() - - /obj/structure/mirror/attack_animal(mob/user as mob) if(!isanimal(user)) return var/mob/living/simple_animal/M = user diff --git a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm index f215123b27..3c5bbfc1ca 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/alien_nests.dm @@ -32,15 +32,20 @@ return /obj/structure/stool/bed/nest/buckle_mob(mob/M as mob, mob/user as mob) + if ( !ismob(M) || (get_dist(src, user) > 1) || (M.loc != src.loc) || user.restrained() || usr.stat || M.buckled || istype(user, /mob/living/silicon/pai) ) return - if(istype(M,/mob/living/carbon/alien)) - return - if(!istype(user,/mob/living/carbon/alien/humanoid)) + unbuckle() + + var/mob/living/carbon/xenos = user + var/mob/living/carbon/victim = M + + if(istype(victim) && locate(/datum/organ/internal/xenos/hivenode) in victim.internal_organs) return - unbuckle() + if(istype(xenos) && !(locate(/datum/organ/internal/xenos/hivenode) in xenos.internal_organs)) + return if(M == usr) return diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index d3463b1e7e..90e639c737 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -20,8 +20,9 @@ layer = 2.8 throwpass = 1 //You can throw objects over this, despite it's density.") climbable = 1 + breakable = 1 + parts = /obj/item/weapon/table_parts - var/parts = /obj/item/weapon/table_parts var/flipped = 0 var/health = 100 @@ -43,16 +44,6 @@ update_adjacent() ..() -/obj/structure/table/proc/destroy() - new parts(loc) - density = 0 - del(src) - -/obj/structure/rack/proc/destroy() - new parts(loc) - density = 0 - del(src) - /obj/structure/table/update_icon() spawn(2) //So it properly updates when deleting @@ -263,49 +254,6 @@ else dir = 2 -/obj/structure/table/ex_act(severity) - switch(severity) - if(1.0) - del(src) - return - if(2.0) - if (prob(50)) - del(src) - return - if(3.0) - if (prob(25)) - destroy() - else - return - - -/obj/structure/table/blob_act() - if(prob(75)) - destroy() - -/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 [src] apart!") - destroy() - - -/obj/structure/table/attack_alien(mob/user) - visible_message("[user] slices [src] apart!") - -/obj/structure/table/attack_animal(mob/living/simple_animal/user) - if(user.wall_smash) - visible_message("[user] smashes [src] apart!") - destroy() - - - -/obj/structure/table/attack_hand(mob/user) - if(HULK in user.mutations) - visible_message("[user] smashes [src] apart!") - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - destroy() - /obj/structure/table/attack_tk() // no telehulk sorry return @@ -601,29 +549,9 @@ flags = FPRINT anchored = 1.0 throwpass = 1 //You can throw objects over this, despite it's density. - var/parts = /obj/item/weapon/rack_parts - -/obj/structure/rack/ex_act(severity) - switch(severity) - if(1.0) - del(src) - if(2.0) - del(src) - if(prob(50)) - new /obj/item/weapon/rack_parts(src.loc) - if(3.0) - if(prob(25)) - del(src) - new /obj/item/weapon/rack_parts(src.loc) - -/obj/structure/rack/blob_act() - if(prob(75)) - del(src) - return - else if(prob(50)) - new /obj/item/weapon/rack_parts(src.loc) - del(src) - return + breakable = 1 + climbable = 1 + parts = /obj/item/weapon/rack_parts /obj/structure/rack/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) if(air_group || (height==0)) return 1 @@ -654,32 +582,4 @@ return user.drop_item() if(W && W.loc) W.loc = src.loc - return - -/obj/structure/rack/meteorhit(obj/O as obj) - del(src) - - -/obj/structure/table/attack_hand(mob/user) - if(HULK in user.mutations) - visible_message("[user] smashes [src] apart!") - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - destroy() - -/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!") - destroy() - -/obj/structure/rack/attack_alien(mob/user) - visible_message("[user] slices [src] apart!") - destroy() - -/obj/structure/rack/attack_animal(mob/living/simple_animal/user) - if(user.wall_smash) - visible_message("[user] smashes [src] apart!") - destroy() - -/obj/structure/rack/attack_tk() // no telehulk sorry return \ No newline at end of file diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 7052bf5a98..cad2907ac7 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -114,6 +114,14 @@ new /obj/item/weapon/shard(loc) if(reinf) new /obj/item/stack/rods(loc) del(src) + else if (istype(usr,/mob/living/carbon/human)) + + var/mob/living/carbon/human/H = usr + + if(H.species.can_shred(H)) + attack_generic(H,25) + return + else if (usr.a_intent == "hurt") playsound(src.loc, 'sound/effects/glassknock.ogg', 80, 1) usr.visible_message("\red [usr.name] bangs against the [src.name]!", \ @@ -131,7 +139,7 @@ return attack_hand(user) -/obj/structure/window/proc/attack_generic(mob/user as mob, damage = 0) //used by attack_alien, attack_animal, and attack_slime +/obj/structure/window/proc/attack_generic(mob/user as mob, damage = 0) //used by attack_animal and attack_slime health -= damage if(health <= 0) user.visible_message("[user] smashes through [src]!") @@ -142,11 +150,6 @@ user.visible_message("[user] smashes into [src]!") playsound(loc, 'sound/effects/Glasshit.ogg', 100, 1) - -/obj/structure/window/attack_alien(mob/user as mob) - if(islarva(user)) return - attack_generic(user, 15) - /obj/structure/window/attack_animal(mob/user as mob) if(!isanimal(user)) return var/mob/living/simple_animal/M = user diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 19223c48f1..42a63f26e5 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -153,50 +153,16 @@ B.virus2 = virus_copylist(M.virus2) return 1 //we bloodied the floor - - - //if there isn't a blood decal already, make one. - var/obj/effect/decal/cleanable/blood/newblood = new /obj/effect/decal/cleanable/blood(src) - - //Species-specific blood. - if(M.species) - newblood.basecolor = M.species.blood_color - else - newblood.basecolor = "#A10808" - - newblood.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type - newblood.virus2 = virus_copylist(M.virus2) - newblood.update_icon() - + blood_splatter(src,M.get_blood(M.vessel),1) return 1 //we bloodied the floor // Only adds blood on the floor -- Skie /turf/simulated/proc/add_blood_floor(mob/living/carbon/M as mob) if(istype(M, /mob/living/carbon/monkey)) - - var/obj/effect/decal/cleanable/blood/this = new /obj/effect/decal/cleanable/blood(src) - this.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type - this.basecolor = "#A10808" - this.update_icon() - - else if(istype(M,/mob/living/carbon/human)) - - var/obj/effect/decal/cleanable/blood/this = new /obj/effect/decal/cleanable/blood(src) - var/mob/living/carbon/human/H = M - - //Species-specific blood. - if(H.species) - this.basecolor = H.species.blood_color - else - this.basecolor = "#A10808" - this.update_icon() - - this.blood_DNA[M.dna.unique_enzymes] = M.dna.b_type - + blood_splatter(src,M,1) else if( istype(M, /mob/living/carbon/alien )) var/obj/effect/decal/cleanable/blood/xeno/this = new /obj/effect/decal/cleanable/blood/xeno(src) this.blood_DNA["UNKNOWN BLOOD"] = "X*" - else if( istype(M, /mob/living/silicon/robot )) new /obj/effect/decal/cleanable/blood/oil(src) diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index d264f8375d..b654aeadaf 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -242,7 +242,7 @@ return src.attack_hand(user) -/turf/simulated/wall/attack_animal(mob/living/simple_animal/M as mob) +/turf/simulated/wall/attack_animal(mob/living/M as mob) if(M.wall_smash) if (istype(src, /turf/simulated/wall/r_wall) && !rotting) M << text("\blue This wall is far too strong for you to destroy.") diff --git a/code/game/verbs/suicide.dm b/code/game/verbs/suicide.dm index ee37b5eb9c..82a81e5af7 100644 --- a/code/game/verbs/suicide.dm +++ b/code/game/verbs/suicide.dm @@ -191,27 +191,6 @@ else src << "Aborting suicide attempt." -/mob/living/carbon/alien/humanoid/verb/suicide() - set hidden = 1 - - if (stat == 2) - src << "You're already dead!" - return - - if (suiciding) - src << "You're already committing suicide! Be patient!" - return - - var/confirm = alert("Are you sure you want to commit suicide?", "Confirm Suicide", "Yes", "No") - - if(confirm == "Yes") - suiciding = 1 - viewers(src) << "\red [src] is thrashing wildly! It looks like \he's trying to commit suicide." - //put em at -175 - adjustOxyLoss(max(175 - getFireLoss() - getBruteLoss() - getOxyLoss(), 0)) - updatehealth() - - /mob/living/carbon/slime/verb/suicide() set hidden = 1 if (stat == 2) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 12b5bf7789..5b369dc9f4 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -141,12 +141,18 @@ var/global/floorIsLava = 0 body += {"

Rudimentary transformation:
These transformations only create a new mob type and copy stuff over. They do not take into account MMIs and similar mob-specific things. The buttons in 'Transformations' are preferred, when possible.

Observer | - \[ Alien: Drone, - Hunter, - Queen, - Sentinel, - Larva \] - Human + \[ Xenos: Larva + Drone + Hunter + Sentinel + Queen \] | + \[ Crew: Human + Unathi + Tajaran + Skrell + Vox \] | \[ + Nymph + Diona \] | \[ slime: Baby, Adult \] Monkey | diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index 0a83ce4903..a5ccbb9100 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -233,11 +233,8 @@ M_job = "slime" else if(ismonkey(M)) M_job = "Monkey" - else if(isalien(M)) //aliens - if(islarva(M)) - M_job = "Alien larva" - else - M_job = "Alien" + else if(isalien(M)) + M_job = "Alien" else M_job = "Carbon-based" diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 1493751ab1..2e087971bc 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -267,6 +267,7 @@ href_list["secretsadmin"] = "check_antagonist" else if(href_list["simplemake"]) + if(!check_rights(R_SPAWN)) return var/mob/M = locate(href_list["mob"]) @@ -284,13 +285,10 @@ switch(href_list["simplemake"]) if("observer") M.change_mob_type( /mob/dead/observer , null, null, delmob ) - if("drone") M.change_mob_type( /mob/living/carbon/alien/humanoid/drone , null, null, delmob ) - if("hunter") M.change_mob_type( /mob/living/carbon/alien/humanoid/hunter , null, null, delmob ) - if("queen") M.change_mob_type( /mob/living/carbon/alien/humanoid/queen , null, null, delmob ) - if("sentinel") M.change_mob_type( /mob/living/carbon/alien/humanoid/sentinel , null, null, delmob ) if("larva") M.change_mob_type( /mob/living/carbon/alien/larva , null, null, delmob ) - if("human") M.change_mob_type( /mob/living/carbon/human , null, null, delmob ) - if("slime") M.change_mob_type( /mob/living/carbon/slime , null, null, delmob ) + if("nymph") M.change_mob_type( /mob/living/carbon/alien/diona , null, null, delmob ) + if("human") M.change_mob_type( /mob/living/carbon/human , null, null, delmob, href_list["species"]) + if("slime") M.change_mob_type( /mob/living/carbon/slime , null, null, delmob ) if("monkey") M.change_mob_type( /mob/living/carbon/monkey , null, null, delmob ) if("robot") M.change_mob_type( /mob/living/silicon/robot , null, null, delmob ) if("cat") M.change_mob_type( /mob/living/simple_animal/cat , null, null, delmob ) @@ -2205,11 +2203,6 @@ if(aliens_allowed) new /datum/event/alien_infestation message_admins("[key_name_admin(usr)] has spawned aliens", 1) - if("alien_silent") //replaces the spawn_xeno verb - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","ALS") - if(aliens_allowed) - create_xeno() if("spiders") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","SL") diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 95fbc615c8..18fcee188b 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -517,24 +517,11 @@ client/proc/one_click_antag() new_vox.mind.special_role = "Vox Raider" new_vox.mutations |= NOCLONE //Stops the station crew from messing around with their DNA. - //Now apply cortical stack. - var/datum/organ/external/affected = new_vox.get_organ("head") - - //To avoid duplicates. - for(var/obj/item/weapon/implant/cortical/imp in new_vox.contents) - affected.implants -= imp - del(imp) - - var/obj/item/weapon/implant/cortical/I = new(new_vox) - I.imp_in = new_vox - I.implanted = 1 - affected.implants += I - I.part = affected - if(ticker.mode && ( istype( ticker.mode,/datum/game_mode/heist ) ) ) var/datum/game_mode/heist/M = ticker.mode - cortical_stacks += I - M.raiders[new_vox.mind] = I + if(new_vox.internal_organs_by_name["stack"]) + cortical_stacks |= new_vox.internal_organs_by_name["stack"] + M.raiders[new_vox.mind] = new_vox.internal_organs_by_name["stack"] ticker.mode.traitors += new_vox.mind new_vox.equip_vox_raider() diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index ce2a2800bb..a0e9fd9878 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -225,38 +225,6 @@ proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0) IonStorm(0) feedback_add_details("admin_verb","ION") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -//I use this proc for respawn character too. /N -/proc/create_xeno(ckey) - if(!ckey) - var/list/candidates = list() - for(var/mob/M in player_list) - if(M.stat != DEAD) continue //we are not dead! - if(!M.client.prefs.be_special & BE_ALIEN) continue //we don't want to be an alium - if(M.client.is_afk()) continue //we are afk - if(M.mind && M.mind.current && M.mind.current.stat != DEAD) continue //we have a live body we are tied to - candidates += M.ckey - if(candidates.len) - ckey = input("Pick the player you want to respawn as a xeno.", "Suitable Candidates") as null|anything in candidates - else - usr << "Error: create_xeno(): no suitable candidates." - if(!istext(ckey)) return 0 - - var/alien_caste = input(usr, "Please choose which caste to spawn.","Pick a caste",null) as null|anything in list("Queen","Hunter","Sentinel","Drone","Larva") - var/obj/effect/landmark/spawn_here = xeno_spawn.len ? pick(xeno_spawn) : pick(latejoin) - var/mob/living/carbon/alien/new_xeno - switch(alien_caste) - if("Queen") new_xeno = new /mob/living/carbon/alien/humanoid/queen(spawn_here) - if("Hunter") new_xeno = new /mob/living/carbon/alien/humanoid/hunter(spawn_here) - if("Sentinel") new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(spawn_here) - if("Drone") new_xeno = new /mob/living/carbon/alien/humanoid/drone(spawn_here) - if("Larva") new_xeno = new /mob/living/carbon/alien/larva(spawn_here) - else return 0 - - new_xeno.ckey = ckey - message_admins("\blue [key_name_admin(usr)] has spawned [ckey] as a filthy xeno [alien_caste].", 1) - return 1 - /* Allow admins to set players to be able to respawn/bypass 30 min wait, without the admin having to edit variables directly Ccomp's first proc. @@ -376,9 +344,6 @@ Ccomp's first proc. log_admin("[key_name(usr)] has [action] on joining the round if they use AntagHUD") message_admins("Admin [key_name_admin(usr)] has [action] on joining the round if they use AntagHUD", 1) - - - /* If a guy was gibbed and you want to revive him, this is a good way to do so. Works kind of like entering the game with a new character. Character receives a new mind if they didn't have one. @@ -406,32 +371,9 @@ Traitors and the like can also be revived with the previous role mostly intact. return if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something - //Check if they were an alien - if(G_found.mind.assigned_role=="Alien") - if(alert("This character appears to have been an alien. Would you like to respawn them as such?",,"Yes","No")=="Yes") - var/turf/T - if(xeno_spawn.len) T = pick(xeno_spawn) - else T = pick(latejoin) - - var/mob/living/carbon/alien/new_xeno - switch(G_found.mind.special_role)//If they have a mind, we can determine which caste they were. - if("Hunter") new_xeno = new /mob/living/carbon/alien/humanoid/hunter(T) - if("Sentinel") new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(T) - if("Drone") new_xeno = new /mob/living/carbon/alien/humanoid/drone(T) - if("Queen") new_xeno = new /mob/living/carbon/alien/humanoid/queen(T) - else//If we don't know what special role they have, for whatever reason, or they're a larva. - create_xeno(G_found.ckey) - return - - //Now to give them their mind back. - G_found.mind.transfer_to(new_xeno) //be careful when doing stuff like this! I've already checked the mind isn't in use - new_xeno.key = G_found.key - new_xeno << "You have been fully respawned. Enjoy the game." - message_admins("\blue [key_name_admin(usr)] has respawned [new_xeno.key] as a filthy xeno.", 1) - return //all done. The ghost is auto-deleted //check if they were a monkey - else if(findtext(G_found.real_name,"monkey")) + if(findtext(G_found.real_name,"monkey")) if(alert("This character appears to have been a monkey. Would you like to respawn them as such?",,"Yes","No")=="Yes") var/mob/living/carbon/monkey/new_monkey = new(pick(latejoin)) G_found.mind.transfer_to(new_monkey) //be careful when doing stuff like this! I've already checked the mind isn't in use @@ -440,8 +382,7 @@ Traitors and the like can also be revived with the previous role mostly intact. message_admins("\blue [key_name_admin(usr)] has respawned [new_monkey.key] as a filthy xeno.", 1) return //all done. The ghost is auto-deleted - - //Ok, it's not a xeno or a monkey. So, spawn a human. + //Ok, it's not a monkey. So, spawn a human. var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned. var/datum/data/record/record_found //Referenced to later to either randomize or not randomize the character. diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 193d63f96c..119076e6a8 100755 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -1580,6 +1580,9 @@ datum/preferences var/datum/organ/internal/I = character.internal_organs_by_name[name] var/status = organ_data[name] + if(!I || !O) + continue + if(status == "amputated") O.amputated = 1 O.status |= ORGAN_DESTROYED diff --git a/code/modules/food/recipes_microwave.dm b/code/modules/food/recipes_microwave.dm index 9518394916..fdd28f5bcc 100644 --- a/code/modules/food/recipes_microwave.dm +++ b/code/modules/food/recipes_microwave.dm @@ -135,7 +135,7 @@ I said no! /datum/recipe/brainburger items = list( /obj/item/weapon/reagent_containers/food/snacks/bun, - /obj/item/brain + /obj/item/organ/brain ) result = /obj/item/weapon/reagent_containers/food/snacks/brainburger @@ -1063,7 +1063,7 @@ I said no! /obj/item/weapon/reagent_containers/food/snacks/egg, /obj/item/weapon/reagent_containers/food/snacks/egg, /obj/item/weapon/reagent_containers/food/snacks/egg, - /obj/item/brain + /obj/item/organ/brain ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/braincake diff --git a/code/modules/hydroponics/seed_datums.dm b/code/modules/hydroponics/seed_datums.dm index 51a8fb499e..7b6710f6c4 100644 --- a/code/modules/hydroponics/seed_datums.dm +++ b/code/modules/hydroponics/seed_datums.dm @@ -1499,7 +1499,7 @@ proc/populate_seed_list() seed_noun = "nodes" display_name = "replicant pods" packet_icon = "seed-replicapod" - products = list(/mob/living/carbon/monkey/diona) + products = list(/mob/living/carbon/alien/diona) plant_icon = "replicapod" product_requires_player = 1 immutable = 1 diff --git a/code/modules/hydroponics/seed_mobs.dm b/code/modules/hydroponics/seed_mobs.dm index 0bb301298a..d80247abd6 100644 --- a/code/modules/hydroponics/seed_mobs.dm +++ b/code/modules/hydroponics/seed_mobs.dm @@ -69,7 +69,7 @@ host << "\green You awaken slowly, stirring into sluggish motion as the air caresses you." // This is a hack, replace with some kind of species blurb proc. - if(istype(host,/mob/living/carbon/monkey/diona)) + if(istype(host,/mob/living/carbon/alien/diona)) host << "You are [host], one of a race of drifting interstellar plantlike creatures that sometimes share their seeds with human traders." host << "Too much darkness will send you into shock and starve you, but light will help you heal." diff --git a/code/modules/mob/abilities.dm b/code/modules/mob/abilities.dm deleted file mode 100644 index e5e2be9af0..0000000000 --- a/code/modules/mob/abilities.dm +++ /dev/null @@ -1,35 +0,0 @@ -/* -Creature-level abilities. -*/ - -/var/global/list/ability_verbs = list( ) - -/* - - Example ability: - -/client/proc/test_ability() - - set category = "Ability" - set name = "Test ability" - set desc = "An ability for testing." - - // Check if the client has a mob and if the mob is valid and alive. - if(!mob || !istype(mob,/mob/living) || mob.stat) - src << "\red You must be corporeal and alive to do that." - return 0 - - //Handcuff check. - if(mob.restrained()) - src << "\red You cannot do this while restrained." - return 0 - - if(istype(mob,/mob/living/carbon)) - var/mob/living/carbon/M = mob - if(M.handcuffed) - src << "\red You cannot do this while cuffed." - return 0 - - src << "\blue You perform an ability." - -*/ \ No newline at end of file diff --git a/code/modules/mob/death.dm b/code/modules/mob/death.dm index 797715c33e..dc1ca25727 100644 --- a/code/modules/mob/death.dm +++ b/code/modules/mob/death.dm @@ -56,6 +56,8 @@ timeofdeath = world.time + var/tod = worldtime2text() //weasellos time of death patch + if(mind) mind.store_memory("Time of death: [tod]", 0) living_mob_list -= src dead_mob_list += src return ..(gibbed) diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm index d54e1a90e7..383d20ff18 100755 --- a/code/modules/mob/language.dm +++ b/code/modules/mob/language.dm @@ -12,6 +12,23 @@ var/flags = 0 // Various language flags. var/native // If set, non-native speakers will have trouble speaking. +/datum/language/proc/broadcast(var/mob/living/speaker,var/message,var/speaker_mask) + + log_say("[key_name(speaker)] : ([name]) [message]") + + for(var/mob/player in player_list) + + var/understood = 0 + + if(istype(player,/mob/dead)) + understood = 1 + else if(src in player.languages) + understood = 1 + + if(understood) + if(!speaker_mask) speaker_mask = speaker.name + player << "[name], [speaker_mask] [speech_verb], \"[message]\"" + /datum/language/unathi name = "Sinta'unathi" desc = "The common language of Moghes, composed of sibilant hisses and rattles. Spoken natively by Unathi." @@ -74,6 +91,103 @@ colour = "rough" key = "3" +/datum/language/xenos + name = "Hivemind" + desc = "Xenomorphs have the strange ability to commune over a psychic hivemind." + speech_verb = "hisses" + colour = "alien" + key = "a" + flags = RESTRICTED | HIVEMIND + +/datum/language/ling + name = "Changeling" + desc = "Although they are normally wary and suspicious of each other, changelings can commune over a distance." + speech_verb = "says" + colour = "changeling" + key = "g" + flags = RESTRICTED | HIVEMIND + +/datum/language/ling/broadcast(var/mob/living/speaker,var/message,var/speaker_mask) + + if(speaker.mind && speaker.mind.changeling) + ..(speaker,message,speaker.mind.changeling.changelingID) + else + ..(speaker,message) + +/datum/language/corticalborer + name = "Cortical Link" + desc = "Cortical borers possess a strange between their tiny minds." + speech_verb = "sings" + colour = "alien" + key = "x" + flags = RESTRICTED | HIVEMIND + +/datum/language/corticalborer/broadcast(var/mob/living/speaker,var/message,var/speaker_mask) + + var/mob/living/simple_animal/borer/B + + if(istype(speaker,/mob/living/carbon)) + var/mob/living/carbon/M = speaker + B = M.has_brain_worms() + else if(istype(speaker,/mob/living/simple_animal/borer)) + B = speaker + + if(B) + speaker_mask = B.truename + ..(speaker,message,speaker_mask) + +/datum/language/binary + name = "Robot Talk" + desc = "Most human stations support free-use communications protocols and routing hubs for synthetic use." + speech_verb = "transmits" + colour = "say_quote" + key = "b" + flags = RESTRICTED | HIVEMIND + var/drone_only + +/datum/language/binary/broadcast(var/mob/living/speaker,var/message,var/speaker_mask) + + if(!speaker.binarycheck()) + return + + if (!message) + return + + var/message_start = "[name], [speaker.name]" + var/message_body = "[speaker.say_quote(message)], \"[message]\"" + + for (var/mob/M in dead_mob_list) + if(!istype(M,/mob/new_player) && !istype(M,/mob/living/carbon/brain)) //No meta-evesdropping + M.show_message("[message_start] [message_body]", 2) + + for (var/mob/living/S in living_mob_list) + + if(drone_only && !istype(S,/mob/living/silicon/robot/drone)) + continue + else if(istype(S , /mob/living/silicon/ai)) + message_start = "[name], [speaker.name]" + else if (!S.binarycheck()) + continue + + S.show_message("[message_start] [message_body]", 2) + + var/list/listening = hearers(1, src) + listening -= src + + for (var/mob/living/M in listening) + if(istype(M, /mob/living/silicon) || M.binarycheck()) + continue + M.show_message("synthesised voice beeps, \"beep beep beep\"",2) + +/datum/language/binary/drone + name = "Drone Talk" + desc = "A heavily encoded damage control coordination stream." + speech_verb = "transmits" + colour = "say_quote" + key = "d" + flags = RESTRICTED | HIVEMIND + drone_only = 1 + // Language handling. /mob/proc/add_language(var/language) diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 23d5416fca..5d48ec1f3c 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -1,207 +1,60 @@ -#define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point -#define HEAT_DAMAGE_LEVEL_2 4 //Amount of damage applied when your body temperature passes the 400K point -#define HEAT_DAMAGE_LEVEL_3 8 //Amount of damage applied when your body temperature passes the 1000K point - /mob/living/carbon/alien + name = "alien" - voice_name = "alien" - speak_emote = list("hisses") + desc = "What IS that?" icon = 'icons/mob/alien.dmi' + icon_state = "alien" + pass_flags = PASSTABLE + melee_damage_lower = 1 + melee_damage_upper = 3 + attacktext = "bites" + attack_sound = null + friendly = "nuzzles" + wall_smash = 0 + health = 100 + maxHealth = 100 + + var/adult_form + var/dead_icon + var/amount_grown = 0 + var/max_grown = 10 + var/time_of_birth + var/language + +/mob/living/carbon/alien/New() + + time_of_birth = world.time + + verbs += /mob/living/proc/ventcrawl + verbs += /mob/living/proc/hide + + var/datum/reagents/R = new/datum/reagents(100) + reagents = R + R.my_atom = src + + name = "[initial(name)] ([rand(1, 1000)])" + real_name = name + regenerate_icons() + + if(language) + add_language(language) + gender = NEUTER - dna = null - - var/storedPlasma = 250 - var/max_plasma = 500 - - alien_talk_understand = 1 - - var/obj/item/weapon/card/id/wear_id = null // Fix for station bounced radios -- Skie - var/has_fine_manipulation = 0 - - var/move_delay_add = 0 // movement delay to add - - status_flags = CANPARALYSE|CANPUSH - var/heal_rate = 1 - var/plasma_rate = 5 - - var/oxygen_alert = 0 - var/phoron_alert = 0 - var/fire_alert = 0 - - var/heat_protection = 0.5 - -/mob/living/carbon/alien/adjustToxLoss(amount) - storedPlasma = min(max(storedPlasma + amount,0),max_plasma) //upper limit of max_plasma, lower limit of 0 - return - -/mob/living/carbon/alien/adjustFireLoss(amount) // Weak to Fire - if(amount > 0) - ..(amount * 2) - else - ..(amount) - return - -/mob/living/carbon/alien/proc/getPlasma() - return storedPlasma - -/mob/living/carbon/alien/eyecheck() - return 2 - -/mob/living/carbon/alien/updatehealth() - if(status_flags & GODMODE) - health = maxHealth - stat = CONSCIOUS - else - //oxyloss is only used for suicide - //toxloss isn't used for aliens, its actually used as alien powers!! - health = maxHealth - getOxyLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() - -/mob/living/carbon/alien/proc/handle_environment(var/datum/gas_mixture/environment) - - //If there are alien weeds on the ground then heal if needed or give some plasma - if(locate(/obj/effect/alien/weeds) in loc) - if(health >= maxHealth - getCloneLoss()) - adjustToxLoss(plasma_rate) - else - adjustBruteLoss(-heal_rate) - adjustFireLoss(-heal_rate) - adjustOxyLoss(-heal_rate) - - if(!environment) - return - var/loc_temp = T0C - if(istype(loc, /obj/mecha)) - var/obj/mecha/M = loc - loc_temp = M.return_temperature() - else if(istype(get_turf(src), /turf/space)) - var/turf/heat_turf = get_turf(src) - loc_temp = heat_turf.temperature - else if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) - loc_temp = loc:air_contents.temperature - else - loc_temp = environment.temperature - - //world << "Loc temp: [loc_temp] - Body temp: [bodytemperature] - Fireloss: [getFireLoss()] - Fire protection: [heat_protection] - Location: [loc] - src: [src]" - - // Aliens are now weak to fire. - - //After then, it reacts to the surrounding atmosphere based on your thermal protection - if(loc_temp > bodytemperature) - //Place is hotter than we are - var/thermal_protection = heat_protection //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to. - if(thermal_protection < 1) - bodytemperature += (1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR) - else - bodytemperature += 1 * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR) - // bodytemperature -= max((loc_temp - bodytemperature / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM) - - // +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt. - if(bodytemperature > 360.15) - //Body temperature is too hot. - fire_alert = max(fire_alert, 1) - switch(bodytemperature) - if(360 to 400) - apply_damage(HEAT_DAMAGE_LEVEL_1, BURN) - fire_alert = max(fire_alert, 2) - if(400 to 1000) - apply_damage(HEAT_DAMAGE_LEVEL_2, BURN) - fire_alert = max(fire_alert, 2) - if(1000 to INFINITY) - apply_damage(HEAT_DAMAGE_LEVEL_3, BURN) - fire_alert = max(fire_alert, 2) - return - -/mob/living/carbon/alien/proc/handle_mutations_and_radiation() - - if(getFireLoss()) - if((COLD_RESISTANCE in mutations) || prob(5)) - adjustFireLoss(-1) - - // Aliens love radiation nom nom nom - if (radiation) - if (radiation > 100) - radiation = 100 - - if (radiation < 0) - radiation = 0 - - switch(radiation) - if(1 to 49) - radiation-- - if(prob(25)) - adjustToxLoss(1) - - if(50 to 74) - radiation -= 2 - adjustToxLoss(1) - if(prob(5)) - radiation -= 5 - - if(75 to 100) - radiation -= 3 - adjustToxLoss(3) - -/mob/living/carbon/alien/IsAdvancedToolUser() - return has_fine_manipulation - -/mob/living/carbon/alien/Process_Spaceslipping() - return 0 // Don't slip in space. - -/mob/living/carbon/alien/Stat() - - statpanel("Status") - stat(null, "Intent: [a_intent]") - stat(null, "Move Mode: [m_intent]") ..() - if (client.statpanel == "Status") - stat(null, "Plasma Stored: [getPlasma()]/[max_plasma]") - - if(emergency_shuttle) - var/eta_status = emergency_shuttle.get_status_panel_eta() - if(eta_status) - stat(null, eta_status) - -/mob/living/carbon/alien/Stun(amount) - if(status_flags & CANSTUN) - stunned = max(max(stunned,amount),0) //can't go below 0, getting a low amount of stun doesn't lower your current stun - else - // add some movement delay - move_delay_add = min(move_delay_add + round(amount / 2), 10) // a maximum delay of 10 +/mob/living/carbon/alien/u_equip(obj/item/W as obj) return -/mob/living/carbon/alien/getDNA() - return null +/mob/living/carbon/alien/Stat() + ..() + stat(null, "Progress: [amount_grown]/[max_grown]") -/mob/living/carbon/alien/setDNA() - return +/mob/living/carbon/alien/restrained() + return 0 -/*---------------------------------------- -Proc: AddInfectionImages() -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/C in mob_list) - if(C.status_flags & XENO_HOST) - 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 +/mob/living/carbon/alien/show_inv(mob/user as mob) + return //Consider adding cuffs and hats to this, for the sake of fun. - -/*---------------------------------------- -Proc: RemoveInfectionImages() -Des: Removes all infected images from the alien. -----------------------------------------*/ -/mob/living/carbon/alien/proc/RemoveInfectionImages() - if (client) - for(var/image/I in client.images) - 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 +/mob/living/carbon/alien/can_use_vents() + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/alien_attacks.dm b/code/modules/mob/living/carbon/alien/alien_attacks.dm new file mode 100644 index 0000000000..45a486adf7 --- /dev/null +++ b/code/modules/mob/living/carbon/alien/alien_attacks.dm @@ -0,0 +1,183 @@ +//There has to be a better way to define this shit. ~ Z +//can't equip anything +/mob/living/carbon/alien/attack_ui(slot_id) + return + +/mob/living/carbon/alien/meteorhit(O as obj) + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message(text("\red [] has been hit by []", src, O), 1) + if (health > 0) + adjustBruteLoss((istype(O, /obj/effect/meteor/small) ? 10 : 25)) + adjustFireLoss(30) + + updatehealth() + return + +/mob/living/carbon/alien/attack_animal(mob/living/M as mob) + + if(istype(M,/mob/living/simple_animal)) + var/mob/living/simple_animal/S = M + if(S.melee_damage_upper == 0) + S.emote("[S.friendly] [src]") + else + for(var/mob/O in viewers(src, null)) + O.show_message("\red [S] [S.attacktext] [src]!", 1) + var/damage = rand(S.melee_damage_lower, S.melee_damage_upper) + adjustBruteLoss(damage) + S.attack_log += text("\[[time_stamp()]\] attacked [src.name] ([src.ckey])") + src.attack_log += text("\[[time_stamp()]\] was attacked by [S.name] ([S.ckey])") + updatehealth() + +/mob/living/carbon/alien/attack_paw(mob/living/carbon/monkey/M as mob) + if(!(istype(M, /mob/living/carbon/monkey))) return//Fix for aliens receiving double messages when attacking other aliens. + + if (!ticker) + M << "You cannot attack people before the game has started." + return + + if (istype(loc, /turf) && istype(loc.loc, /area/start)) + M << "No attacking people at spawn, you jackass." + return + ..() + + switch(M.a_intent) + + if ("help") + help_shake_act(M) + else + if (istype(wear_mask, /obj/item/clothing/mask/muzzle)) + return + if (health > 0) + playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [M.name] has bit [src]!"), 1) + adjustBruteLoss(rand(1, 3)) + updatehealth() + return + + +/mob/living/carbon/alien/attack_slime(mob/living/carbon/slime/M as mob) + if (!ticker) + M << "You cannot attack people before the game has started." + return + + if(M.Victim) return // can't attack while eating! + + if (health > -100) + + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red The [M.name] glomps []!", src), 1) + + var/damage = rand(1, 3) + + if(M.is_adult) + damage = rand(20, 40) + else + damage = rand(5, 35) + + adjustBruteLoss(damage) + + + updatehealth() + + return + +/mob/living/carbon/alien/attack_hand(mob/living/carbon/human/M as mob) + if (!ticker) + M << "You cannot attack people before the game has started." + return + + if (istype(loc, /turf) && istype(loc.loc, /area/start)) + M << "No attacking people at spawn, you jackass." + return + + ..() + + if(M.gloves && istype(M.gloves,/obj/item/clothing/gloves)) + var/obj/item/clothing/gloves/G = M.gloves + if(G.cell) + if(M.a_intent == "hurt")//Stungloves. Any contact will stun the alien. + if(G.cell.charge >= 2500) + G.cell.use(2500) + + Weaken(5) + if (stuttering < 5) + stuttering = 5 + Stun(5) + + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message("\red [src] has been touched with the stun gloves by [M]!", 1, "\red You hear someone fall.", 2) + return + else + M << "\red Not enough charge! " + return + + switch(M.a_intent) + + if ("help") + if (health > 0) + help_shake_act(M) + else + if (M.health >= -75.0) + if ((M.head && M.head.flags & 4) || (M.wear_mask && !( M.wear_mask.flags & 32 )) ) + M << "\blue Remove that mask!" + return + var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human( ) + O.source = M + O.target = src + O.s_loc = M.loc + O.t_loc = loc + O.place = "CPR" + requests += O + spawn( 0 ) + O.process() + return + + if ("grab") + if (M == src) + return + var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, M, src ) + + M.put_in_active_hand(G) + + grabbed_by += G + G.synch() + + LAssailant = M + + playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) + + else + var/damage = rand(1, 9) + if (prob(90)) + if (HULK in M.mutations) + damage += 5 + spawn(0) + Paralyse(1) + step_away(src,M,15) + sleep(3) + step_away(src,M,15) + playsound(loc, "punch", 25, 1, -1) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] has punched []!", M, src), 1) + if (damage > 4.9) + Weaken(rand(10,15)) + for(var/mob/O in viewers(M, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] has weakened []!", M, src), 1, "\red You hear someone fall.", 2) + adjustBruteLoss(damage) + updatehealth() + else + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] has attempted to punch []!", M, src), 1) + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/alien_damage.dm b/code/modules/mob/living/carbon/alien/alien_damage.dm new file mode 100644 index 0000000000..1483559120 --- /dev/null +++ b/code/modules/mob/living/carbon/alien/alien_damage.dm @@ -0,0 +1,56 @@ +/mob/living/carbon/alien/ex_act(severity) + + if(!blinded) + flick("flash", flash) + + var/b_loss = null + var/f_loss = null + switch (severity) + if (1.0) + b_loss += 500 + gib() + return + + if (2.0) + + b_loss += 60 + + f_loss += 60 + + ear_damage += 30 + ear_deaf += 120 + + if(3.0) + b_loss += 30 + if (prob(50)) + Paralyse(1) + ear_damage += 15 + ear_deaf += 60 + + adjustBruteLoss(b_loss) + adjustFireLoss(f_loss) + + updatehealth() + + + +/mob/living/carbon/alien/blob_act() + if (stat == 2) + return + var/shielded = 0 + + var/damage = null + if (stat != 2) + damage = rand(10,30) + + if(shielded) + damage /= 4 + + //paralysis += 1 + + show_message("\red The blob attacks you!") + + adjustFireLoss(damage) + + updatehealth() + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/death.dm b/code/modules/mob/living/carbon/alien/death.dm index 0a060dd1f7..7dfd2cc0eb 100644 --- a/code/modules/mob/living/carbon/alien/death.dm +++ b/code/modules/mob/living/carbon/alien/death.dm @@ -1,41 +1,13 @@ -/mob/living/carbon/alien/gib() - death(1) - var/atom/movable/overlay/animation = null - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 +/mob/living/carbon/alien/death(gibbed) - animation = new(loc) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src + if(stat == DEAD) return + if(healths) healths.icon_state = "health6" + stat = DEAD - flick("gibbed-a", animation) - xgibs(loc, viruses) - dead_mob_list -= src + if(dead_icon) icon_state = dead_icon - spawn(15) - if(animation) del(animation) - if(src) del(src) + if(!gibbed) + update_canmove() + if(client) blind.layer = 0 -/mob/living/carbon/alien/dust() - death(1) - var/atom/movable/overlay/animation = null - monkeyizing = 1 - canmove = 0 - icon = null - invisibility = 101 - - animation = new(loc) - animation.icon_state = "blank" - animation.icon = 'icons/mob/mob.dmi' - animation.master = src - - flick("dust-a", animation) - new /obj/effect/decal/remains/xeno(loc) - dead_mob_list -= src - - spawn(15) - if(animation) del(animation) - if(src) del(src) + return ..(gibbed) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/diona/diona.dm b/code/modules/mob/living/carbon/alien/diona/diona.dm new file mode 100644 index 0000000000..3f4bc2105d --- /dev/null +++ b/code/modules/mob/living/carbon/alien/diona/diona.dm @@ -0,0 +1,25 @@ +/mob/living/carbon/alien/diona + name = "diona nymph" + voice_name = "diona nymph" + adult_form = /mob/living/carbon/human + speak_emote = list("chirrups") + icon_state = "nymph" + language = "Rootspeak" + + amount_grown = 0 + max_grown = 5 // Target number of donors. + + var/list/donors = list() + var/last_checked_stage = 0 + + universal_understand = 0 // Dionaea do not need to speak to people + universal_speak = 0 // before becoming an adult. Use *chirp. + holder_type = /obj/item/weapon/holder/diona + +/mob/living/carbon/alien/diona/New() + + ..() + verbs += /mob/living/carbon/proc/eat_weeds + verbs += /mob/living/carbon/proc/fertilize_plant + verbs += /mob/living/carbon/alien/diona/proc/steal_blood + verbs += /mob/living/carbon/alien/diona/proc/merge \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/diona/diona_attacks.dm b/code/modules/mob/living/carbon/alien/diona/diona_attacks.dm new file mode 100644 index 0000000000..108333bf86 --- /dev/null +++ b/code/modules/mob/living/carbon/alien/diona/diona_attacks.dm @@ -0,0 +1,14 @@ +/mob/living/carbon/alien/diona/attack_hand(mob/living/carbon/human/M as mob) + + //Let people pick the little buggers up. + if(M.a_intent == "help") + if(M.species && M.species.name == "Diona") + M << "You feel your being twine with that of [src] as it merges with your biomass." + src << "You feel your being twine with that of [M] as you merge with its biomass." + src.verbs += /mob/living/carbon/alien/diona/proc/split + src.verbs -= /mob/living/carbon/alien/diona/proc/merge + src.loc = M + else + get_scooped(M) + + ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/diona/diona_powers.dm b/code/modules/mob/living/carbon/alien/diona/diona_powers.dm new file mode 100644 index 0000000000..b8a47501a8 --- /dev/null +++ b/code/modules/mob/living/carbon/alien/diona/diona_powers.dm @@ -0,0 +1,90 @@ +//Verbs after this point. +/mob/living/carbon/alien/diona/proc/merge() + + set category = "Abilities" + set name = "Merge with gestalt" + set desc = "Merge with another diona." + + if(istype(src.loc,/mob/living/carbon)) + src.verbs -= /mob/living/carbon/alien/diona/proc/merge + return + + var/list/choices = list() + for(var/mob/living/carbon/C in view(1,src)) + + if(!(src.Adjacent(C)) || !(C.client)) continue + + if(istype(C,/mob/living/carbon/human)) + var/mob/living/carbon/human/D = C + if(D.species && D.species.name == "Diona") + choices += C + + var/mob/living/M = input(src,"Who do you wish to merge with?") in null|choices + + if(!M || !src || !(src.Adjacent(M))) return + + if(istype(M,/mob/living/carbon/human)) + M << "You feel your being twine with that of [src] as it merges with your biomass." + M.status_flags |= PASSEMOTES + + src << "You feel your being twine with that of [M] as you merge with its biomass." + src.loc = M + src.verbs += /mob/living/carbon/alien/diona/proc/split + src.verbs -= /mob/living/carbon/alien/diona/proc/merge + else + return + +/mob/living/carbon/alien/diona/proc/split() + + set category = "Abilities" + set name = "Split from gestalt" + set desc = "Split away from your gestalt as a lone nymph." + + if(!(istype(src.loc,/mob/living/carbon))) + src.verbs -= /mob/living/carbon/alien/diona/proc/split + return + + src.loc << "You feel a pang of loss as [src] splits away from your biomass." + src << "You wiggle out of the depths of [src.loc]'s biomass and plop to the ground." + + var/mob/living/M = src.loc + + src.loc = get_turf(src) + src.verbs -= /mob/living/carbon/alien/diona/proc/split + src.verbs += /mob/living/carbon/alien/diona/proc/merge + + if(istype(M)) + for(var/atom/A in M.contents) + if(istype(A,/mob/living/simple_animal/borer) || istype(A,/obj/item/weapon/holder)) + return + M.status_flags &= ~PASSEMOTES + +/mob/living/carbon/alien/diona/proc/steal_blood() + set category = "Abilities" + set name = "Steal Blood" + set desc = "Take a blood sample from a suitable donor." + + var/list/choices = list() + for(var/mob/living/carbon/human/H in oview(1,src)) + if(src.Adjacent(H)) + choices += H + + var/mob/living/carbon/human/M = input(src,"Who do you wish to take a sample from?") in null|choices + + if(!M || !src) return + + if(M.species.flags & NO_BLOOD) + src << "\red That donor has no blood to take." + return + + if(donors.Find(M.real_name)) + src << "\red That donor offers you nothing new." + return + + src.visible_message("\red [src] flicks out a feeler and neatly steals a sample of [M]'s blood.","\red You flick out a feeler and neatly steal a sample of [M]'s blood.") + donors += M.real_name + for(var/datum/language/L in M.languages) + languages |= L + + spawn(25) + update_progression() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/diona/life.dm b/code/modules/mob/living/carbon/alien/diona/life.dm new file mode 100644 index 0000000000..5a82e3f373 --- /dev/null +++ b/code/modules/mob/living/carbon/alien/diona/life.dm @@ -0,0 +1,20 @@ +//Dionaea regenerate health and nutrition in light. +/mob/living/carbon/alien/diona/handle_environment(datum/gas_mixture/environment) + + var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing + if(isturf(loc)) //else, there's considered to be no light + var/turf/T = loc + var/area/A = T.loc + if(A) + if(A.lighting_use_dynamic) light_amount = min(10,T.lighting_lumcount) - 5 //hardcapped so it's not abused by having a ton of flashlights + else light_amount = 5 + + nutrition += light_amount + + if(nutrition > 500) + nutrition = 500 + if(light_amount > 2) //if there's enough light, heal + adjustBruteLoss(-1) + adjustFireLoss(-1) + adjustToxLoss(-1) + adjustOxyLoss(-1) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/diona/progression.dm b/code/modules/mob/living/carbon/alien/diona/progression.dm new file mode 100644 index 0000000000..b99f593a10 --- /dev/null +++ b/code/modules/mob/living/carbon/alien/diona/progression.dm @@ -0,0 +1,40 @@ +/mob/living/carbon/alien/diona/confirm_evolution() + + if(!is_alien_whitelisted(src, "Diona") && config.usealienwhitelist) + src << alert("You are currently not whitelisted to play as a full diona.") + return null + + if(amount_grown < max_grown) + src << "You are not yet ready for your growth..." + return null + + src.split() + + if(istype(loc,/obj/item/weapon/holder/diona)) + var/obj/item/weapon/holder/diona/L = loc + src.loc = L.loc + del(L) + + src.visible_message("\red [src] begins to shift and quiver, and erupts in a shower of shed bark as it splits into a tangle of nearly a dozen new dionaea.","\red You begin to shift and quiver, feeling your awareness splinter. All at once, we consume our stored nutrients to surge with growth, splitting into a tangle of at least a dozen new dionaea. We have attained our gestalt form.") + return "Diona" + +/mob/living/carbon/alien/diona/show_evolution_blurb() + //TODO + return + +/mob/living/carbon/alien/diona/update_progression() + + amount_grown = donors.len + + if(amount_grown <= last_checked_stage) + return + + // Only fire off these messages once. + last_checked_stage = amount_grown + if(amount_grown == max_grown) + src << "\green You feel ready to move on to your next stage of growth." + else if(amount_grown == 3) + universal_understand = 1 + src << "\green You feel your awareness expand, and realize you know how to understand the creatures around you." + else + src << "\green The blood seeps into your small form, and you draw out the echoes of memories and personality from it, working them into your budding mind." \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/diona/say_understands.dm b/code/modules/mob/living/carbon/alien/diona/say_understands.dm new file mode 100644 index 0000000000..3f68a44cff --- /dev/null +++ b/code/modules/mob/living/carbon/alien/diona/say_understands.dm @@ -0,0 +1,6 @@ +/mob/living/carbon/alien/diona/say_understands(var/mob/other,var/datum/language/speaking = null) + + if (istype(other, /mob/living/carbon/human) && !speaking) + if(languages.len >= 2) // They have sucked down some blood. + return 1 + return ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/diona/update_icons.dm b/code/modules/mob/living/carbon/alien/diona/update_icons.dm new file mode 100644 index 0000000000..b39972cdad --- /dev/null +++ b/code/modules/mob/living/carbon/alien/diona/update_icons.dm @@ -0,0 +1,8 @@ +/mob/living/carbon/alien/diona/update_icons() + + if(stat == DEAD) + icon_state = "[initial(icon_state)]_dead" + else if(lying || resting || stunned) + icon_state = "[initial(icon_state)]_sleep" + else + icon_state = "[initial(icon_state)]" diff --git a/code/modules/mob/living/carbon/alien/larva/emote.dm b/code/modules/mob/living/carbon/alien/emote.dm similarity index 86% rename from code/modules/mob/living/carbon/alien/larva/emote.dm rename to code/modules/mob/living/carbon/alien/emote.dm index 375c5c6b0c..0efcae7c91 100644 --- a/code/modules/mob/living/carbon/alien/larva/emote.dm +++ b/code/modules/mob/living/carbon/alien/emote.dm @@ -1,127 +1,127 @@ -/mob/living/carbon/alien/larva/emote(var/act,var/m_type=1,var/message = null) - - var/param = null - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - param = copytext(act, t1 + 1, length(act) + 1) - act = copytext(act, 1, t1) - - if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' - act = copytext(act,1,length(act)) - var/muzzled = istype(src.wear_mask, /obj/item/clothing/mask/muzzle) - - switch(act) - if ("me") - if(silent) - return - if (src.client) - if (client.prefs.muted & MUTE_IC) - src << "\red You cannot send IC messages (muted)." - return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return - if (stat) - return - if(!(message)) - return - return custom_emote(m_type, message) - - if ("custom") - return custom_emote(m_type, message) - if("sign") - if (!src.restrained()) - message = text("The alien signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null)) - m_type = 1 - if ("burp") - if (!muzzled) - message = "[src] burps." - m_type = 2 - if("scratch") - if (!src.restrained()) - message = "The [src.name] scratches." - m_type = 1 - if("whimper") - if (!muzzled) - message = "The [src.name] whimpers." - m_type = 2 -// if("roar") -// if (!muzzled) -// message = "The [src.name] roars." Commenting out since larva shouldn't roar /N -// m_type = 2 - if("tail") - message = "The [src.name] waves its tail." - m_type = 1 - if("gasp") - message = "The [src.name] gasps." - m_type = 2 - if("shiver") - message = "The [src.name] shivers." - m_type = 2 - if("drool") - message = "The [src.name] drools." - m_type = 1 - if("scretch") - if (!muzzled) - message = "The [src.name] scretches." - m_type = 2 - if("choke") - message = "The [src.name] chokes." - m_type = 2 - if("moan") - message = "The [src.name] moans!" - m_type = 2 - if("nod") - message = "The [src.name] nods its head." - m_type = 1 -// if("sit") -// message = "The [src.name] sits down." //Larvan can't sit down, /N -// m_type = 1 - if("sway") - message = "The [src.name] sways around dizzily." - m_type = 1 - if("sulk") - message = "The [src.name] sulks down sadly." - m_type = 1 - if("twitch") - message = "The [src.name] twitches violently." - m_type = 1 - if("dance") - if (!src.restrained()) - message = "The [src.name] dances around happily." - m_type = 1 - if("roll") - if (!src.restrained()) - message = "The [src.name] rolls." - m_type = 1 - if("shake") - message = "The [src.name] shakes its head." - m_type = 1 - if("gnarl") - if (!muzzled) - message = "The [src.name] gnarls and shows its teeth.." - m_type = 2 - 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) - m_type = 2 - if("help") - src << "burp, choke, collapse, dance, drool, gasp, shiver, gnarl, jump, moan, nod, roll, scratch,\nscretch, shake, sign-#, sulk, sway, tail, twitch, whimper" - else - src << text("Invalid Emote: []", act) - if ((message && src.stat == 0)) - log_emote("[name]/[key] : [message]") - if (m_type & 1) - for(var/mob/O in viewers(src, null)) - O.show_message(message, m_type) - //Foreach goto(703) - else - for(var/mob/O in hearers(src, null)) - O.show_message(message, m_type) - //Foreach goto(746) +/mob/living/carbon/alien/emote(var/act,var/m_type=1,var/message = null) + + var/param = null + if (findtext(act, "-", 1, null)) + var/t1 = findtext(act, "-", 1, null) + param = copytext(act, t1 + 1, length(act) + 1) + act = copytext(act, 1, t1) + + if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' + act = copytext(act,1,length(act)) + var/muzzled = istype(src.wear_mask, /obj/item/clothing/mask/muzzle) + + switch(act) + if ("me") + if(silent) + return + if (src.client) + if (client.prefs.muted & MUTE_IC) + src << "\red You cannot send IC messages (muted)." + return + if (src.client.handle_spam_prevention(message,MUTE_IC)) + return + if (stat) + return + if(!(message)) + return + return custom_emote(m_type, message) + + if ("custom") + return custom_emote(m_type, message) + if("sign") + if (!src.restrained()) + message = text("The alien signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null)) + m_type = 1 + if ("burp") + if (!muzzled) + message = "[src] burps." + m_type = 2 + if("scratch") + if (!src.restrained()) + message = "The [src.name] scratches." + m_type = 1 + if("whimper") + if (!muzzled) + message = "The [src.name] whimpers." + m_type = 2 + if("tail") + message = "The [src.name] waves its tail." + m_type = 1 + if("gasp") + message = "The [src.name] gasps." + m_type = 2 + if("shiver") + message = "The [src.name] shivers." + m_type = 2 + if("drool") + message = "The [src.name] drools." + m_type = 1 + if("scretch") + if (!muzzled) + message = "The [src.name] scretches." + m_type = 2 + if("choke") + message = "The [src.name] chokes." + m_type = 2 + if("moan") + message = "The [src.name] moans!" + m_type = 2 + if("nod") + message = "The [src.name] nods its head." + m_type = 1 +// if("sit") +// message = "The [src.name] sits down." //Larvan can't sit down, /N +// m_type = 1 + if("sway") + message = "The [src.name] sways around dizzily." + m_type = 1 + if("sulk") + message = "The [src.name] sulks down sadly." + m_type = 1 + if("twitch") + message = "The [src.name] twitches violently." + m_type = 1 + if("dance") + if (!src.restrained()) + message = "The [src.name] dances around happily." + m_type = 1 + if("roll") + if (!src.restrained()) + message = "The [src.name] rolls." + m_type = 1 + if("shake") + message = "The [src.name] shakes its head." + m_type = 1 + if("gnarl") + if (!muzzled) + message = "The [src.name] gnarls and shows its teeth.." + m_type = 2 + 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) + m_type = 2 + if("chirp") + message = "The [src.name] chirps!" + playsound(src.loc, 'sound/misc/nymphchirp.ogg', 50, 0) + m_type = 2 + if("help") + src << "burp, chirp, choke, collapse, dance, drool, gasp, shiver, gnarl, jump, moan, nod, roll, scratch,\nscretch, shake, sign-#, sulk, sway, tail, twitch, whimper" + else + src << text("Invalid Emote: []", act) + if ((message && src.stat == 0)) + log_emote("[name]/[key] : [message]") + if (m_type & 1) + for(var/mob/O in viewers(src, null)) + O.show_message(message, m_type) + //Foreach goto(703) + else + for(var/mob/O in hearers(src, null)) + O.show_message(message, m_type) + //Foreach goto(746) return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm deleted file mode 100644 index 92426808b6..0000000000 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ /dev/null @@ -1,188 +0,0 @@ -/*NOTES: -These are general powers. Specific powers are stored under the appropriate alien creature type. -*/ - -/*Alien spit now works like a taser shot. It won't home in on the target but will act the same once it does hit. -Doesn't work on other aliens/AI.*/ - - -/mob/living/carbon/alien/proc/powerc(X, Y)//Y is optional, checks for weed planting. X can be null. - if(stat) - src << "\green You must be conscious to do this." - return 0 - else if(X && getPlasma() < X) - src << "\green Not enough plasma stored." - return 0 - else if(Y && (!isturf(src.loc) || istype(src.loc, /turf/space))) - src << "\green Bad place for a garden!" - return 0 - else return 1 - -/mob/living/carbon/alien/humanoid/verb/plant() - set name = "Plant Weeds (50)" - set desc = "Plants some alien weeds" - set category = "Alien" - - if(powerc(50,1)) - adjustToxLoss(-50) - for(var/mob/O in viewers(src, null)) - O.show_message(text("\green [src] has planted some alien weeds!"), 1) - new /obj/effect/alien/weeds/node(loc) - return - -/* -/mob/living/carbon/alien/humanoid/verb/ActivateHuggers() - set name = "Activate facehuggers (5)" - set desc = "Makes all nearby facehuggers activate" - set category = "Alien" - - if(powerc(5)) - adjustToxLoss(-5) - for(var/obj/item/clothing/mask/facehugger/F in range(8,src)) - F.GoActive() - emote("roar") - return -*/ -/mob/living/carbon/alien/humanoid/verb/whisp(mob/M as mob in oview()) - set name = "Whisper (10)" - set desc = "Whisper to someone" - set category = "Alien" - - if(powerc(10)) - adjustToxLoss(-10) - var/msg = sanitize(input("Message:", "Alien Whisper") as text|null) - if(msg) - log_say("AlienWhisper: [key_name(src)]->[M.key] : [msg]") - M << "\green You hear a strange, alien voice in your head... \italic [msg]" - src << {"\green You said: "[msg]" to [M]"} - return - -/mob/living/carbon/alien/humanoid/verb/transfer_plasma(mob/living/carbon/alien/M as mob in oview()) - set name = "Transfer Plasma" - set desc = "Transfer Plasma to another alien" - set category = "Alien" - - if(isalien(M)) - var/amount = input("Amount:", "Transfer Plasma to [M]") as num - if (amount) - amount = abs(round(amount)) - if(powerc(amount)) - if (get_dist(src,M) <= 1) - M.adjustToxLoss(amount) - adjustToxLoss(-amount) - M << "\green [src] has transfered [amount] plasma to you." - src << {"\green You have trasferred [amount] plasma to [M]"} - else - src << "\green You need to be closer." - return - - -/mob/living/carbon/alien/humanoid/proc/corrosive_acid(O as obj|turf in oview(1)) //If they right click to corrode, an error will flash if its an invalid target./N - set name = "Corrossive Acid (200)" - set desc = "Drench an object in acid, destroying it over time." - set category = "Alien" - - if(powerc(200)) - if(O in oview(1)) - // OBJ CHECK - if(isobj(O)) - var/obj/I = O - if(I.unacidable) //So the aliens don't destroy energy fields/singularies/other aliens/etc with their acid. - src << "\green You cannot dissolve this object." - return - // TURF CHECK - else if(istype(O, /turf/simulated)) - var/turf/T = O - // R WALL - if(istype(T, /turf/simulated/wall/r_wall)) - src << "\green You cannot dissolve this object." - return - // R FLOOR - if(istype(T, /turf/simulated/floor/engine)) - src << "\green You cannot dissolve this object." - return - else// Not a type we can acid. - return - - adjustToxLoss(-200) - new /obj/effect/alien/acid(get_turf(O), O) - visible_message("\green [src] vomits globs of vile stuff all over [O]. It begins to sizzle and melt under the bubbling mess of acid!") - else - src << "\green Target is too far away." - return - - -/mob/living/carbon/alien/humanoid/proc/neurotoxin(mob/target as mob in oview()) - set name = "Spit Neurotoxin (50)" - set desc = "Spits neurotoxin at someone, paralyzing them for a short time if they are not wearing protective gear." - set category = "Alien" - - if(powerc(50)) - if(isalien(target)) - src << "\green Your allies are not a valid target." - return - adjustToxLoss(-50) - src << "\green You spit neurotoxin at [target]." - for(var/mob/O in oviewers()) - if ((O.client && !( O.blinded ))) - O << "\red [src] spits neurotoxin at [target]!" - //I'm not motivated enough to revise this. Prjectile code in general needs update. - var/turf/T = loc - var/turf/U = (istype(target, /atom/movable) ? target.loc : target) - - if(!U || !T) - return - while(U && !istype(U,/turf)) - U = U.loc - if(!istype(T, /turf)) - return - if (U == T) - usr.bullet_act(new /obj/item/projectile/energy/neurotoxin(usr.loc), get_organ_target()) - return - if(!istype(U, /turf)) - return - - var/obj/item/projectile/energy/neurotoxin/A = new /obj/item/projectile/energy/neurotoxin(usr.loc) - A.current = U - A.yo = U.y - T.y - A.xo = U.x - T.x - A.process() - return - -/mob/living/carbon/alien/humanoid/proc/resin() // -- TLE - set name = "Secrete Resin (75)" - set desc = "Secrete tough malleable resin." - set category = "Alien" - - if(powerc(75)) - var/choice = input("Choose what you wish to shape.","Resin building") as null|anything in list("resin door","resin wall","resin membrane","resin nest") //would do it through typesof but then the player choice would have the type path and we don't want the internal workings to be exposed ICly - Urist - if(!choice || !powerc(75)) return - adjustToxLoss(-75) - src << "\green You shape a [choice]." - for(var/mob/O in viewers(src, null)) - O.show_message(text("\red [src] vomits up a thick purple substance and begins to shape it!"), 1) - switch(choice) - if("resin door") - new /obj/structure/mineral_door/resin(loc) - if("resin wall") - new /obj/effect/alien/resin/wall(loc) - if("resin membrane") - new /obj/effect/alien/resin/membrane(loc) - if("resin nest") - new /obj/structure/stool/bed/nest(loc) - return - -/mob/living/carbon/alien/humanoid/verb/regurgitate() - set name = "Regurgitate" - set desc = "Empties the contents of your stomach" - set category = "Alien" - - if(powerc()) - if(stomach_contents.len) - for(var/mob/M in src) - if(M in stomach_contents) - stomach_contents.Remove(M) - M.loc = loc - //Paralyse(10) - src.visible_message("\green [src] hurls out the contents of their stomach!") - return diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm deleted file mode 100644 index 2b084ce8b5..0000000000 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm +++ /dev/null @@ -1,48 +0,0 @@ -/mob/living/carbon/alien/humanoid/drone - name = "alien drone" - caste = "d" - maxHealth = 100 - health = 100 - icon_state = "aliend_s" - plasma_rate = 15 - -/mob/living/carbon/alien/humanoid/drone/New() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - if(src.name == "alien drone") - src.name = text("alien drone ([rand(1, 1000)])") - src.real_name = src.name - verbs.Add(/mob/living/carbon/alien/humanoid/proc/resin,/mob/living/carbon/alien/humanoid/proc/corrosive_acid) - ..() -//Drones use the same base as generic humanoids. -//Drone verbs - -/mob/living/carbon/alien/humanoid/drone/verb/evolve() // -- TLE - set name = "Evolve (500)" - set desc = "Produce an interal egg sac capable of spawning children. Only one queen can exist at a time." - set category = "Alien" - - if(powerc(500)) - // Queen check - var/no_queen = 1 - for(var/mob/living/carbon/alien/humanoid/queen/Q in living_mob_list) - if(!Q.key && Q.brain_op_stage != 4) - continue - no_queen = 0 - - if(src.has_brain_worms()) - src << "We cannot perform this ability at the present time!" - return - - if(no_queen) - adjustToxLoss(-500) - src << "\green You begin to evolve!" - for(var/mob/O in viewers(src, null)) - O.show_message(text("\green [src] begins to twist and contort!"), 1) - var/mob/living/carbon/alien/humanoid/queen/new_xeno = new (loc) - mind.transfer_to(new_xeno) - del(src) - else - src << "We already have an alive queen." - return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm deleted file mode 100644 index 3a15f620b2..0000000000 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ /dev/null @@ -1,76 +0,0 @@ -/mob/living/carbon/alien/humanoid/hunter - name = "alien hunter" - caste = "h" - maxHealth = 150 - health = 150 - storedPlasma = 100 - max_plasma = 150 - icon_state = "alienh_s" - plasma_rate = 5 - -/mob/living/carbon/alien/humanoid/hunter/New() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - if(name == "alien hunter") - name = text("alien hunter ([rand(1, 1000)])") - real_name = name - ..() - -/mob/living/carbon/alien/humanoid/hunter - - - handle_regular_hud_updates() - - ..() //-Yvarov - - if (healths) - if (stat != 2) - switch(health) - if(150 to INFINITY) - healths.icon_state = "health0" - if(100 to 150) - healths.icon_state = "health1" - if(50 to 100) - healths.icon_state = "health2" - if(25 to 50) - healths.icon_state = "health3" - if(0 to 25) - healths.icon_state = "health4" - else - healths.icon_state = "health5" - else - healths.icon_state = "health6" - - - handle_environment() - if(m_intent == "run" || resting) - ..() - else - adjustToxLoss(-heal_rate) - - -//Hunter verbs -/* -/mob/living/carbon/alien/humanoid/hunter/verb/invis() - set name = "Invisibility (50)" - set desc = "Makes you invisible for 15 seconds" - set category = "Alien" - - if(alien_invis) - update_icons() - else - if(powerc(50)) - adjustToxLoss(-50) - alien_invis = 1.0 - update_icons() - src << "\green You are now invisible." - for(var/mob/O in oviewers(src, null)) - O.show_message(text("\red [src] fades into the surroundings!"), 1) - spawn(250) - if(!isnull(src))//Don't want the game to runtime error when the mob no-longer exists. - alien_invis = 0.0 - update_icons() - src << "\green You are no longer invisible." - return -*/ \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm deleted file mode 100644 index 226824c6ab..0000000000 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm +++ /dev/null @@ -1,44 +0,0 @@ -/mob/living/carbon/alien/humanoid/sentinel - name = "alien sentinel" - caste = "s" - maxHealth = 125 - health = 125 - storedPlasma = 100 - max_plasma = 250 - icon_state = "aliens_s" - plasma_rate = 10 - -/mob/living/carbon/alien/humanoid/sentinel/New() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - if(name == "alien sentinel") - name = text("alien sentinel ([rand(1, 1000)])") - real_name = name - verbs.Add(/mob/living/carbon/alien/humanoid/proc/corrosive_acid,/mob/living/carbon/alien/humanoid/proc/neurotoxin) - ..() - -/mob/living/carbon/alien/humanoid/sentinel - - - handle_regular_hud_updates() - - ..() //-Yvarov - - if (healths) - if (stat != 2) - switch(health) - if(125 to INFINITY) - healths.icon_state = "health0" - if(100 to 125) - healths.icon_state = "health1" - if(75 to 100) - healths.icon_state = "health2" - if(25 to 75) - healths.icon_state = "health3" - if(0 to 25) - healths.icon_state = "health4" - else - healths.icon_state = "health5" - else - healths.icon_state = "health6" diff --git a/code/modules/mob/living/carbon/alien/humanoid/death.dm b/code/modules/mob/living/carbon/alien/humanoid/death.dm deleted file mode 100644 index 91138a4309..0000000000 --- a/code/modules/mob/living/carbon/alien/humanoid/death.dm +++ /dev/null @@ -1,17 +0,0 @@ -/mob/living/carbon/alien/humanoid/death(gibbed) - if(stat == DEAD) return - if(healths) healths.icon_state = "health6" - stat = DEAD - - if(!gibbed) - playsound(loc, 'sound/voice/hiss6.ogg', 80, 1, 1) - for(var/mob/O in viewers(src, null)) - 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) - - return ..(gibbed) diff --git a/code/modules/mob/living/carbon/alien/humanoid/emote.dm b/code/modules/mob/living/carbon/alien/humanoid/emote.dm deleted file mode 100644 index 71dc56ef40..0000000000 --- a/code/modules/mob/living/carbon/alien/humanoid/emote.dm +++ /dev/null @@ -1,135 +0,0 @@ -/mob/living/carbon/alien/humanoid/emote(var/act,var/m_type=1,var/message = null) - - var/param = null - if (findtext(act, "-", 1, null)) - var/t1 = findtext(act, "-", 1, null) - param = copytext(act, t1 + 1, length(act) + 1) - act = copytext(act, 1, t1) - - if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_' - act = copytext(act,1,length(act)) - var/muzzled = istype(src.wear_mask, /obj/item/clothing/mask/muzzle) - - switch(act) - if ("me") - if(silent) - return - if (src.client) - if (client.prefs.muted & MUTE_IC) - src << "\red You cannot send IC messages (muted)." - return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return - if (stat) - return - if(!(message)) - return - return custom_emote(m_type, message) - - if ("custom") - return custom_emote(m_type, message) - if("sign") - if (!src.restrained()) - message = text("The alien signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null)) - m_type = 1 - if ("burp") - if (!muzzled) - message = "[src] burps." - m_type = 2 - if ("deathgasp") - message = "[src] lets out a waning guttural screech, green blood bubbling from its maw..." - m_type = 2 - if("scratch") - if (!src.restrained()) - message = "The [src.name] scratches." - m_type = 1 - if("whimper") - if (!muzzled) - message = "The [src.name] whimpers." - m_type = 2 - if("roar") - if (!muzzled) - message = "The [src.name] roars." - m_type = 2 - if("hiss") - if(!muzzled) - message = "The [src.name] hisses." - m_type = 2 - if("tail") - message = "The [src.name] waves its tail." - m_type = 1 - if("gasp") - message = "The [src.name] gasps." - m_type = 2 - if("shiver") - message = "The [src.name] shivers." - m_type = 2 - if("drool") - message = "The [src.name] drools." - m_type = 1 - if("scretch") - if (!muzzled) - message = "The [src.name] scretches." - m_type = 2 - if("choke") - message = "The [src.name] chokes." - m_type = 2 - if("moan") - message = "The [src.name] moans!" - m_type = 2 - if("nod") - message = "The [src.name] nods its head." - m_type = 1 - if("sit") - message = "The [src.name] sits down." - m_type = 1 - if("sway") - message = "The [src.name] sways around dizzily." - m_type = 1 - if("sulk") - message = "The [src.name] sulks down sadly." - m_type = 1 - if("twitch") - message = "The [src.name] twitches violently." - m_type = 1 - if("dance") - if (!src.restrained()) - message = "The [src.name] dances around happily." - m_type = 1 - if("roll") - if (!src.restrained()) - message = "The [src.name] rolls." - m_type = 1 - if("shake") - message = "The [src.name] shakes its head." - m_type = 1 - if("gnarl") - if (!muzzled) - message = "The [src.name] gnarls and shows its teeth.." - m_type = 2 - if("jump") - message = "The [src.name] jumps!" - m_type = 1 - if("collapse") - Paralyse(2) - message = text("[] collapses!", src) - m_type = 2 - if("help") - src << "burp, deathgasp, choke, collapse, dance, drool, gasp, shiver, gnarl, jump, moan, nod, roar, roll, scratch,\nscretch, shake, sign-#, sit, sulk, sway, tail, twitch, whimper" - else - src << text("Invalid Emote: []", act) - if ((message && src.stat == 0)) - log_emote("[name]/[key] : [message]") - if (act == "roar") - playsound(src.loc, 'sound/voice/hiss5.ogg', 40, 1, 1) - if (act == "deathgasp") - playsound(src.loc, 'sound/voice/hiss6.ogg', 80, 1, 1) - if (m_type & 1) - for(var/mob/O in viewers(src, null)) - O.show_message(message, m_type) - //Foreach goto(703) - else - for(var/mob/O in hearers(src, null)) - O.show_message(message, m_type) - //Foreach goto(746) - return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm deleted file mode 100644 index 03e590f036..0000000000 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm +++ /dev/null @@ -1,423 +0,0 @@ -/mob/living/carbon/alien/humanoid - name = "alien" - icon_state = "alien_s" - - var/obj/item/clothing/suit/wear_suit = null //TODO: necessary? Are they even used? ~Carn - var/obj/item/clothing/head/head = null // - var/obj/item/weapon/r_store = null - var/obj/item/weapon/l_store = null - var/caste = "" - update_icon = 1 - -//This is fine right now, if we're adding organ specific damage this needs to be updated -/mob/living/carbon/alien/humanoid/New() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - if(name == "alien") - name = text("alien ([rand(1, 1000)])") - real_name = name - ..() - -//This is fine, works the same as a human -/mob/living/carbon/alien/humanoid/Bump(atom/movable/AM as mob|obj, yes) - spawn( 0 ) - if ((!( yes ) || now_pushing)) - return - now_pushing = 0 - ..() - if (!istype(AM, /atom/movable)) - return - - if (ismob(AM)) - var/mob/tmob = AM - tmob.LAssailant = src - - if (!now_pushing) - now_pushing = 1 - if (!AM.anchored) - var/t = get_dir(src, AM) - if (istype(AM, /obj/structure/window)) - if(AM:ini_dir == NORTHWEST || AM:ini_dir == NORTHEAST || AM:ini_dir == SOUTHWEST || AM:ini_dir == SOUTHEAST) - for(var/obj/structure/window/win in get_step(AM,t)) - now_pushing = 0 - return - step(AM, t) - now_pushing = null - return - return - -/mob/living/carbon/alien/humanoid/movement_delay() - var/tally = 0 - if (istype(src, /mob/living/carbon/alien/humanoid/queen)) - tally += 5 - if (istype(src, /mob/living/carbon/alien/humanoid/drone)) - tally += 2 - if (istype(src, /mob/living/carbon/alien/humanoid/sentinel)) - tally += 1 - if (istype(src, /mob/living/carbon/alien/humanoid/hunter)) - tally = -1 // hunters go supersuperfast - return (tally + move_delay_add + config.alien_delay) - -///mob/living/carbon/alien/humanoid/bullet_act(var/obj/item/projectile/Proj) taken care of in living - -/mob/living/carbon/alien/humanoid/emp_act(severity) - if(wear_suit) wear_suit.emp_act(severity) - if(head) head.emp_act(severity) - if(r_store) r_store.emp_act(severity) - if(l_store) l_store.emp_act(severity) - ..() - -/mob/living/carbon/alien/humanoid/ex_act(severity) - if(!blinded) - flick("flash", flash) - - var/shielded = 0 - - var/b_loss = null - var/f_loss = null - switch (severity) - if (1.0) - b_loss += 500 - gib() - return - - if (2.0) - if (!shielded) - b_loss += 60 - - f_loss += 60 - - ear_damage += 30 - ear_deaf += 120 - - if(3.0) - b_loss += 30 - if (prob(50) && !shielded) - Paralyse(1) - ear_damage += 15 - ear_deaf += 60 - - adjustBruteLoss(b_loss) - adjustFireLoss(f_loss) - - updatehealth() - -/mob/living/carbon/alien/humanoid/blob_act() - if (stat == 2) - return - var/shielded = 0 - var/damage = null - if (stat != 2) - damage = rand(30,40) - - if(shielded) - damage /= 4 - - - show_message("\red The blob attacks!") - - adjustFireLoss(damage) - - return - - -/mob/living/carbon/alien/humanoid/meteorhit(O as obj) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message(text("\red [] has been hit by []", src, O), 1) - if (health > 0) - adjustFireLoss((istype(O, /obj/effect/meteor/small) ? 10 : 25)) - adjustFireLoss(30) - - updatehealth() - return - -/mob/living/carbon/alien/humanoid/attack_paw(mob/living/carbon/monkey/M as mob) - if(!ismonkey(M)) return//Fix for aliens receiving double messages when attacking other aliens. - - if (!ticker) - M << "You cannot attack people before the game has started." - return - - if (istype(loc, /turf) && istype(loc.loc, /area/start)) - M << "No attacking people at spawn, you jackass." - return - ..() - - switch(M.a_intent) - - if ("help") - help_shake_act(M) - else - if (istype(wear_mask, /obj/item/clothing/mask/muzzle)) - return - if (health > 0) - playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [M.name] has bit [src]!"), 1) - adjustBruteLoss(rand(1, 3)) - updatehealth() - return - - -/mob/living/carbon/alien/humanoid/attack_slime(mob/living/carbon/slime/M as mob) - if (!ticker) - M << "You cannot attack people before the game has started." - return - - if(M.Victim) return // can't attack while eating! - - if (health > -100) - - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red The [M.name] glomps []!", src), 1) - - var/damage = rand(1, 3) - - if(M.is_adult) - damage = rand(10, 40) - else - damage = rand(5, 35) - - adjustBruteLoss(damage) - - if(M.powerlevel > 0) - var/stunprob = 10 - var/power = M.powerlevel + rand(0,3) - - switch(M.powerlevel) - if(1 to 2) stunprob = 20 - if(3 to 4) stunprob = 30 - if(5 to 6) stunprob = 40 - if(7 to 8) stunprob = 60 - if(9) stunprob = 70 - if(10) stunprob = 95 - - if(prob(stunprob)) - M.powerlevel -= 3 - if(M.powerlevel < 0) - M.powerlevel = 0 - - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red The [M.name] has shocked []!", src), 1) - - Weaken(power) - if (stuttering < power) - stuttering = power - Stun(power) - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() - - if (prob(stunprob) && M.powerlevel >= 8) - adjustFireLoss(M.powerlevel * rand(6,10)) - - - updatehealth() - - return - -/mob/living/carbon/alien/humanoid/attack_animal(mob/living/simple_animal/M as mob) - if(M.melee_damage_upper == 0) - M.emote("[M.friendly] [src]") - else - if(M.attack_sound) - playsound(loc, M.attack_sound, 50, 1, 1) - for(var/mob/O in viewers(src, null)) - O.show_message("\red [M] [M.attacktext] [src]!", 1) - var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - adjustBruteLoss(damage) - updatehealth() - -/mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M as mob) - if (!ticker) - M << "You cannot attack people before the game has started." - return - - if (istype(loc, /turf) && istype(loc.loc, /area/start)) - M << "No attacking people at spawn, you jackass." - return - - ..() - - if(M.gloves && istype(M.gloves,/obj/item/clothing/gloves)) - var/obj/item/clothing/gloves/G = M.gloves - if(G.cell) - if(M.a_intent == "hurt")//Stungloves. Any contact will stun the alien. - if(G.cell.charge >= 2500) - G.cell.use(2500) - - Weaken(5) - if (stuttering < 5) - stuttering = 5 - Stun(5) - - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message("\red [src] has been touched with the stun gloves by [M]!", 1, "\red You hear someone fall.", 2) - return - else - M << "\red Not enough charge! " - return - - switch(M.a_intent) - - if ("help") - if (health > 0) - help_shake_act(M) - else - if (M.health >= -75.0) - if (((M.head && M.head.flags & 4) || ((M.wear_mask && !( M.wear_mask.flags & 32 )) || ((head && head.flags & 4) || (wear_mask && !( wear_mask.flags & 32 )))))) - M << "\blue Remove that mask!" - return - var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human( ) - O.source = M - O.target = src - O.s_loc = M.loc - O.t_loc = loc - O.place = "CPR" - requests += O - spawn( 0 ) - O.process() - return - - if ("grab") - if (M == src || anchored) - return - var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src) - - M.put_in_active_hand(G) - - grabbed_by += G - G.synch() - - LAssailant = M - - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) - - if ("hurt") - var/damage = rand(1, 9) - if (prob(90)) - if (HULK in M.mutations)//HULK SMASH - damage += 14 - spawn(0) - Weaken(damage) // Why can a hulk knock an alien out but not knock out a human? Damage is robust enough. - step_away(src,M,15) - sleep(3) - step_away(src,M,15) - playsound(loc, "punch", 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has punched []!", M, src), 1) - if (damage > 9||prob(5))//Regular humans have a very small chance of weakening an alien. - Weaken(1,5) - for(var/mob/O in viewers(M, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has weakened []!", M, src), 1, "\red You hear someone fall.", 2) - adjustBruteLoss(damage) - updatehealth() - else - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has attempted to punch []!", M, src), 1) - - if ("disarm") - if (!lying) - if (prob(5))//Very small chance to push an alien down. - Weaken(2) - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has pushed down []!", M, src), 1) - else - if (prob(50)) - drop_item() - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has disarmed []!", M, src), 1) - else - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has attempted to disarm []!", M, src), 1) - return - -/*Code for aliens attacking aliens. Because aliens act on a hivemind, I don't see them as very aggressive with each other. -As such, they can either help or harm other aliens. Help works like the human help command while harm is a simple nibble. -In all, this is a lot like the monkey code. /N -*/ - -/mob/living/carbon/alien/humanoid/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - if (!ticker) - M << "You cannot attack people before the game has started." - return - - if (istype(loc, /turf) && istype(loc.loc, /area/start)) - M << "No attacking people at spawn, you jackass." - return - - ..() - - switch(M.a_intent) - - if ("help") - sleeping = max(0,sleeping-5) - resting = 0 - AdjustParalysis(-3) - AdjustStunned(-3) - AdjustWeakened(-3) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M.name] nuzzles [] trying to wake it up!", src), 1) - - else - if (health > 0) - playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) - var/damage = rand(1, 3) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [M.name] has bit []!", src), 1) - adjustBruteLoss(damage) - updatehealth() - else - M << "\green [name] is too injured for that." - return - - -/mob/living/carbon/alien/humanoid/restrained() - if (handcuffed) - return 1 - return 0 - - -/mob/living/carbon/alien/humanoid/var/co2overloadtime = null -/mob/living/carbon/alien/humanoid/var/temperature_resistance = T0C+75 - -/mob/living/carbon/alien/humanoid/show_inv(mob/user as mob) - - user.set_machine(src) - var/dat = {" -
[name]
-

-
Left Hand: [(l_hand ? text("[]", l_hand) : "Nothing")] -
Right Hand: [(r_hand ? text("[]", r_hand) : "Nothing")] -
Head: [(head ? text("[]", head) : "Nothing")] -
(Exo)Suit: [(wear_suit ? text("[]", wear_suit) : "Nothing")] -
Empty Pouches -
Close -
"} - user << browse(dat, text("window=mob[name];size=340x480")) - onclose(user, "mob[name]") - return - - diff --git a/code/modules/mob/living/carbon/alien/humanoid/inventory.dm b/code/modules/mob/living/carbon/alien/humanoid/inventory.dm deleted file mode 100644 index 0e03bf6892..0000000000 --- a/code/modules/mob/living/carbon/alien/humanoid/inventory.dm +++ /dev/null @@ -1,54 +0,0 @@ -//unequip -/mob/living/carbon/alien/humanoid/u_equip(obj/item/W as obj) - if (W == wear_suit) - wear_suit = null - update_inv_wear_suit(0) - else if (W == head) - head = null - update_inv_head(0) - else if (W == r_store) - r_store = null - update_inv_pockets(0) - else if (W == l_store) - l_store = null - update_inv_pockets(0) - else if (W == r_hand) - r_hand = null - update_inv_r_hand(0) - else if (W == l_hand) - l_hand = null - update_inv_l_hand(0) - -/mob/living/carbon/alien/humanoid/attack_ui(slot_id) - var/obj/item/W = get_active_hand() - if(W) - if(!istype(W)) return - switch(slot_id) -// if("o_clothing") -// if("head") - if(slot_l_store) - if(l_store) - return - if(W.w_class > 3) - return - u_equip(W) - l_store = W - update_inv_pockets() - if(slot_r_store) - if(r_store) - return - if(W.w_class > 3) - return - u_equip(W) - r_store = W - update_inv_pockets() - else - switch(slot_id) - if(slot_wear_suit) - if(wear_suit) wear_suit.attack_alien(src) - if(slot_head) - if(head) head.attack_alien(src) - if(slot_l_store) - if(l_store) l_store.attack_alien(src) - if(slot_r_store) - if(r_store) r_store.attack_alien(src) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/humanoid/life.dm b/code/modules/mob/living/carbon/alien/humanoid/life.dm deleted file mode 100644 index defcc968d1..0000000000 --- a/code/modules/mob/living/carbon/alien/humanoid/life.dm +++ /dev/null @@ -1,453 +0,0 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/mob/living/carbon/alien/humanoid - oxygen_alert = 0 - phoron_alert = 0 - fire_alert = 0 - - var/temperature_alert = 0 - - -/mob/living/carbon/alien/humanoid/Life() - set invisibility = 0 - set background = 1 - - if (monkeyizing) - return - - ..() - - var/datum/gas_mixture/environment = loc.return_air() - - if (stat != DEAD) //still breathing - - //First, resolve location and get a breath - - if(air_master.current_cycle%4==2) - //Only try to take a breath every 4 seconds, unless suffocating - spawn(0) breathe() - - else //Still give containing object the chance to interact - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - - //Mutations and radiation - handle_mutations_and_radiation() - - //Chemicals in the body - handle_chemicals_in_body() - - //Disabilities - handle_disabilities() - - //Apparently, the person who wrote this code designed it so that - //blinded get reset each cycle and then get activated later in the - //code. Very ugly. I dont care. Moving this stuff here so its easy - //to find it. - blinded = null - - //Handle temperature/pressure differences between body and environment - handle_environment(environment) - - //stuff in the stomach - handle_stomach() - - - //Status updates, death etc. - handle_regular_status_updates() - update_canmove() - - // Grabbing - for(var/obj/item/weapon/grab/G in src) - G.process() - - if(client) - handle_regular_hud_updates() - - -/mob/living/carbon/alien/humanoid - proc/handle_disabilities() - if (disabilities & EPILEPSY) - if ((prob(1) && paralysis < 10)) - src << "\red You have a seizure!" - Paralyse(10) - if (disabilities & COUGHING) - if ((prob(5) && paralysis <= 1)) - drop_item() - spawn( 0 ) - emote("cough") - return - if (disabilities & TOURETTES) - if ((prob(10) && paralysis <= 1)) - Stun(10) - spawn( 0 ) - emote("twitch") - return - if (disabilities & NERVOUS) - if (prob(10)) - stuttering = max(10, stuttering) - - - proc/breathe() - if(reagents) - if(reagents.has_reagent("lexorin")) return - if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) return - - var/datum/gas_mixture/environment = loc.return_air() - var/datum/gas_mixture/breath - // HACK NEED CHANGING LATER - if(health < 0) - losebreath++ - - if(losebreath>0) //Suffocating so do not take a breath - losebreath-- - if (prob(75)) //High chance of gasping for air - spawn emote("gasp") - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - else - //First, check for air from internal atmosphere (using an air tank and mask generally) - breath = get_breath_from_internal(BREATH_VOLUME) - - //No breath from internal atmosphere so get breath from location - if(!breath) - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME) - else if(istype(loc, /turf/)) - var/breath_moles = 0 - /*if(environment.return_pressure() > ONE_ATMOSPHERE) - // Loads of air around (pressure effect will be handled elsewhere), so lets just take a enough to fill our lungs at normal atmos pressure (using n = Pv/RT) - breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature) - else*/ - // Not enough air around, take a percentage of what's there to model this properly - breath_moles = environment.total_moles*BREATH_PERCENTAGE - - breath = loc.remove_air(breath_moles) - - // Handle chem smoke effect -- Doohl - for(var/obj/effect/effect/smoke/chem/smoke in view(1, src)) - if(smoke.reagents.total_volume) - smoke.reagents.reaction(src, INGEST) - spawn(5) - if(smoke) - smoke.reagents.copy_to(src, 10) // I dunno, maybe the reagents enter the blood stream through the lungs? - break // If they breathe in the nasty stuff once, no need to continue checking - - - else //Still give containing object the chance to interact - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - - handle_breath(breath) - - if(breath) - loc.assume_air(breath) - - - proc/get_breath_from_internal(volume_needed) - if(internal) - if (!contents.Find(internal)) - internal = null - if (!wear_mask || !(wear_mask.flags & MASKINTERNALS) ) - internal = null - if(internal) - if (internals) - internals.icon_state = "internal1" - return internal.remove_air_volume(volume_needed) - else - if (internals) - internals.icon_state = "internal0" - return null - - proc/handle_breath(datum/gas_mixture/breath) - if(status_flags & GODMODE) - return - - if(!breath || (breath.total_moles == 0)) - //Aliens breathe in vaccuum - return 0 - - var/phoron_used = 0 - var/breath_pressure = (breath.total_moles * R_IDEAL_GAS_EQUATION * breath.temperature) / BREATH_VOLUME - - //Partial pressure of the phoron in our breath - var/Toxins_pp = (breath.gas["phoron"] / breath.total_moles) * breath_pressure - - if(Toxins_pp) // Detect phoron in air - - adjustToxLoss(breath.gas["phoron"] * 250) - phoron_alert = max(phoron_alert, 1) - - phoron_used = breath.gas["phoron"] - - else - phoron_alert = 0 - - //Breathe in phoron and out oxygen - breath.adjust_gas("phoron", -phoron_used) - breath.adjust_gas("oxygen", phoron_used) - - if(breath.temperature > (T0C+66) && !(COLD_RESISTANCE in mutations)) // Hot air hurts :( - if(prob(20)) - src << "\red You feel a searing heat in your lungs!" - fire_alert = max(fire_alert, 1) - else - fire_alert = 0 - - //Temporary fixes to the alerts. - - return 1 - - - - proc/adjust_body_temperature(current, loc_temp, boost) - var/temperature = current - var/difference = abs(current-loc_temp) //get difference - var/increments// = difference/10 //find how many increments apart they are - if(difference > 50) - increments = difference/5 - else - increments = difference/10 - var/change = increments*boost // Get the amount to change by (x per increment) - var/temp_change - if(current < loc_temp) - temperature = min(loc_temp, temperature+change) - else if(current > loc_temp) - temperature = max(loc_temp, temperature-change) - temp_change = (temperature - current) - return temp_change - - /* - proc/get_thermal_protection() - var/thermal_protection = 1.0 - //Handle normal clothing - if(head && (head.body_parts_covered & HEAD)) - thermal_protection += 0.5 - if(wear_suit && (wear_suit.body_parts_covered & UPPER_TORSO)) - thermal_protection += 0.5 - if(wear_suit && (wear_suit.body_parts_covered & LEGS)) - thermal_protection += 0.2 - if(wear_suit && (wear_suit.body_parts_covered & ARMS)) - thermal_protection += 0.2 - if(wear_suit && (wear_suit.body_parts_covered & HANDS)) - thermal_protection += 0.2 - if(wear_suit && (wear_suit.flags & SUITSPACE)) - thermal_protection += 3 - if(COLD_RESISTANCE in mutations) - thermal_protection += 5 - - return thermal_protection - - proc/add_fire_protection(var/temp) - var/fire_prot = 0 - if(head) - if(head.protective_temperature > temp) - fire_prot += (head.protective_temperature/10) - if(wear_mask) - if(wear_mask.protective_temperature > temp) - fire_prot += (wear_mask.protective_temperature/10) - if(wear_suit) - if(wear_suit.protective_temperature > temp) - fire_prot += (wear_suit.protective_temperature/10) - - - return fire_prot - */ - - proc/handle_chemicals_in_body() - - if(reagents) reagents.metabolize(src) - - if(FAT in mutations) - if(nutrition < 100) - if(prob(round((50 - nutrition) / 100))) - src << "\blue You feel fit again!" - mutations.Remove(FAT) -/* else - if(nutrition > 500) - if(prob(5 + round((nutrition - 200) / 2))) - src << "\red You suddenly feel blubbery!" - mutations.Add(FAT) - FUCK YOU FATCODE -Hawk */ - if (nutrition > 0) - nutrition -= HUNGER_FACTOR - - if (drowsyness) - drowsyness-- - eye_blurry = max(2, eye_blurry) - if (prob(5)) - sleeping += 1 - Paralyse(5) - - confused = max(0, confused - 1) - // decrement dizziness counter, clamped to 0 - if(resting) - dizziness = max(0, dizziness - 5) - jitteriness = max(0, jitteriness - 5) - else - dizziness = max(0, dizziness - 1) - jitteriness = max(0, jitteriness - 1) - - updatehealth() - - return //TODO: DEFERRED - - - proc/handle_regular_status_updates() - updatehealth() - - if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP - blinded = 1 - silent = 0 - else //ALIVE. LIGHTS ARE ON - if(health < config.health_threshold_dead || brain_op_stage == 4.0) - death() - blinded = 1 - stat = DEAD - silent = 0 - return 1 - - //UNCONSCIOUS. NO-ONE IS HOME - if( (getOxyLoss() > 50) || (config.health_threshold_crit > health) ) - if( health <= 20 && prob(1) ) - spawn(0) - emote("gasp") - if(!reagents.has_reagent("inaprovaline")) - adjustOxyLoss(1) - Paralyse(3) - - if(paralysis) - AdjustParalysis(-1) - blinded = 1 - stat = UNCONSCIOUS - else if(sleeping) - sleeping = max(sleeping-1, 0) - blinded = 1 - stat = UNCONSCIOUS - if( prob(10) && health ) - spawn(0) - emote("hiss") - //CONSCIOUS - else - stat = CONSCIOUS - - /* What in the living hell is this?*/ - if(move_delay_add > 0) - move_delay_add = max(0, move_delay_add - rand(1, 2)) - - //Eyes - if(sdisabilities & BLIND) //disabled-blind, doesn't get better on its own - blinded = 1 - else if(eye_blind) //blindness, heals slowly over time - eye_blind = max(eye_blind-1,0) - blinded = 1 - else if(eye_blurry) //blurry eyes heal slowly - eye_blurry = max(eye_blurry-1, 0) - - //Ears - if(sdisabilities & DEAF) //disabled-deaf, doesn't get better on its own - ear_deaf = max(ear_deaf, 1) - else if(ear_deaf) //deafness, heals slowly over time - ear_deaf = max(ear_deaf-1, 0) - else if(ear_damage < 25) //ear damage heals slowly under this threshold. otherwise you'll need earmuffs - ear_damage = max(ear_damage-0.05, 0) - - //Other - handle_statuses() - return 1 - - - proc/handle_regular_hud_updates() - - if (stat == 2 || (XRAY in mutations)) - sight |= SEE_TURFS - sight |= SEE_MOBS - sight |= SEE_OBJS - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_LEVEL_TWO - else if (stat != 2) - sight |= SEE_MOBS - sight &= ~SEE_TURFS - sight &= ~SEE_OBJS - see_in_dark = 4 - see_invisible = SEE_INVISIBLE_LEVEL_TWO - - if (healths) - if (stat != 2) - switch(health) - if(100 to INFINITY) - healths.icon_state = "health0" - if(75 to 100) - healths.icon_state = "health1" - if(50 to 75) - healths.icon_state = "health2" - if(25 to 50) - healths.icon_state = "health3" - if(0 to 25) - healths.icon_state = "health4" - else - healths.icon_state = "health5" - else - healths.icon_state = "health6" - - if(pullin) pullin.icon_state = "pull[pulling ? 1 : 0]" - - - if (toxin) toxin.icon_state = "tox[phoron_alert ? 1 : 0]" - if (oxygen) oxygen.icon_state = "oxy[oxygen_alert ? 1 : 0]" - if (fire) fire.icon_state = "fire[fire_alert ? 1 : 0]" - //NOTE: the alerts dont reset when youre out of danger. dont blame me, - //blame the person who coded them. Temporary fix added. - if (client) - client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired) - - if ((blind && stat != 2)) - if ((blinded)) - blind.layer = 18 - else - blind.layer = 0 - - if (disabilities & NEARSIGHTED) - client.screen += global_hud.vimpaired - - if (eye_blurry) - client.screen += global_hud.blurry - - if (druggy) - client.screen += global_hud.druggy - - if (stat != 2) - if (machine) - if (!( machine.check_eye(src) )) - reset_view(null) - else - if(client && !client.adminobs) - reset_view(null) - - return 1 - - proc/handle_stomach() - spawn(0) - for(var/mob/living/M in stomach_contents) - if(M.loc != src) - stomach_contents.Remove(M) - continue - if(istype(M, /mob/living/carbon) && stat != 2) - if(M.stat == 2) - M.death(1) - stomach_contents.Remove(M) - del(M) - continue - if(air_master.current_cycle%3==1) - if(!(status_flags & GODMODE)) - M.adjustBruteLoss(5) - nutrition += 10 - -/mob/living/carbon/alien/humanoid/handle_stunned() - if(stunned && !..()) - update_icons() - return stunned diff --git a/code/modules/mob/living/carbon/alien/humanoid/login.dm b/code/modules/mob/living/carbon/alien/humanoid/login.dm deleted file mode 100644 index 607a03fef0..0000000000 --- a/code/modules/mob/living/carbon/alien/humanoid/login.dm +++ /dev/null @@ -1,7 +0,0 @@ -/mob/living/carbon/alien/humanoid/Login() - ..() - update_hud() - if(!isturf(loc)) - client.eye = loc - client.perspective = EYE_PERSPECTIVE - return diff --git a/code/modules/mob/living/carbon/alien/humanoid/queen.dm b/code/modules/mob/living/carbon/alien/humanoid/queen.dm deleted file mode 100644 index 1b98392b81..0000000000 --- a/code/modules/mob/living/carbon/alien/humanoid/queen.dm +++ /dev/null @@ -1,92 +0,0 @@ -/mob/living/carbon/alien/humanoid/queen - name = "alien queen" - caste = "q" - maxHealth = 250 - health = 250 - icon_state = "alienq_s" - status_flags = CANPARALYSE - heal_rate = 5 - plasma_rate = 20 - - -/mob/living/carbon/alien/humanoid/queen/New() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - - //there should only be one queen - for(var/mob/living/carbon/alien/humanoid/queen/Q in living_mob_list) - if(Q == src) continue - if(Q.stat == DEAD) continue - if(Q.client) - name = "alien princess ([rand(1, 999)])" //if this is too cutesy feel free to change it/remove it. - break - - real_name = src.name - verbs.Add(/mob/living/carbon/alien/humanoid/proc/corrosive_acid,/mob/living/carbon/alien/humanoid/proc/neurotoxin,/mob/living/carbon/alien/humanoid/proc/resin) - verbs -= /mob/living/carbon/alien/verb/ventcrawl - ..() - - -/mob/living/carbon/alien/humanoid/queen - - handle_regular_hud_updates() - - ..() //-Yvarov - - if (src.healths) - if (src.stat != 2) - switch(health) - if(250 to INFINITY) - src.healths.icon_state = "health0" - if(175 to 250) - src.healths.icon_state = "health1" - if(100 to 175) - src.healths.icon_state = "health2" - if(50 to 100) - src.healths.icon_state = "health3" - if(0 to 50) - src.healths.icon_state = "health4" - else - src.healths.icon_state = "health5" - else - src.healths.icon_state = "health6" - - -//Queen verbs -/mob/living/carbon/alien/humanoid/queen/verb/lay_egg() - - set name = "Lay Egg (75)" - set desc = "Lay an egg to produce huggers to impregnate prey with." - set category = "Alien" - - if(locate(/obj/effect/alien/egg) in get_turf(src)) - src << "There's already an egg here." - return - - if(powerc(75,1))//Can't plant eggs on spess tiles. That's silly. - adjustToxLoss(-75) - for(var/mob/O in viewers(src, null)) - O.show_message(text("\green [src] has laid an egg!"), 1) - new /obj/effect/alien/egg(loc) - return - - -/mob/living/carbon/alien/humanoid/queen/large - icon = 'icons/mob/alienqueen.dmi' - icon_state = "queen_s" - pixel_x = -16 - -/mob/living/carbon/alien/humanoid/queen/large/update_icons() - 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 = "queen_sleep" - else icon_state = "queen_l" - for(var/image/I in overlays_lying) - overlays += I - else - icon_state = "queen_s" - for(var/image/I in overlays_standing) - overlays += I \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm deleted file mode 100644 index 57d0300b39..0000000000 --- a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm +++ /dev/null @@ -1,154 +0,0 @@ -//Xeno Overlays Indexes////////// -#define X_HEAD_LAYER 1 -#define X_SUIT_LAYER 2 -#define X_L_HAND_LAYER 3 -#define X_R_HAND_LAYER 4 -#define TARGETED_LAYER 5 -#define X_TOTAL_LAYERS 5 -///////////////////////////////// - -/mob/living/carbon/alien/humanoid - var/list/overlays_lying[X_TOTAL_LAYERS] - var/list/overlays_standing[X_TOTAL_LAYERS] - -/mob/living/carbon/alien/humanoid/update_icons() - 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(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 - if(m_intent == "run") icon_state = "alien[caste]_running" - else icon_state = "alien[caste]_s" - for(var/image/I in overlays_standing) - overlays += I - -/mob/living/carbon/alien/humanoid/regenerate_icons() - ..() - if (monkeyizing) return - - update_inv_head(0) - update_inv_wear_suit(0) - update_inv_r_hand(0) - update_inv_l_hand(0) - update_inv_pockets(0) - update_hud() - update_icons() - - -/mob/living/carbon/alien/humanoid/update_hud() - //TODO - if (client) -// if(other) client.screen |= hud_used.other //Not used -// else client.screen -= hud_used.other //Not used - client.screen |= contents - - - -/mob/living/carbon/alien/humanoid/update_inv_wear_suit(var/update_icons=1) - if(wear_suit) - var/t_state = wear_suit.item_state - if(!t_state) t_state = wear_suit.icon_state - var/image/lying = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]2") - var/image/standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]") - - if(wear_suit.blood_DNA) - var/t_suit = "suit" - if( istype(wear_suit, /obj/item/clothing/suit/armor) ) - t_suit = "armor" - lying.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "[t_suit]blood2") - standing.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "[t_suit]blood") - - //TODO - wear_suit.screen_loc = ui_alien_oclothing - if (istype(wear_suit, /obj/item/clothing/suit/straight_jacket)) - drop_from_inventory(handcuffed) - drop_r_hand() - drop_l_hand() - - overlays_lying[X_SUIT_LAYER] = lying - overlays_standing[X_SUIT_LAYER] = standing - else - overlays_lying[X_SUIT_LAYER] = null - overlays_standing[X_SUIT_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/alien/humanoid/update_inv_head(var/update_icons=1) - if (head) - var/t_state = head.item_state - if(!t_state) t_state = head.icon_state - var/image/lying = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]2") - var/image/standing = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "[t_state]") - if(head.blood_DNA) - lying.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "helmetblood2") - standing.overlays += image("icon" = 'icons/effects/blood.dmi', "icon_state" = "helmetblood") - head.screen_loc = ui_alien_head - overlays_lying[X_HEAD_LAYER] = lying - overlays_standing[X_HEAD_LAYER] = standing - else - overlays_lying[X_HEAD_LAYER] = null - overlays_standing[X_HEAD_LAYER] = null - if(update_icons) update_icons() - - -/mob/living/carbon/alien/humanoid/update_inv_pockets(var/update_icons=1) - if(l_store) l_store.screen_loc = ui_storage1 - if(r_store) r_store.screen_loc = ui_storage2 - if(update_icons) update_icons() - - -/mob/living/carbon/alien/humanoid/update_inv_r_hand(var/update_icons=1) - if(r_hand) - var/t_state = r_hand.item_state - if(!t_state) t_state = r_hand.icon_state - r_hand.screen_loc = ui_rhand - overlays_standing[X_R_HAND_LAYER] = image("icon" = 'icons/mob/items_righthand.dmi', "icon_state" = t_state) - else - overlays_standing[X_R_HAND_LAYER] = null - if(update_icons) update_icons() - -/mob/living/carbon/alien/humanoid/update_inv_l_hand(var/update_icons=1) - if(l_hand) - var/t_state = l_hand.item_state - if(!t_state) t_state = l_hand.icon_state - l_hand.screen_loc = ui_lhand - overlays_standing[X_L_HAND_LAYER] = image("icon" = 'icons/mob/items_lefthand.dmi', "icon_state" = t_state) - else - overlays_standing[X_L_HAND_LAYER] = null - if(update_icons) update_icons() - -//Call when target overlay should be added/removed -/mob/living/carbon/alien/humanoid/update_targeted(var/update_icons=1) - if (targeted_by && target_locked) - overlays_lying[TARGETED_LAYER] = target_locked - overlays_standing[TARGETED_LAYER] = target_locked - else if (!targeted_by && target_locked) - del(target_locked) - if (!targeted_by) - overlays_lying[TARGETED_LAYER] = null - overlays_standing[TARGETED_LAYER] = null - if(update_icons) update_icons() - -//Xeno Overlays Indexes////////// -#undef X_HEAD_LAYER -#undef X_SUIT_LAYER -#undef X_L_HAND_LAYER -#undef X_R_HAND_LAYER -#undef TARGETED_LAYER -#undef X_TOTAL_LAYERS diff --git a/code/modules/mob/living/carbon/alien/larva/death.dm b/code/modules/mob/living/carbon/alien/larva/death.dm deleted file mode 100644 index 27f49e3ad9..0000000000 --- a/code/modules/mob/living/carbon/alien/larva/death.dm +++ /dev/null @@ -1,15 +0,0 @@ -/mob/living/carbon/alien/larva/death(gibbed) - if(stat == DEAD) return - if(healths) healths.icon_state = "health6" - stat = DEAD - icon_state = "larva_dead" - - if(!gibbed) - update_canmove() - if(client) blind.layer = 0 - - tod = worldtime2text() //weasellos time of death patch - if(mind) mind.store_memory("Time of death: [tod]", 0) - living_mob_list -= src - - return ..(gibbed) diff --git a/code/modules/mob/living/carbon/alien/larva/inventory.dm b/code/modules/mob/living/carbon/alien/larva/inventory.dm deleted file mode 100644 index 076053b253..0000000000 --- a/code/modules/mob/living/carbon/alien/larva/inventory.dm +++ /dev/null @@ -1,3 +0,0 @@ -//can't unequip since it can't equip anything -/mob/living/carbon/alien/larva/u_equip(obj/item/W as obj) - return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm index 9f5640c69b..c811fd2b09 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva.dm @@ -1,375 +1,19 @@ /mob/living/carbon/alien/larva name = "alien larva" real_name = "alien larva" - icon_state = "larva0" - pass_flags = PASSTABLE + adult_form = /mob/living/carbon/human + speak_emote = list("hisses") + icon_state = "larva" + language = "Hivemind" + melee_damage_lower = 3 + melee_damage_upper = 6 + + amount_grown = 0 + max_grown = 200 maxHealth = 25 health = 25 - storedPlasma = 50 - max_plasma = 50 - 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() - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - if(name == "alien larva") - name = "alien larva ([rand(1, 1000)])" - real_name = name - regenerate_icons() ..() - -//This is fine, works the same as a human -/mob/living/carbon/alien/larva/Bump(atom/movable/AM as mob|obj, yes) - - spawn( 0 ) - if ((!( yes ) || now_pushing)) - return - now_pushing = 1 - if(ismob(AM)) - var/mob/tmob = AM - if(istype(tmob, /mob/living/carbon/human) && (FAT in tmob.mutations)) - if(prob(70)) - src << "\red You fail to push [tmob]'s fat ass out of the way." - now_pushing = 0 - return - if(!(tmob.status_flags & CANPUSH)) - now_pushing = 0 - return - tmob.LAssailant = src - - now_pushing = 0 - ..() - if (!( istype(AM, /atom/movable) )) - return - if (!( now_pushing )) - now_pushing = 1 - if (!( AM.anchored )) - var/t = get_dir(src, AM) - step(AM, t) - now_pushing = null - return - return - -//This needs to be fixed -/mob/living/carbon/alien/larva/Stat() - ..() - stat(null, "Progress: [amount_grown]/[max_grown]") - -/mob/living/carbon/alien/larva/adjustToxLoss(amount) - if(stat != DEAD) - amount_grown = min(amount_grown + 1, max_grown) - ..(amount) - - -/mob/living/carbon/alien/larva/ex_act(severity) - if(!blinded) - flick("flash", flash) - - var/b_loss = null - var/f_loss = null - switch (severity) - if (1.0) - b_loss += 500 - gib() - return - - if (2.0) - - b_loss += 60 - - f_loss += 60 - - ear_damage += 30 - ear_deaf += 120 - - if(3.0) - b_loss += 30 - if (prob(50)) - Paralyse(1) - ear_damage += 15 - ear_deaf += 60 - - adjustBruteLoss(b_loss) - adjustFireLoss(f_loss) - - updatehealth() - - - -/mob/living/carbon/alien/larva/blob_act() - if (stat == 2) - return - var/shielded = 0 - - var/damage = null - if (stat != 2) - damage = rand(10,30) - - if(shielded) - damage /= 4 - - //paralysis += 1 - - show_message("\red The blob attacks you!") - - adjustFireLoss(damage) - - updatehealth() - return - - -//can't equip anything -/mob/living/carbon/alien/larva/attack_ui(slot_id) - return - -/mob/living/carbon/alien/larva/meteorhit(O as obj) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message(text("\red [] has been hit by []", src, O), 1) - if (health > 0) - adjustBruteLoss((istype(O, /obj/effect/meteor/small) ? 10 : 25)) - adjustFireLoss(30) - - updatehealth() - return - - -/mob/living/carbon/alien/larva/attack_animal(mob/living/simple_animal/M as mob) - if(M.melee_damage_upper == 0) - M.emote("[M.friendly] [src]") - else - for(var/mob/O in viewers(src, null)) - O.show_message("\red [M] [M.attacktext] [src]!", 1) - var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - adjustBruteLoss(damage) - M.attack_log += text("\[[time_stamp()]\] attacked [src.name] ([src.ckey])") - src.attack_log += text("\[[time_stamp()]\] was attacked by [M.name] ([M.ckey])") - updatehealth() - - - -/mob/living/carbon/alien/larva/attack_paw(mob/living/carbon/monkey/M as mob) - if(!(istype(M, /mob/living/carbon/monkey))) return//Fix for aliens receiving double messages when attacking other aliens. - - if (!ticker) - M << "You cannot attack people before the game has started." - return - - if (istype(loc, /turf) && istype(loc.loc, /area/start)) - M << "No attacking people at spawn, you jackass." - return - ..() - - switch(M.a_intent) - - if ("help") - help_shake_act(M) - else - if (istype(wear_mask, /obj/item/clothing/mask/muzzle)) - return - if (health > 0) - playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [M.name] has bit [src]!"), 1) - adjustBruteLoss(rand(1, 3)) - updatehealth() - return - - -/mob/living/carbon/alien/larva/attack_slime(mob/living/carbon/slime/M as mob) - if (!ticker) - M << "You cannot attack people before the game has started." - return - - if(M.Victim) return // can't attack while eating! - - if (health > -100) - - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red The [M.name] glomps []!", src), 1) - - var/damage = rand(1, 3) - - if(M.is_adult) - damage = rand(20, 40) - else - damage = rand(5, 35) - - adjustBruteLoss(damage) - - - updatehealth() - - return - -/mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M as mob) - if (!ticker) - M << "You cannot attack people before the game has started." - return - - if (istype(loc, /turf) && istype(loc.loc, /area/start)) - M << "No attacking people at spawn, you jackass." - return - - ..() - - if(M.gloves && istype(M.gloves,/obj/item/clothing/gloves)) - var/obj/item/clothing/gloves/G = M.gloves - if(G.cell) - if(M.a_intent == "hurt")//Stungloves. Any contact will stun the alien. - if(G.cell.charge >= 2500) - G.cell.use(2500) - - Weaken(5) - if (stuttering < 5) - stuttering = 5 - Stun(5) - - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message("\red [src] has been touched with the stun gloves by [M]!", 1, "\red You hear someone fall.", 2) - return - else - M << "\red Not enough charge! " - return - - switch(M.a_intent) - - if ("help") - if (health > 0) - help_shake_act(M) - else - if (M.health >= -75.0) - if ((M.head && M.head.flags & 4) || (M.wear_mask && !( M.wear_mask.flags & 32 )) ) - M << "\blue Remove that mask!" - return - var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human( ) - O.source = M - O.target = src - O.s_loc = M.loc - O.t_loc = loc - O.place = "CPR" - requests += O - spawn( 0 ) - O.process() - return - - if ("grab") - if (M == src) - return - var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, M, src ) - - M.put_in_active_hand(G) - - grabbed_by += G - G.synch() - - LAssailant = M - - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) - - else - var/damage = rand(1, 9) - if (prob(90)) - if (HULK in M.mutations) - damage += 5 - spawn(0) - Paralyse(1) - step_away(src,M,15) - sleep(3) - step_away(src,M,15) - playsound(loc, "punch", 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has punched []!", M, src), 1) - if (damage > 4.9) - Weaken(rand(10,15)) - for(var/mob/O in viewers(M, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has weakened []!", M, src), 1, "\red You hear someone fall.", 2) - adjustBruteLoss(damage) - updatehealth() - else - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has attempted to punch []!", M, src), 1) - return - -/mob/living/carbon/alien/larva/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - if (!ticker) - M << "You cannot attack people before the game has started." - return - - if (istype(loc, /turf) && istype(loc.loc, /area/start)) - M << "No attacking people at spawn, you jackass." - return - - ..() - - switch(M.a_intent) - - if ("help") - sleeping = max(0,sleeping-5) - resting = 0 - AdjustParalysis(-3) - AdjustStunned(-3) - AdjustWeakened(-3) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M.name] nuzzles [] trying to wake it up!", src), 1) - - else - if (health > 0) - playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) - var/damage = rand(1, 3) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [M.name] has bit []!", src), 1) - adjustBruteLoss(damage) - updatehealth() - else - M << "\green [name] is too injured for that." - return - -/mob/living/carbon/alien/larva/restrained() - return 0 - -/mob/living/carbon/alien/larva/var/co2overloadtime = null -/mob/living/carbon/alien/larva/var/temperature_resistance = T0C+75 - -// new damage icon system -// now constructs damage icon for each organ from mask * damage field - - -/mob/living/carbon/alien/larva/show_inv(mob/user as mob) - - user.set_machine(src) - var/dat = {" -
[name]
-


-
Close -
"} - user << browse(dat, text("window=mob[name];size=340x480")) - onclose(user, "mob[name]") - return - -/* Commented out because it's duplicated in life.dm -/mob/living/carbon/alien/larva/proc/grow() // Larvae can grow into full fledged Xenos if they survive long enough -- TLE - if(icon_state == "larva_l" && !canmove) // This is a shit death check. It is made of shit and death. Fix later. - return - else - var/mob/living/carbon/alien/humanoid/A = new(loc) - A.key = key - del(src) */ \ No newline at end of file + add_language("Rootspeak") \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm index 9bb6ae4376..8d40ef9d5a 100644 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ b/code/modules/mob/living/carbon/alien/larva/life.dm @@ -1,369 +1,12 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -/mob/living/carbon/alien/larva - - var/temperature_alert = 0 - - -/mob/living/carbon/alien/larva/Life() - set invisibility = 0 - set background = 1 - - if (monkeyizing) - return - - ..() - var/datum/gas_mixture/enviroment = loc.return_air() - if (stat != DEAD) //still breathing - - // GROW! - if(amount_grown < max_grown) - amount_grown++ - - //First, resolve location and get a breath - if(air_master.current_cycle%4==2) - //Only try to take a breath every 4 seconds, unless suffocating - spawn(0) breathe() - else //Still give containing object the chance to interact - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - //Mutations and radiation - handle_mutations_and_radiation() - - //Chemicals in the body - handle_chemicals_in_body() - - - //Apparently, the person who wrote this code designed it so that - //blinded get reset each cycle and then get activated later in the - //code. Very ugly. I dont care. Moving this stuff here so its easy - //to find it. - blinded = null - - //Handle temperature/pressure differences between body and environment - handle_environment(enviroment) - - //stuff in the stomach - //handle_stomach() - - //Status updates, death etc. - handle_regular_status_updates() - update_canmove() - - // Grabbing - 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() - - -/mob/living/carbon/alien/larva - - proc/breathe() - - if(reagents.has_reagent("lexorin")) return - if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) return - - var/datum/gas_mixture/environment = loc.return_air() - var/datum/gas_mixture/breath - // HACK NEED CHANGING LATER - if(health < 0) - losebreath++ - - if(losebreath>0) //Suffocating so do not take a breath - losebreath-- - if (prob(75)) //High chance of gasping for air - spawn emote("gasp") - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - else - //First, check for air from internal atmosphere (using an air tank and mask generally) - breath = get_breath_from_internal(BREATH_VOLUME) - - //No breath from internal atmosphere so get breath from location - if(!breath) - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME) - else if(istype(loc, /turf/)) - var/breath_moles = 0 - /*if(environment.return_pressure() > ONE_ATMOSPHERE) - // Loads of air around (pressure effect will be handled elsewhere), so lets just take a enough to fill our lungs at normal atmos pressure (using n = Pv/RT) - breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature) - else*/ - // Not enough air around, take a percentage of what's there to model this properly - breath_moles = environment.total_moles*BREATH_PERCENTAGE - - breath = loc.remove_air(breath_moles) - - // Handle chem smoke effect -- Doohl - for(var/obj/effect/effect/smoke/chem/smoke in view(1, src)) - if(smoke.reagents.total_volume) - smoke.reagents.reaction(src, INGEST) - spawn(5) - if(smoke) - smoke.reagents.copy_to(src, 10) // I dunno, maybe the reagents enter the blood stream through the lungs? - break // If they breathe in the nasty stuff once, no need to continue checking - - - else //Still give containing object the chance to interact - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - - handle_breath(breath) - - if(breath) - loc.assume_air(breath) - - - proc/get_breath_from_internal(volume_needed) - if(internal) - if (!contents.Find(internal)) - internal = null - if (!wear_mask || !(wear_mask.flags & MASKINTERNALS) ) - internal = null - if(internal) - if (internals) - internals.icon_state = "internal1" - return internal.remove_air_volume(volume_needed) - else - if (internals) - internals.icon_state = "internal0" - return null - - proc/handle_breath(datum/gas_mixture/breath) - if(status_flags & GODMODE) - return - - if(!breath || (breath.total_moles == 0)) - //Aliens breathe in vaccuum - return 0 - - var/phoron_used = 0 - var/breath_pressure = (breath.total_moles * R_IDEAL_GAS_EQUATION * breath.temperature) / BREATH_VOLUME - - //Partial pressure of the phoron in our breath - var/Toxins_pp = (breath.gas["phoron"] / breath.total_moles) * breath_pressure - - if(Toxins_pp) // Detect phoron in air - - adjustToxLoss(breath.gas["phoron"] * 250) - phoron_alert = max(phoron_alert, 1) - - phoron_used = breath.gas["phoron"] - - else - phoron_alert = 0 - - //Breathe in phoron and out oxygen - breath.adjust_gas("phoron", -phoron_used) - breath.adjust_gas("oxygen", phoron_used) - - if(breath.temperature > (T0C+66) && !(COLD_RESISTANCE in mutations)) // Hot air hurts :( - if(prob(20)) - src << "\red You feel a searing heat in your lungs!" - fire_alert = max(fire_alert, 1) - else - fire_alert = 0 - - //Temporary fixes to the alerts. - - return 1 - - - proc/handle_chemicals_in_body() - if(reagents) reagents.metabolize(src) - - if(FAT in mutations) - if(nutrition < 100) - if(prob(round((50 - nutrition) / 100))) - src << "\blue You feel fit again!" - mutations.Add(FAT) -/* else - if(nutrition > 500) - if(prob(5 + round((nutrition - max_grown) / 2))) - src << "\red You suddenly feel blubbery!" - mutations.Add(FAT) -FUCK YOU MORE FAT CODE -Hawk*/ - if (nutrition > 0) - nutrition-= HUNGER_FACTOR - - if (drowsyness) - drowsyness-- - eye_blurry = max(2, eye_blurry) - if (prob(5)) - sleeping += 1 - Paralyse(5) - - confused = max(0, confused - 1) - // decrement dizziness counter, clamped to 0 - if(resting) - dizziness = max(0, dizziness - 5) - jitteriness = max(0, jitteriness - 5) - else - dizziness = max(0, dizziness - 1) - jitteriness = max(0, jitteriness - 1) - - updatehealth() - - return //TODO: DEFERRED - - proc/handle_regular_status_updates() - updatehealth() - - if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP - blinded = 1 - silent = 0 - else //ALIVE. LIGHTS ARE ON - if(health < -25 || brain_op_stage == 4.0) - death() - blinded = 1 - silent = 0 - return 1 - - //UNCONSCIOUS. NO-ONE IS HOME - if( (getOxyLoss() > 25) || (0 > health) ) - //if( health <= 20 && prob(1) ) - // spawn(0) - // emote("gasp") - if(!reagents.has_reagent("inaprovaline")) - adjustOxyLoss(1) - Paralyse(3) - - if(paralysis) - AdjustParalysis(-2) - blinded = 1 - stat = UNCONSCIOUS - else if(sleeping) - sleeping = max(sleeping-1, 0) - blinded = 1 - stat = UNCONSCIOUS - if( prob(10) && health ) - spawn(0) - emote("hiss_") - //CONSCIOUS - else - stat = CONSCIOUS - - /* What in the living hell is this?*/ - if(move_delay_add > 0) - move_delay_add = max(0, move_delay_add - rand(1, 2)) - - //Eyes - if(sdisabilities & BLIND) //disabled-blind, doesn't get better on its own - blinded = 1 - else if(eye_blind) //blindness, heals slowly over time - eye_blind = max(eye_blind-1,0) - blinded = 1 - else if(eye_blurry) //blurry eyes heal slowly - eye_blurry = max(eye_blurry-1, 0) - - //Ears - if(sdisabilities & DEAF) //disabled-deaf, doesn't get better on its own - ear_deaf = max(ear_deaf, 1) - else if(ear_deaf) //deafness, heals slowly over time - ear_deaf = max(ear_deaf-1, 0) - else if(ear_damage < 25) //ear damage heals slowly under this threshold. - ear_damage = max(ear_damage-0.05, 0) - - //Other - handle_statuses() - return 1 - - - proc/handle_regular_hud_updates() - - if (stat == 2 || (XRAY in mutations)) - sight |= SEE_TURFS - sight |= SEE_MOBS - sight |= SEE_OBJS - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_LEVEL_TWO - else if (stat != 2) - sight |= SEE_MOBS - sight &= ~SEE_TURFS - sight &= ~SEE_OBJS - see_in_dark = 4 - see_invisible = SEE_INVISIBLE_LEVEL_TWO - - if (healths) - if (stat != 2) - switch(health) - if(25 to INFINITY) - healths.icon_state = "health0" - if(19 to 25) - healths.icon_state = "health1" - if(13 to 19) - healths.icon_state = "health2" - if(7 to 13) - healths.icon_state = "health3" - if(0 to 7) - healths.icon_state = "health4" - else - healths.icon_state = "health5" - else - healths.icon_state = "health6" - - if(pullin) pullin.icon_state = "pull[pulling ? 1 : 0]" - - - if (toxin) toxin.icon_state = "tox[phoron_alert ? 1 : 0]" - if (oxygen) oxygen.icon_state = "oxy[oxygen_alert ? 1 : 0]" - if (fire) fire.icon_state = "fire[fire_alert ? 1 : 0]" - //NOTE: the alerts dont reset when youre out of danger. dont blame me, - //blame the person who coded them. Temporary fix added. - if (client) - client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired) - - if ((blind && stat != 2)) - if ((blinded)) - blind.layer = 18 - else - blind.layer = 0 - - if (disabilities & NEARSIGHTED) - client.screen += global_hud.vimpaired - - if (eye_blurry) - client.screen += global_hud.blurry - - if (druggy) - client.screen += global_hud.druggy - - if (stat != 2) - if (machine) - if (!( machine.check_eye(src) )) - reset_view(null) - else - if(client && !client.adminobs) - reset_view(null) - - return 1 - - proc/handle_random_events() - return - - - proc/handle_stomach() - spawn(0) - for(var/mob/living/M in stomach_contents) - if(M.loc != src) - stomach_contents.Remove(M) - continue - if(istype(M, /mob/living/carbon) && stat != 2) - if(M.stat == 2) - M.death(1) - stomach_contents.Remove(M) - del(M) - continue - if(air_master.current_cycle%3==1) - if(!(M.status_flags & GODMODE)) - M.adjustBruteLoss(5) - nutrition += 10 \ No newline at end of file +//Larvae regenerate health and nutrition from plasma and alien weeds. +/mob/living/carbon/alien/larva/handle_environment(var/datum/gas_mixture/environment) + + if(!environment) return + + var/turf/T = get_turf(src) + if(environment.gas["phoron"] > 0 || (T && locate(/obj/effect/alien/weeds) in T.contents)) + update_progression() + adjustBruteLoss(-1) + adjustFireLoss(-1) + adjustToxLoss(-1) + adjustOxyLoss(-1) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/larva/login.dm b/code/modules/mob/living/carbon/alien/larva/login.dm deleted file mode 100644 index 33808a4d96..0000000000 --- a/code/modules/mob/living/carbon/alien/larva/login.dm +++ /dev/null @@ -1,3 +0,0 @@ -/mob/living/carbon/alien/larva/Login() - return ..() - diff --git a/code/modules/mob/living/carbon/alien/larva/powers.dm b/code/modules/mob/living/carbon/alien/larva/powers.dm deleted file mode 100644 index a1806692df..0000000000 --- a/code/modules/mob/living/carbon/alien/larva/powers.dm +++ /dev/null @@ -1,56 +0,0 @@ - -/mob/living/carbon/alien/larva/verb/hide() - set name = "Hide" - set desc = "Allows to hide beneath tables or certain items. Toggled on or off." - set category = "Alien" - - if(stat != CONSCIOUS) - return - - if (layer != TURF_LAYER+0.2) - layer = TURF_LAYER+0.2 - src << text("\green You are now hiding.") - for(var/mob/O in oviewers(src, null)) - if ((O.client && !( O.blinded ))) - O << text("[] scurries to the ground!", src) - else - layer = MOB_LAYER - src << text("\green You have stopped hiding.") - for(var/mob/O in oviewers(src, null)) - if ((O.client && !( O.blinded ))) - O << text("[] slowly peaks up from the ground...", src) - -/mob/living/carbon/alien/larva/verb/evolve() - set name = "Evolve" - set desc = "Evolve into a fully grown Alien." - set category = "Alien" - - if(stat != CONSCIOUS) - return - - if(handcuffed || legcuffed) - src << "\red You cannot evolve when you are cuffed." - - if(amount_grown >= max_grown) //TODO ~Carn - //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 - switch(alien_caste) - if("Hunter") - new_xeno = new /mob/living/carbon/alien/humanoid/hunter(loc) - if("Sentinel") - new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(loc) - if("Drone") - new_xeno = new /mob/living/carbon/alien/humanoid/drone(loc) - if(mind) mind.transfer_to(new_xeno) - del(src) - return - else - src << "\red You are not fully grown." - return diff --git a/code/modules/mob/living/carbon/alien/larva/progression.dm b/code/modules/mob/living/carbon/alien/larva/progression.dm new file mode 100644 index 0000000000..50d75af813 --- /dev/null +++ b/code/modules/mob/living/carbon/alien/larva/progression.dm @@ -0,0 +1,17 @@ +/mob/living/carbon/alien/larva/update_progression() + if(amount_grown < max_grown) + amount_grown++ + return + +/mob/living/carbon/alien/larva/confirm_evolution() + + 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") + return alien_caste ? "Xenomorph [alien_caste]" : null + +/mob/living/carbon/alien/larva/show_evolution_blurb() + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/larva/update_icons.dm b/code/modules/mob/living/carbon/alien/larva/update_icons.dm deleted file mode 100644 index 3ab3fb3b38..0000000000 --- a/code/modules/mob/living/carbon/alien/larva/update_icons.dm +++ /dev/null @@ -1,22 +0,0 @@ - -/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/life.dm b/code/modules/mob/living/carbon/alien/life.dm new file mode 100644 index 0000000000..7a51069fe8 --- /dev/null +++ b/code/modules/mob/living/carbon/alien/life.dm @@ -0,0 +1,191 @@ +// Alien larva are quite simple. +/mob/living/carbon/alien/Life() + + set invisibility = 0 + set background = 1 + + if (monkeyizing) return + if(!loc) return + + ..() + + if (stat != DEAD) //still breathing + + // GROW! + update_progression() + + // Radiation. + handle_mutations_and_radiation() + + // Chemicals in the body + handle_chemicals_in_body() + + blinded = null + + if(loc) + handle_environment(loc.return_air()) + + //Status updates, death etc. + handle_regular_status_updates() + update_canmove() + update_icons() + + if(client) + handle_regular_hud_updates() + +/mob/living/carbon/alien/proc/handle_chemicals_in_body() + return // Nothing yet. Maybe check it out at a later date. + +/mob/living/carbon/alien/proc/handle_mutations_and_radiation() + + // Currently both Dionaea and larvae like to eat radiation, so I'm defining the + // rad absorbtion here. This will need to be changed if other baby aliens are added. + + if(!radiation) + return + + var/rads = radiation/25 + radiation -= rads + nutrition += rads + heal_overall_damage(rads,rads) + adjustOxyLoss(-(rads)) + adjustToxLoss(-(rads)) + return + +/mob/living/carbon/alien/proc/handle_regular_status_updates() + + if(status_flags & GODMODE) return 0 + + if(stat == DEAD) + blinded = 1 + silent = 0 + else + updatehealth() + + if(health <= 0) + death() + blinded = 1 + silent = 0 + return 1 + + if(paralysis) + AdjustParalysis(-1) + blinded = 1 + stat = UNCONSCIOUS + if(halloss > 0) + adjustHalLoss(-3) + else if(sleeping) + + adjustHalLoss(-3) + if (mind) + if((mind.active && client != null) || immune_to_ssd) + sleeping = max(sleeping-1, 0) + blinded = 1 + stat = UNCONSCIOUS + + else if(resting) + if(halloss > 0) + adjustHalLoss(-3) + + else + stat = CONSCIOUS + if(halloss > 0) + adjustHalLoss(-1) + + // Eyes and blindness. + if(!has_eyes()) + eye_blind = 1 + blinded = 1 + eye_blurry = 1 + else if(eye_blind) + eye_blind = max(eye_blind-1,0) + blinded = 1 + else if(eye_blurry) + eye_blurry = max(eye_blurry-1, 0) + + //Ears + if(sdisabilities & DEAF) //disabled-deaf, doesn't get better on its own + ear_deaf = max(ear_deaf, 1) + else if(ear_deaf) //deafness, heals slowly over time + ear_deaf = max(ear_deaf-1, 0) + ear_damage = max(ear_damage-0.05, 0) + + update_icons() + + return 1 + +/mob/living/carbon/alien/proc/handle_regular_hud_updates() + + if (stat == 2 || (XRAY in src.mutations)) + sight |= SEE_TURFS + sight |= SEE_MOBS + sight |= SEE_OBJS + see_in_dark = 8 + see_invisible = SEE_INVISIBLE_LEVEL_TWO + else if (stat != 2) + sight &= ~SEE_TURFS + sight &= ~SEE_MOBS + sight &= ~SEE_OBJS + see_in_dark = 2 + see_invisible = SEE_INVISIBLE_LIVING + + if (healths) + if (stat != 2) + switch(health) + if(100 to INFINITY) + healths.icon_state = "health0" + if(80 to 100) + healths.icon_state = "health1" + if(60 to 80) + healths.icon_state = "health2" + if(40 to 60) + healths.icon_state = "health3" + if(20 to 40) + healths.icon_state = "health4" + if(0 to 20) + healths.icon_state = "health5" + else + healths.icon_state = "health6" + else + healths.icon_state = "health7" + + if(pullin) + pullin.icon_state = "pull[pulling ? 1 : 0]" + + if (client) + client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired) + + if ((blind && stat != 2)) + if ((blinded)) + blind.layer = 18 + else + blind.layer = 0 + if (disabilities & NEARSIGHTED) + client.screen += global_hud.vimpaired + if (eye_blurry) + client.screen += global_hud.blurry + if (druggy) + client.screen += global_hud.druggy + + if (stat != 2) + if (machine) + if (!( machine.check_eye(src) )) + reset_view(null) + else + if(client && !client.adminobs) + reset_view(null) + + return 1 + +/mob/living/carbon/alien/proc/handle_environment(var/datum/gas_mixture/environment) + // Both alien subtypes survive in vaccum and suffer in high temperatures, + // so I'll just define this once, for both (see radiation comment above) + if(!environment) return + + if(environment.temperature > (T0C+66)) + adjustFireLoss((environment.temperature - (T0C+66))/5) // Might be too high, check in testing. + if (fire) fire.icon_state = "fire2" + if(prob(20)) + src << "\red You feel a searing heat!" + else + if (fire) fire.icon_state = "fire0" diff --git a/code/modules/mob/living/carbon/alien/login.dm b/code/modules/mob/living/carbon/alien/login.dm deleted file mode 100644 index 9701338e4b..0000000000 --- a/code/modules/mob/living/carbon/alien/login.dm +++ /dev/null @@ -1,4 +0,0 @@ -/mob/living/carbon/alien/humanoid/Login() - ..() - AddInfectionImages() - return diff --git a/code/modules/mob/living/carbon/alien/logout.dm b/code/modules/mob/living/carbon/alien/logout.dm deleted file mode 100644 index c0734cd21f..0000000000 --- a/code/modules/mob/living/carbon/alien/logout.dm +++ /dev/null @@ -1,4 +0,0 @@ -/mob/living/carbon/alien/humanoid/Logout() - ..() - RemoveInfectionImages() - return diff --git a/code/modules/mob/living/carbon/alien/powers.dm b/code/modules/mob/living/carbon/alien/powers.dm deleted file mode 100644 index d9452a8d79..0000000000 --- a/code/modules/mob/living/carbon/alien/powers.dm +++ /dev/null @@ -1,5 +0,0 @@ -/mob/living/carbon/alien/verb/ventcrawl() // -- TLE - set name = "Crawl through vent" - set desc = "Enter an air vent and crawl through the pipe system." - set category = "Alien" - handle_ventcrawl() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/progression.dm b/code/modules/mob/living/carbon/alien/progression.dm new file mode 100644 index 0000000000..fe3ec5d2d5 --- /dev/null +++ b/code/modules/mob/living/carbon/alien/progression.dm @@ -0,0 +1,50 @@ +/mob/living/carbon/alien/verb/evolve() + + set name = "Evolve" + set desc = "Evolve into your adult form." + set category = "Abilities" + + if(stat != CONSCIOUS) + return + + if(!adult_form) + verbs -= /mob/living/carbon/alien/verb/evolve + return + + if(handcuffed || legcuffed) + src << "\red You cannot evolve when you are cuffed." + return + + if(amount_grown < max_grown) + src << "\red You are not fully grown." + return + + // confirm_evolution() handles choices and other specific requirements. + var/new_species = confirm_evolution() + if(!new_species || !adult_form ) + return + + var/mob/living/carbon/human/adult = new adult_form(get_turf(src)) + adult.set_species(new_species) + show_evolution_blurb() + + if(mind) + mind.transfer_to(adult) + else + adult.key = src.key + + for (var/obj/item/W in src.contents) + src.drop_from_inventory(W) + + for(var/datum/language/L in languages) + adult.add_language(L.name) + del(src) + +/mob/living/carbon/alien/proc/update_progression() + return + +/mob/living/carbon/alien/proc/confirm_evolution() + return + +/mob/living/carbon/alien/proc/show_evolution_blurb() + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/say.dm b/code/modules/mob/living/carbon/alien/say.dm index 28947ac55e..f822078885 100644 --- a/code/modules/mob/living/carbon/alien/say.dm +++ b/code/modules/mob/living/carbon/alien/say.dm @@ -1,68 +1,34 @@ -/mob/living/carbon/alien/say(var/message) - - if (silent) - return - - if (length(message) >= 2) - if (department_radio_keys[copytext(message, 1, 3)] == "alientalk") - message = copytext(message, 3) - message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) - if (stat == 2) - return say_dead(message) - else - alien_talk(message) - else - if (copytext(message, 1, 2) != "*" && !stat) - playsound(loc, "hiss", 25, 1, 1)//So aliens can hiss while they hiss yo/N - return ..(message) - else - -/mob/living/proc/alien_talk(var/message) - - log_say("[key_name(src)] : [message]") - message = trim(message) - - if (!message) - return - - var/message_a = say_quote(message) - var/rendered = "Hivemind, [name] [message_a]" - for (var/mob/living/S in player_list) - if(!S.stat) - if(S.alien_talk_understand) - if(S.alien_talk_understand == alien_talk_understand) - S.show_message(rendered, 2) - else if (S.hivecheck()) - S.show_message(rendered, 2) - - var/list/listening = hearers(1, src) - listening -= src - listening += src - - var/list/heard = list() - for (var/mob/M in listening) - if(!istype(M, /mob/living/carbon/alien) && !M.alien_talk_understand) - heard += M - - - if (length(heard)) - var/message_b - - message_b = "hsssss" - message_b = say_quote(message_b) - message_b = "[message_b]" - - rendered = "[voice_name] [message_b]" - - for (var/mob/M in heard) - M.show_message(rendered, 2) - - message = say_quote(message) - - rendered = "Hivemind, [name] [message_a]" - - for (var/mob/M in player_list) - if (istype(M, /mob/new_player)) - continue - if (M.stat > 1) - M.show_message(rendered, 2) \ No newline at end of file +/mob/living/carbon/alien/say(var/message) + var/verb = "says" + var/message_range = world.view + + if(client) + if(client.prefs.muted & MUTE_IC) + src << "\red You cannot speak in IC (Muted)." + return + + message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) + + if(stat == 2) + return say_dead(message) + + var/datum/language/speaking = null + + if(length(message) >= 2) + var/channel_prefix = copytext(message, 1 ,3) + if(languages.len) + for(var/datum/language/L in languages) + if(lowertext(channel_prefix) == ":[L.key]") + verb = L.speech_verb + speaking = L + break + + if(speaking) + message = trim(copytext(message,3)) + + message = capitalize(trim_left(message)) + + if(!message || stat) + return + + ..(message, speaking, verb, null, null, message_range, null) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/special/_main.dm b/code/modules/mob/living/carbon/alien/special/_main.dm deleted file mode 100644 index eb5594f3c9..0000000000 --- a/code/modules/mob/living/carbon/alien/special/_main.dm +++ /dev/null @@ -1,71 +0,0 @@ -//XCOM alien code -//By Xerif (Donated by the Foundation project, ss13.org) - -/mob/living/carbon/alien/humanoid/special - has_fine_manipulation = 1 - var/xcom_state - - New() - ..() - spawn (1) - var/datum/reagents/R = new/datum/reagents(100) - reagents = R - R.my_atom = src - - mind = new() - mind.key = key - mind.special_role = "Special Xeno" - - name = "[name] ([rand(1, 1000)])" - real_name = name - - src.stand_icon = new /icon('xcomalien.dmi', xcom_state) - src.lying_icon = new /icon('xcomalien.dmi', xcom_state) - src.icon = src.stand_icon - - remove_special_verbs() - - rebuild_appearance() - - death(gibbed) - ..() - spawn(5) - gib() - - Stat() - statpanel("Status") - if (src.client && src.client.holder) - stat(null, "([x], [y], [z])") - - stat(null, "Intent: [src.a_intent]") - stat(null, "Move Mode: [src.m_intent]") - - if (src.client.statpanel == "Status") - if (src.internal) - if (!src.internal.air_contents) - del(src.internal) - else - stat("Internal Atmosphere Info", src.internal.name) - stat("Tank Pressure", src.internal.air_contents.return_pressure()) - stat("Distribution Pressure", src.internal.distribute_pressure) - return - - alien_talk() - if(istype(src, /mob/living/carbon/alien/humanoid/special/etheral)) - ..() - return - if(istype(src, /mob/living/carbon/alien/humanoid/special/sectoid)) - ..() - return - return - -/mob/living/carbon/alien/humanoid/special/proc/xcom_attack() - return - -/mob/living/carbon/alien/humanoid/special/proc/remove_special_verbs() - verbs -= /mob/living/carbon/alien/humanoid/verb/plant - verbs -= /mob/living/carbon/alien/humanoid/verb/ActivateHuggers - verbs -= /mob/living/carbon/alien/humanoid/verb/whisp - verbs -= /mob/living/carbon/alien/humanoid/verb/transfer_plasma - verbs -= /mob/living/carbon/alien/humanoid/verb/corrode - return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/special/snakeman.dm b/code/modules/mob/living/carbon/alien/special/snakeman.dm deleted file mode 100644 index 7aa7b9d5db..0000000000 --- a/code/modules/mob/living/carbon/alien/special/snakeman.dm +++ /dev/null @@ -1,59 +0,0 @@ -/mob/living/carbon/alien/humanoid/special/snakeman - name = "Snakeman" - desc = "This race developed in an extremely hostile environment. They are extremely tough and can resist extreme temperature variations. Their mobility depends on a snake-like giant \"foot\" which protects all the vital organs. " - xcom_state = "snake" - - movement_delay() - return 4 - -/mob/living/carbon/alien/humanoid/special/snakeman/verb/lay_egg(mob/living/carbon/human/M as mob) - set name = "Impregnate" - set desc = "Lays an egg on a corpse, allowing the egg to feed." - set category = "Snakeman" - - set src = view(0) - - if(stat) - return - - if(!M) - return - - if(!M.client) - src << "This being is missing a brain." - return - - visible_message("[src] extends a probiscis and stabs it into [M]") - - if (!do_mob(usr, M, 50)) - usr << "\red The injection of the egg has been interrupted!" - return - - if(M.client) - M.client.mob = new/mob/living/carbon/alien/humanoid/special/snakeman(new/obj/effect/snake_egg(src.loc)) - visible_message("[src] injects [M] with an egg.") - visible_message("The egg absorbs [M]") - M.mutations |= NOCLONE - M.update_body() - M.death() - else - src << "This being is missing a brain." - - return - -/obj/effect/snake_egg - name = "Egg" - icon = 'icons/mob/alien.dmi' - icon_state = "egg" - density = 1 - anchored = 1 - - New() - ..() - - spawn(300) - for(var/mob/M in src) - M.loc = src.loc - icon_state = "egg_hatched" - density = 0 - return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/update_icons.dm b/code/modules/mob/living/carbon/alien/update_icons.dm new file mode 100644 index 0000000000..7bb90a4d9e --- /dev/null +++ b/code/modules/mob/living/carbon/alien/update_icons.dm @@ -0,0 +1,20 @@ +/mob/living/carbon/alien/regenerate_icons() + overlays = list() + update_icons() + +/mob/living/carbon/alien/update_icons() + + var/state = 0 + if(amount_grown > max_grown*0.75) + state = 2 + else if(amount_grown > max_grown*0.25) + state = 1 + + if(stat == DEAD) + icon_state = "[initial(icon_state)][state]_dead" + else if (stunned) + icon_state = "[initial(icon_state)][state]_stun" + else if(lying || resting) + icon_state = "[initial(icon_state)][state]_sleep" + else + icon_state = "[initial(icon_state)][state]" diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm index 6959828f9b..ae2ed01192 100644 --- a/code/modules/mob/living/carbon/brain/MMI.dm +++ b/code/modules/mob/living/carbon/brain/MMI.dm @@ -22,7 +22,7 @@ var/obj/mecha = null//This does not appear to be used outside of reference in mecha.dm. attackby(var/obj/item/O as obj, var/mob/user as mob) - if(istype(O,/obj/item/brain) && !brainmob) //Time to stick a brain in it --NEO + if(istype(O,/obj/item/organ/brain) && !brainmob) //Time to stick a brain in it --NEO if(!O:brainmob) user << "\red You aren't sure where this brain came from, but you're pretty sure it's a useless brain." return @@ -61,6 +61,7 @@ return ..() + //TODO: ORGAN REMOVAL UPDATE. Make the brain remain in the MMI so it doesn't lose organ data. attack_self(mob/user as mob) if(!brainmob) user << "\red You upend the MMI, but there's nothing in it." @@ -68,7 +69,7 @@ user << "\red You upend the MMI, but the brain is clamped into place." else user << "\blue You upend the MMI, spilling the brain onto the floor." - var/obj/item/brain/brain = new(user.loc) + var/obj/item/organ/brain/brain = new(user.loc) brainmob.container = null//Reset brainmob mmi var. brainmob.loc = brain//Throw mob into brain. living_mob_list -= brainmob//Get outta here diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 27b9da88e8..d2ba4fbb94 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -1,7 +1,7 @@ -/obj/item/brain +/obj/item/organ/brain name = "brain" - desc = "A piece of juicy meat found in a persons head." - icon = 'icons/obj/surgery.dmi' + health = 400 //They need to live awhile longer than other organs. + desc = "A piece of juicy meat found in a person's head." icon_state = "brain2" flags = TABLEPASS force = 1.0 @@ -11,32 +11,32 @@ throw_range = 5 origin_tech = "biotech=3" attack_verb = list("attacked", "slapped", "whacked") + prosthetic_name = "cyberbrain" + prosthetic_icon = "brain-prosthetic" + organ_tag = "brain" var/mob/living/carbon/brain/brainmob = null - New() - ..() - //Shifting the brain "mob" over to the brain object so it's easier to keep track of. --NEO - //WASSSSSUUUPPPP /N - spawn(5) - if(brainmob && brainmob.client) - brainmob.client.screen.len = null //clear the hud +/obj/item/organ/brain/New() + ..() + spawn(5) + if(brainmob && brainmob.client) + brainmob.client.screen.len = null //clear the hud - proc - transfer_identity(var/mob/living/carbon/H) - name = "[H]'s brain" - brainmob = new(src) - brainmob.name = H.real_name - brainmob.real_name = H.real_name - brainmob.dna = H.dna.Clone() - brainmob.timeofhostdeath = H.timeofdeath - if(H.mind) - H.mind.transfer_to(brainmob) +/obj/item/organ/brain/proc/transfer_identity(var/mob/living/carbon/H) + name = "[H]'s brain" + brainmob = new(src) + brainmob.name = H.real_name + brainmob.real_name = H.real_name + brainmob.dna = H.dna.Clone() + brainmob.timeofhostdeath = H.timeofdeath + if(H.mind) + H.mind.transfer_to(brainmob) - brainmob << "\blue You feel slightly disoriented. That's normal when you're just a brain." - callHook("debrain", list(brainmob)) + brainmob << "\blue You feel slightly disoriented. That's normal when you're just a brain." + callHook("debrain", list(brainmob)) -/obj/item/brain/examine() // -- TLE +/obj/item/organ/brain/examine() // -- TLE set src in oview(12) if (!( usr )) return @@ -47,53 +47,27 @@ else usr << "This one seems particularly lifeless. Perhaps it will regain some of its luster later.." -/obj/item/brain/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - if(!istype(M, /mob)) - return +/obj/item/organ/brain/removed(var/mob/living/target,var/mob/living/user) - add_fingerprint(user) + ..() - if(!(user.zone_sel.selecting == ("head")) || !istype(M, /mob/living/carbon/human)) - return ..() + var/mob/living/simple_animal/borer/borer = target.has_brain_worms() - if( !(locate(/obj/machinery/optable, M.loc) && M.resting) && ( !(locate(/obj/structure/table/, M.loc) && M.lying) && prob(50) ) ) - return ..() + if(borer) + borer.detatch() //Should remove borer if the brain is removed - RR - var/mob/living/carbon/human/H = M - if(istype(M, /mob/living/carbon/human) && ((H.head && H.head.flags & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES))) - // you can't stab someone in the eyes wearing a mask! - user << "\blue You're going to need to remove their head cover first." - return + var/mob/living/carbon/human/H = target + var/obj/item/organ/brain/B = src + if(istype(B) && istype(H)) + B.transfer_identity(target) -//since these people will be dead M != usr +/obj/item/organ/brain/replaced(var/mob/living/target) - if(M:brain_op_stage == 4.0) - for(var/mob/O in viewers(M, null)) - if(O == (user || M)) - continue - if(M == user) - O.show_message(text("\red [user] inserts [src] into his head!"), 1) - else - O.show_message(text("\red [M] has [src] inserted into his head by [user]."), 1) - - if(M != user) - M << "\red [user] inserts [src] into your head!" - user << "\red You insert [src] into [M]'s head!" - else - user << "\red You insert [src] into your head!" - - //this might actually be outdated since barring badminnery, a debrain'd body will have any client sucked out to the brain's internal mob. Leaving it anyway to be safe. --NEO - if(M.key)//Revised. /N - M.ghostize() + if(target.key) + target.ghostize() + if(brainmob) if(brainmob.mind) - brainmob.mind.transfer_to(M) + brainmob.mind.transfer_to(target) else - M.key = brainmob.key - - M:brain_op_stage = 3.0 - - del(src) - else - ..() - return + target.key = brainmob.key \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/death.dm b/code/modules/mob/living/carbon/brain/death.dm index 62916d818d..897b03c8a1 100644 --- a/code/modules/mob/living/carbon/brain/death.dm +++ b/code/modules/mob/living/carbon/brain/death.dm @@ -36,7 +36,7 @@ if(container && istype(container, /obj/item/device/mmi)) del(container)//Gets rid of the MMI if there is one if(loc) - if(istype(loc,/obj/item/brain)) + if(istype(loc,/obj/item/organ/brain)) del(loc)//Gets rid of the brain item spawn(15) if(animation) del(animation) diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm index b2deeae467..bd1467f5ef 100644 --- a/code/modules/mob/living/carbon/brain/posibrain.dm +++ b/code/modules/mob/living/carbon/brain/posibrain.dm @@ -10,7 +10,6 @@ construction_time = 75 var/searching = 0 var/askDelay = 10 * 60 * 1 - mob/living/carbon/brain/brainmob = null req_access = list(access_robotics) locked = 0 mecha = null//This does not appear to be used outside of reference in mecha.dm. @@ -133,14 +132,13 @@ /obj/item/device/mmi/posibrain/New() src.brainmob = new(src) + src.brainmob.add_language("Binary") src.brainmob.name = "[pick(list("PBU","HIU","SINA","ARMA","OSI"))]-[rand(100, 999)]" src.brainmob.real_name = src.brainmob.name src.brainmob.loc = src src.brainmob.container = src - src.brainmob.robot_talk_understand = 1 src.brainmob.stat = 0 src.brainmob.silent = 0 - src.brainmob.brain_op_stage = 4.0 dead_mob_list -= src.brainmob ..() diff --git a/code/modules/mob/living/carbon/brain/say.dm b/code/modules/mob/living/carbon/brain/say.dm index fa09d87f22..4756cc88ad 100644 --- a/code/modules/mob/living/carbon/brain/say.dm +++ b/code/modules/mob/living/carbon/brain/say.dm @@ -1,3 +1,4 @@ +//TODO: Convert this over for languages. /mob/living/carbon/brain/say(var/message) if (silent) return @@ -5,11 +6,6 @@ if(!(container && (istype(container, /obj/item/device/mmi) || istype(container, /obj/item/device/mmi/posibrain)))) return //No MMI, can't speak, bucko./N else - if ((department_radio_keys[copytext(message, 1, 3)] == "binary") && (container && istype(container, /obj/item/device/mmi/posibrain))) - message = copytext(message, 3) - message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) - robot_talk(message) - return if(prob(emp_damage*4)) if(prob(10))//10% chane to drop the message entirely return diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index f0c22c9f59..468f2861fa 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -224,7 +224,11 @@ M.visible_message("[M] shakes [src] trying to wake [t_him] up!", \ "You shake [src] trying to wake [t_him] up!") else - M.visible_message("[M] hugs [src] to make [t_him] feel better!", \ + var/mob/living/carbon/human/H = M + if(istype(H)) + H.species.hug(H,src) + else + M.visible_message("[M] hugs [src] to make [t_him] feel better!", \ "You hug [src] to make [t_him] feel better!") AdjustParalysis(-3) @@ -424,71 +428,38 @@ if(alert(src,"You sure you want to sleep for a while?","Sleep","Yes","No") == "Yes") usr.sleeping = 20 //Short nap -//Brain slug proc for voluntary removal of control. -/mob/living/carbon/proc/release_control() +/mob/living/carbon/Bump(atom/movable/AM as mob|obj, yes) - set category = "Alien" - set name = "Release Control" - set desc = "Release control of your host's body." + spawn( 0 ) + if ((!( yes ) || now_pushing)) + return + now_pushing = 1 + if(ismob(AM)) + var/mob/tmob = AM + if(istype(tmob, /mob/living/carbon/human) && (HULK in tmob.mutations)) + if(prob(70)) + usr << "\red You fail to push [tmob]'s fat ass out of the way." + now_pushing = 0 + return + if(!(tmob.status_flags & CANPUSH)) + now_pushing = 0 + return - var/mob/living/simple_animal/borer/B = has_brain_worms() - - if(B && B.host_brain) - src << "\red You withdraw your probosci, releasing control of [B.host_brain]" - - B.detatch() - - verbs -= /mob/living/carbon/proc/release_control - verbs -= /mob/living/carbon/proc/punish_host - verbs -= /mob/living/carbon/proc/spawn_larvae - - else - src << "\red ERROR NO BORER OR BRAINMOB DETECTED IN THIS MOB, THIS IS A BUG !" - -//Brain slug proc for tormenting the host. -/mob/living/carbon/proc/punish_host() - set category = "Alien" - set name = "Torment host" - set desc = "Punish your host with agony." - - var/mob/living/simple_animal/borer/B = has_brain_worms() - - if(!B) - return - - if(B.host_brain.ckey) - src << "\red You send a punishing spike of psychic agony lancing into your host's brain." - B.host_brain << "\red Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!" - -//Check for brain worms in head. -/mob/proc/has_brain_worms() - - for(var/I in contents) - if(istype(I,/mob/living/simple_animal/borer)) - return I - - return 0 - -/mob/living/carbon/proc/spawn_larvae() - set category = "Alien" - set name = "Reproduce" - set desc = "Spawn several young." - - var/mob/living/simple_animal/borer/B = has_brain_worms() - - if(!B) - return - - if(B.chemicals >= 100) - src << "\red Your host twitches and quivers as you rapidly excrete a larva from your sluglike body." - visible_message("\red [src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!") - B.chemicals -= 100 - B.has_reproduced = 1 - - new /obj/effect/decal/cleanable/vomit(get_turf(src)) - playsound(loc, 'sound/effects/splat.ogg', 50, 1) - new /mob/living/simple_animal/borer(get_turf(src)) - - else - src << "You do not have enough chemicals stored to reproduce." + tmob.LAssailant = src + now_pushing = 0 + ..() + if (!( istype(AM, /atom/movable) )) + return + if (!( now_pushing )) + now_pushing = 1 + if (!( AM.anchored )) + var/t = get_dir(src, AM) + if (istype(AM, /obj/structure/window)) + if(AM:ini_dir == NORTHWEST || AM:ini_dir == NORTHEAST || AM:ini_dir == SOUTHWEST || AM:ini_dir == SOUTHEAST) + for(var/obj/structure/window/win in get_step(AM,t)) + now_pushing = 0 + return + step(AM, t) + now_pushing = null return + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 0dff048d00..feed242bef 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -1,7 +1,6 @@ /mob/living/carbon/ gender = MALE var/list/stomach_contents = list() - var/brain_op_stage = 0.0 var/list/datum/disease2/disease/virus2 = list() var/antibodies = 0 var/last_eating = 0 //Not sure what this does... I found it hidden in food.dm diff --git a/code/modules/mob/living/carbon/carbon_powers.dm b/code/modules/mob/living/carbon/carbon_powers.dm new file mode 100644 index 0000000000..f4bc6e4d68 --- /dev/null +++ b/code/modules/mob/living/carbon/carbon_powers.dm @@ -0,0 +1,99 @@ +//TODO: Consider renaming carbon/monkey to carbon/small. + +/mob/living/carbon/proc/fertilize_plant() + + set category = "Abilities" + set name = "Fertilize plant" + set desc = "Turn your food into nutrients for plants." + + var/list/trays = list() + for(var/obj/machinery/portable_atmospherics/hydroponics/tray in range(1)) + if(tray.nutrilevel < 10 && src.Adjacent(tray)) + trays += tray + + var/obj/machinery/portable_atmospherics/hydroponics/target = input("Select a tray:") as null|anything in trays + + if(!src || !target || target.nutrilevel == 10) return //Sanity check. + + src.nutrition -= ((10-target.nutrilevel)*5) + target.nutrilevel = 10 + src.visible_message("\red [src] secretes a trickle of green liquid, refilling [target]'s nutrient tray.","\red You secrete a trickle of green liquid from your tail, refilling [target]'s nutrient tray.") + +/mob/living/carbon/proc/eat_weeds() + + set category = "Abilities" + set name = "Eat Weeds" + set desc = "Clean the weeds out of soil or a hydroponics tray." + + var/list/trays = list() + for(var/obj/machinery/portable_atmospherics/hydroponics/tray in range(1)) + if(tray.weedlevel > 0 && src.Adjacent(tray)) + trays += tray + + var/obj/machinery/portable_atmospherics/hydroponics/target = input("Select a tray:") as null|anything in trays + + if(!src || !target || target.weedlevel == 0) return //Sanity check. + + src.reagents.add_reagent("nutriment", target.weedlevel) + target.weedlevel = 0 + src.visible_message("\red [src] begins rooting through [target], ripping out weeds and eating them noisily.","\red You begin rooting through [target], ripping out weeds and eating them noisily.") + +//Brain slug proc for voluntary removal of control. +/mob/living/carbon/proc/release_control() + + set category = "Abilities" + set name = "Release Control" + set desc = "Release control of your host's body." + + var/mob/living/simple_animal/borer/B = has_brain_worms() + + if(B && B.host_brain) + src << "\red You withdraw your probosci, releasing control of [B.host_brain]" + + B.detatch() + + verbs -= /mob/living/carbon/proc/release_control + verbs -= /mob/living/carbon/proc/punish_host + verbs -= /mob/living/carbon/proc/spawn_larvae + + else + src << "\red ERROR NO BORER OR BRAINMOB DETECTED IN THIS MOB, THIS IS A BUG !" + +//Brain slug proc for tormenting the host. +/mob/living/carbon/proc/punish_host() + set category = "Abilities" + set name = "Torment host" + set desc = "Punish your host with agony." + + var/mob/living/simple_animal/borer/B = has_brain_worms() + + if(!B) + return + + if(B.host_brain.ckey) + src << "\red You send a punishing spike of psychic agony lancing into your host's brain." + B.host_brain << "\red Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!" + +/mob/living/carbon/proc/spawn_larvae() + set category = "Abilities" + set name = "Reproduce" + set desc = "Spawn several young." + + var/mob/living/simple_animal/borer/B = has_brain_worms() + + if(!B) + return + + if(B.chemicals >= 100) + src << "\red Your host twitches and quivers as you rapidly excrete a larva from your sluglike body." + visible_message("\red [src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!") + B.chemicals -= 100 + B.has_reproduced = 1 + + new /obj/effect/decal/cleanable/vomit(get_turf(src)) + playsound(loc, 'sound/effects/splat.ogg', 50, 1) + new /mob/living/simple_animal/borer(get_turf(src)) + + else + src << "You do not have enough chemicals stored to reproduce." + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/alien/alien.dm b/code/modules/mob/living/carbon/human/alien/alien.dm new file mode 100644 index 0000000000..4c5c9e739b --- /dev/null +++ b/code/modules/mob/living/carbon/human/alien/alien.dm @@ -0,0 +1,92 @@ +proc/create_new_xenomorph(var/alien_caste,var/target) + + target = get_turf(target) + if(!target || !alien_caste) return + + var/mob/living/carbon/human/new_alien = new(target) + new_alien.set_species("Xenomorph [alien_caste]") + return new_alien + +/mob/living/carbon/human/xdrone/New(var/new_loc) + h_style = "Bald" + ..(new_loc, "Xenomorph Drone") + +/mob/living/carbon/human/xsentinel/New(var/new_loc) + h_style = "Bald" + ..(new_loc, "Xenomorph Sentinel") + +/mob/living/carbon/human/xhunter/New(var/new_loc) + h_style = "Bald" + ..(new_loc, "Xenomorph Hunter") + +/mob/living/carbon/human/xqueen/New(var/new_loc) + h_style = "Bald" + ..(new_loc, "Xenomorph Queen") + +/mob/living/carbon/human/Stat() + + ..() + +// I feel like we should generalize/condense down all the various icon-rendering antag procs. +/*---------------------------------------- +Proc: AddInfectionImages() +Des: Gives the client of the alien an image on each infected mob. +----------------------------------------*/ +/mob/living/carbon/human/proc/AddInfectionImages() + if (client) + for (var/mob/living/C in mob_list) + if(C.status_flags & XENO_HOST) + 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 + +/*---------------------------------------- +Proc: RemoveInfectionImages() +Des: Removes all infected images from the alien. +----------------------------------------*/ +/mob/living/carbon/human/proc/RemoveInfectionImages() + if (client) + for(var/image/I in client.images) + if(dd_hasprefix_case(I.icon_state, "infected")) + del(I) + return + +/* TODO: Convert this over. +/mob/living/carbon/human/alien/show_inv(mob/user as mob) + + user.set_machine(src) + var/dat = {" +
[name]
+

+
Left Hand: [(l_hand ? text("[]", l_hand) : "Nothing")] +
Right Hand: [(r_hand ? text("[]", r_hand) : "Nothing")] +
Head: [(head ? text("[]", head) : "Nothing")] +
(Exo)Suit: [(wear_suit ? text("[]", wear_suit) : "Nothing")] +
Empty Pouches +
Close +
"} + user << browse(dat, text("window=mob[name];size=340x480")) + onclose(user, "mob[name]") + return + */ + +/* TODO: Convert this over. +/mob/living/carbon/human/alien/queen/large + icon = 'icons/mob/alienqueen.dmi' + icon_state = "queen_s" + pixel_x = -16 + +/mob/living/carbon/human/alien/queen/large/update_icons() + 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 = "queen_sleep" + else icon_state = "queen_l" + for(var/image/I in overlays_lying) + overlays += I + else + icon_state = "queen_s" + for(var/image/I in overlays_standing) + overlays += I*/ \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/human/alien/alien_embryo.dm similarity index 90% rename from code/modules/mob/living/carbon/alien/special/alien_embryo.dm rename to code/modules/mob/living/carbon/human/alien/alien_embryo.dm index 35b9e9fbfd..4bdddc2ca6 100644 --- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm +++ b/code/modules/mob/living/carbon/human/alien/alien_embryo.dm @@ -1,143 +1,159 @@ -// 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(!affected_mob) return - if(loc != affected_mob) - affected_mob.status_flags &= ~(XENO_HOST) - processing_objects.Remove(src) - spawn(0) - RemoveInfectionImages(affected_mob) - affected_mob = null - 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() - 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/L in mob_list) - if(iscorgi(L) || iscarbon(L)) - if(L.status_flags & XENO_HOST) - var/I = image('icons/mob/alien.dmi', loc = L, icon_state = "infected[stage]") - alien.client.images += I - -/*---------------------------------------- -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 - -/*---------------------------------------- -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")) +// 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(!affected_mob) return + if(loc != affected_mob) + affected_mob.status_flags &= ~(XENO_HOST) + processing_objects.Remove(src) + spawn(0) + RemoveInfectionImages(affected_mob) + affected_mob = null + 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() + + for(var/mob/living/carbon/alien in player_list) + + if(!locate(/datum/organ/internal/xenos/hivenode) in alien.internal_organs) + continue + + 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/L in mob_list) + if(iscorgi(L) || iscarbon(L)) + if(L.status_flags & XENO_HOST) + var/I = image('icons/mob/alien.dmi', loc = L, icon_state = "infected[stage]") + alien.client.images += I + +/*---------------------------------------- +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 in player_list) + + if(!locate(/datum/organ/internal/xenos/hivenode) in alien.internal_organs) + continue + + 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 + +/*---------------------------------------- +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 in player_list) + + if(!locate(/datum/organ/internal/xenos/hivenode) in alien.internal_organs) + continue + + 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) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/human/alien/alien_facehugger.dm similarity index 86% rename from code/modules/mob/living/carbon/alien/special/facehugger.dm rename to code/modules/mob/living/carbon/human/alien/alien_facehugger.dm index fc702d3f63..ffbaed6cc7 100644 --- a/code/modules/mob/living/carbon/alien/special/facehugger.dm +++ b/code/modules/mob/living/carbon/human/alien/alien_facehugger.dm @@ -1,241 +1,239 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 - -//TODO: Make these simple_animals - -var/const/MIN_IMPREGNATION_TIME = 100 //time it takes to impregnate someone -var/const/MAX_IMPREGNATION_TIME = 150 - -var/const/MIN_ACTIVE_TIME = 200 //time between being dropped and going idle -var/const/MAX_ACTIVE_TIME = 400 - -/obj/item/clothing/mask/facehugger - name = "alien" - desc = "It has some sort of a tube at the end of its tail." - icon = 'icons/mob/alien.dmi' - icon_state = "facehugger" - item_state = "facehugger" - w_class = 1 //note: can be picked up by aliens unlike most other items of w_class below 4 - flags = FPRINT | TABLEPASS | MASKCOVERSMOUTH | MASKCOVERSEYES | MASKINTERNALS - body_parts_covered = FACE|EYES - throw_range = 5 - - var/stat = CONSCIOUS //UNCONSCIOUS is the idle state in this case - - var/sterile = 0 - - var/strength = 5 - - var/attached = 0 - -/obj/item/clothing/mask/facehugger/attack_paw(user as mob) //can be picked up by aliens - if(isalien(user)) - attack_hand(user) - return - else - ..() - return - -/obj/item/clothing/mask/facehugger/attack_hand(user as mob) - if((stat == CONSCIOUS && !sterile) && !isalien(user)) - Attach(user) - return - else - ..() - return - -/obj/item/clothing/mask/facehugger/attack(mob/living/M as mob, mob/user as mob) - ..() - user.drop_from_inventory(src) - Attach(M) - -/obj/item/clothing/mask/facehugger/New() - if(aliens_allowed) - ..() - else - del(src) - -/obj/item/clothing/mask/facehugger/examine() - ..() - switch(stat) - if(DEAD,UNCONSCIOUS) - usr << "\red \b [src] is not moving." - if(CONSCIOUS) - usr << "\red \b [src] seems to be active." - if (sterile) - usr << "\red \b It looks like the proboscis has been removed." - return - -/obj/item/clothing/mask/facehugger/attackby() - Die() - return - -/obj/item/clothing/mask/facehugger/bullet_act() - Die() - return - -/obj/item/clothing/mask/facehugger/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > 300) - Die() - return - -/obj/item/clothing/mask/facehugger/equipped(mob/M) - Attach(M) - -/obj/item/clothing/mask/facehugger/Crossed(atom/target) - HasProximity(target) - return - -/obj/item/clothing/mask/facehugger/on_found(mob/finder as mob) - if(stat == CONSCIOUS) - HasProximity(finder) - return 1 - return - -/obj/item/clothing/mask/facehugger/HasProximity(atom/movable/AM as mob|obj) - 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) - ..() - if(stat == CONSCIOUS) - icon_state = "[initial(icon_state)]" - Attach(hit_atom) - throwing = 0 - -/obj/item/clothing/mask/facehugger/proc/Attach(M as mob) - if( (!iscorgi(M) && !iscarbon(M)) || isalien(M)) - return - if(attached) - return - else - attached++ - spawn(MAX_IMPREGNATION_TIME) - attached = 0 - - var/mob/living/L = M //just so I don't need to use : - - if(loc == L) return - if(stat != CONSCIOUS) return - if(!sterile) L.take_organ_damage(strength,0) //done here so that even borgs and humans in helmets take damage - - L.visible_message("\red \b [src] leaps at [L]'s face!") - - 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(iscarbon(M)) - var/mob/living/carbon/target = L - - 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.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 - - spawn(rand(MIN_IMPREGNATION_TIME,MAX_IMPREGNATION_TIME)) - Impregnate(L) - - return - -/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 - 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 - -/obj/item/clothing/mask/facehugger/proc/GoActive() - if(stat == DEAD || stat == CONSCIOUS) - return - - stat = CONSCIOUS - icon_state = "[initial(icon_state)]" - -/* for(var/mob/living/carbon/alien/alien in world) - var/image/activeIndicator = image('icons/mob/alien.dmi', loc = src, icon_state = "facehugger_active") - activeIndicator.override = 1 - if(alien && alien.client) - alien.client.images += activeIndicator */ - - return - -/obj/item/clothing/mask/facehugger/proc/GoIdle() - if(stat == DEAD || stat == UNCONSCIOUS) - return - -/* RemoveActiveIndicators() */ - - stat = UNCONSCIOUS - icon_state = "[initial(icon_state)]_inactive" - - spawn(rand(MIN_ACTIVE_TIME,MAX_ACTIVE_TIME)) - GoActive() - return - -/obj/item/clothing/mask/facehugger/proc/Die() - if(stat == DEAD) - return - -/* RemoveActiveIndicators() */ - - icon_state = "[initial(icon_state)]_dead" - stat = DEAD - - src.visible_message("\red \b[src] curls up into a ball!") - - return - -/proc/CanHug(var/mob/M) - - if(iscorgi(M)) - return 1 - - if(!iscarbon(M) || isalien(M)) - return 0 - var/mob/living/carbon/C = M - if(ishuman(C)) - var/mob/living/carbon/human/H = C - if(H.head && H.head.flags & HEADCOVERSMOUTH) - return 0 - return 1 +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 + +//TODO: Make these simple_animals + +var/const/MIN_IMPREGNATION_TIME = 100 //time it takes to impregnate someone +var/const/MAX_IMPREGNATION_TIME = 150 + +var/const/MIN_ACTIVE_TIME = 200 //time between being dropped and going idle +var/const/MAX_ACTIVE_TIME = 400 + +/obj/item/clothing/mask/facehugger + name = "alien" + desc = "It has some sort of a tube at the end of its tail." + icon = 'icons/mob/alien.dmi' + icon_state = "facehugger" + item_state = "facehugger" + w_class = 1 //note: can be picked up by aliens unlike most other items of w_class below 4 + flags = FPRINT | TABLEPASS | MASKCOVERSMOUTH | MASKCOVERSEYES | MASKINTERNALS + body_parts_covered = FACE|EYES + throw_range = 5 + + var/stat = CONSCIOUS //UNCONSCIOUS is the idle state in this case + var/sterile = 0 + var/strength = 5 + var/attached = 0 + +/obj/item/clothing/mask/facehugger/attack_paw(user as mob) //can be picked up by aliens + attack_hand(user) + return + +/obj/item/clothing/mask/facehugger/attack_hand(user as mob) + + if((stat == CONSCIOUS && !sterile)) + Attach(user) + return + else + ..() + return + +/obj/item/clothing/mask/facehugger/attack(mob/living/M as mob, mob/user as mob) + ..() + user.drop_from_inventory(src) + Attach(M) + +/obj/item/clothing/mask/facehugger/New() + if(aliens_allowed) + ..() + else + del(src) + +/obj/item/clothing/mask/facehugger/examine() + ..() + switch(stat) + if(DEAD,UNCONSCIOUS) + usr << "\red \b [src] is not moving." + if(CONSCIOUS) + usr << "\red \b [src] seems to be active." + if (sterile) + usr << "\red \b It looks like the proboscis has been removed." + return + +/obj/item/clothing/mask/facehugger/attackby() + Die() + return + +/obj/item/clothing/mask/facehugger/bullet_act() + Die() + return + +/obj/item/clothing/mask/facehugger/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > 300) + Die() + return + +/obj/item/clothing/mask/facehugger/equipped(mob/M) + Attach(M) + +/obj/item/clothing/mask/facehugger/Crossed(atom/target) + HasProximity(target) + return + +/obj/item/clothing/mask/facehugger/on_found(mob/finder as mob) + if(stat == CONSCIOUS) + HasProximity(finder) + return 1 + return + +/obj/item/clothing/mask/facehugger/HasProximity(atom/movable/AM as mob|obj) + 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) + ..() + if(stat == CONSCIOUS) + icon_state = "[initial(icon_state)]" + Attach(hit_atom) + throwing = 0 + +/obj/item/clothing/mask/facehugger/proc/Attach(M as mob) + + if((!iscorgi(M) && !iscarbon(M))) + return + + if(attached) + return + + var/mob/living/carbon/C = M + if(istype(C) && locate(/datum/organ/internal/xenos/hivenode) in C.internal_organs) + return + + attached++ + spawn(MAX_IMPREGNATION_TIME) + attached = 0 + + var/mob/living/L = M //just so I don't need to use : + + if(loc == L) return + if(stat != CONSCIOUS) return + if(!sterile) L.take_organ_damage(strength,0) //done here so that even borgs and humans in helmets take damage + + L.visible_message("\red \b [src] leaps at [L]'s face!") + + 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(iscarbon(M)) + var/mob/living/carbon/target = L + + 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.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/corgi = M + src.loc = corgi + corgi.facehugger = src + corgi.wear_mask = src + //C.regenerate_icons() + + GoIdle() //so it doesn't jump the people that tear it off + + spawn(rand(MIN_IMPREGNATION_TIME,MAX_IMPREGNATION_TIME)) + Impregnate(L) + + return + +/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 + 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 + +/obj/item/clothing/mask/facehugger/proc/GoActive() + if(stat == DEAD || stat == CONSCIOUS) + return + + stat = CONSCIOUS + icon_state = "[initial(icon_state)]" + + return + +/obj/item/clothing/mask/facehugger/proc/GoIdle() + if(stat == DEAD || stat == UNCONSCIOUS) + return + +/* RemoveActiveIndicators() */ + + stat = UNCONSCIOUS + icon_state = "[initial(icon_state)]_inactive" + + spawn(rand(MIN_ACTIVE_TIME,MAX_ACTIVE_TIME)) + GoActive() + return + +/obj/item/clothing/mask/facehugger/proc/Die() + if(stat == DEAD) + return + +/* RemoveActiveIndicators() */ + + icon_state = "[initial(icon_state)]_dead" + stat = DEAD + + src.visible_message("\red \b[src] curls up into a ball!") + + return + +/proc/CanHug(var/mob/M) + + if(iscorgi(M)) + return 1 + + if(!iscarbon(M)) + return 0 + + var/mob/living/carbon/C = M + if(istype(C) && locate(/datum/organ/internal/xenos/hivenode) in C.internal_organs) + return 0 + + if(ishuman(C)) + var/mob/living/carbon/human/H = C + if(H.head && H.head.flags & HEADCOVERSMOUTH) + return 0 + return 1 diff --git a/code/modules/mob/living/carbon/human/alien/alien_powers.dm b/code/modules/mob/living/carbon/human/alien/alien_powers.dm new file mode 100644 index 0000000000..4b522c3552 --- /dev/null +++ b/code/modules/mob/living/carbon/human/alien/alien_powers.dm @@ -0,0 +1,228 @@ +/proc/alien_queen_exists(var/ignore_self,var/mob/living/carbon/human/self) + for(var/mob/living/carbon/human/Q in living_mob_list) + if(self && ignore_self && self == Q) + continue + if(Q.species.name != "Xenomorph Queen") + continue + if(!Q.key || !Q.client || Q.stat) + continue + return 1 + return 0 + +/mob/living/carbon/human/proc/gain_plasma(var/amount) + + var/datum/organ/internal/xenos/plasmavessel/I = internal_organs_by_name["plasma vessel"] + if(!istype(I)) return + + if(amount) + I.stored_plasma += amount + I.stored_plasma = max(0,min(I.stored_plasma,I.max_plasma)) + +/mob/living/carbon/human/proc/check_alien_ability(var/cost,var/needs_foundation,var/needs_organ) + + var/datum/organ/internal/xenos/plasmavessel/P = internal_organs_by_name["plasma vessel"] + if(!istype(P)) + src << "Your plasma vessel has been removed!" + return + + if(needs_organ) + var/datum/organ/internal/I = internal_organs_by_name[needs_organ] + if(!I) + src << "Your [needs_organ] has been removed!" + return + else if((I.status & ORGAN_CUT_AWAY) || I.is_broken()) + src << "Your [needs_organ] is too damaged to function!" + return + + if(P.stored_plasma < cost) + src << "\red You don't have enough phoron stored to do that." + return 0 + + if(needs_foundation) + var/turf/T = get_turf(src) + var/has_foundation + if(T) + //TODO: Work out the actual conditions this needs. + if(!(istype(T,/turf/space))) + has_foundation = 1 + if(!has_foundation) + src << "\red You need a solid foundation to do that on." + return 0 + + P.stored_plasma -= cost + return 1 + +// Free abilities. +/mob/living/carbon/human/proc/transfer_plasma(mob/living/carbon/human/M as mob in oview()) + set name = "Transfer Plasma" + set desc = "Transfer Plasma to another alien" + set category = "Abilities" + + if (get_dist(src,M) <= 1) + src << "\green You need to be closer." + return + + var/datum/organ/internal/xenos/plasmavessel/I = M.internal_organs_by_name["plasma vessel"] + if(!istype(I)) + src << "\green Their plasma vessel is missing." + return + + var/amount = input("Amount:", "Transfer Plasma to [M]") as num + if (amount) + amount = abs(round(amount)) + if(check_alien_ability(amount,0,"plasma vessel")) + M.gain_plasma(amount) + M << "\green [src] has transfered [amount] plasma to you." + src << "\green You have transferred [amount] plasma to [M]" + return + +// Queen verbs. +/mob/living/carbon/human/proc/lay_egg() + + set name = "Lay Egg (75)" + set desc = "Lay an egg to produce huggers to impregnate prey with." + set category = "Abilities" + + if(!aliens_allowed) + src << "You begin to lay an egg, but hesitate. You suspect it isn't allowed." + verbs -= /mob/living/carbon/human/proc/lay_egg + return + + if(locate(/obj/effect/alien/egg) in get_turf(src)) + src << "There's already an egg here." + return + + if(check_alien_ability(75,1,"egg sac")) + for(var/mob/O in viewers(src, null)) + O.show_message(text("\green [src] has laid an egg!"), 1) + new /obj/effect/alien/egg(loc) + + return + +// Drone verbs. +/mob/living/carbon/human/proc/evolve() + set name = "Evolve (500)" + set desc = "Produce an interal egg sac capable of spawning children. Only one queen can exist at a time." + set category = "Abilities" + + if(alien_queen_exists()) + src << "We already have an active queen." + return + + if(check_alien_ability(500)) + src << "\green You begin to evolve!" + for(var/mob/O in viewers(src, null)) + O.show_message(text("\green [src] begins to twist and contort!"), 1) + src.set_species("Xenomorph Queen") + + return + +/mob/living/carbon/human/proc/plant() + set name = "Plant Weeds (50)" + set desc = "Plants some alien weeds" + set category = "Abilities" + + if(check_alien_ability(50,1,"resin spinner")) + for(var/mob/O in viewers(src, null)) + O.show_message(text("\green [src] has planted some alien weeds!"), 1) + new /obj/effect/alien/weeds/node(loc) + return + +/mob/living/carbon/human/proc/corrosive_acid(O as obj|turf in oview(1)) //If they right click to corrode, an error will flash if its an invalid target./N + set name = "Corrosive Acid (200)" + set desc = "Drench an object in acid, destroying it over time." + set category = "Abilities" + + if(!O in oview(1)) + src << "\green [O] is too far away." + return + + // OBJ CHECK + if(isobj(O)) + var/obj/I = O + if(I.unacidable) //So the aliens don't destroy energy fields/singularies/other aliens/etc with their acid. + src << "\green You cannot dissolve this object." + return + + // TURF CHECK + else if(istype(O, /turf/simulated)) + var/turf/T = O + // R WALL + if(istype(T, /turf/simulated/wall/r_wall)) + src << "\green You cannot dissolve this object." + return + // R FLOOR + if(istype(T, /turf/simulated/floor/engine)) + src << "\green You cannot dissolve this object." + return + else// Not a type we can acid. + return + + if(check_alien_ability(200,0,"acid gland")) + new /obj/effect/alien/acid(get_turf(O), O) + visible_message("\green [src] vomits globs of vile stuff all over [O]. It begins to sizzle and melt under the bubbling mess of acid!") + + return + +/mob/living/carbon/human/proc/neurotoxin(mob/target as mob in oview()) + set name = "Spit Neurotoxin (50)" + set desc = "Spits neurotoxin at someone, paralyzing them for a short time if they are not wearing protective gear." + set category = "Abilities" + + if(!check_alien_ability(50,0,"acid gland")) + return + + src << "\green You spit neurotoxin at [target]." + for(var/mob/O in oviewers()) + if ((O.client && !( O.blinded ))) + O << "\red [src] spits neurotoxin at [target]!" + + //I'm not motivated enough to revise this. Prjectile code in general needs update. + // Maybe change this to use throw_at? ~ Z + var/turf/T = loc + var/turf/U = (istype(target, /atom/movable) ? target.loc : target) + + if(!U || !T) + return + while(U && !istype(U,/turf)) + U = U.loc + if(!istype(T, /turf)) + return + if (U == T) + usr.bullet_act(new /obj/item/projectile/energy/neurotoxin(usr.loc), get_organ_target()) + return + if(!istype(U, /turf)) + return + + var/obj/item/projectile/energy/neurotoxin/A = new /obj/item/projectile/energy/neurotoxin(usr.loc) + A.current = U + A.yo = U.y - T.y + A.xo = U.x - T.x + A.process() + return + +/mob/living/carbon/human/proc/resin() // -- TLE + set name = "Secrete Resin (75)" + set desc = "Secrete tough malleable resin." + set category = "Abilities" + + var/choice = input("Choose what you wish to shape.","Resin building") as null|anything in list("resin door","resin wall","resin membrane","resin nest") //would do it through typesof but then the player choice would have the type path and we don't want the internal workings to be exposed ICly - Urist + if(!choice) + return + + if(!check_alien_ability(75,1,"resin spinner")) + return + + src << "\green You shape a [choice]." + for(var/mob/O in viewers(src, null)) + O.show_message(text("\red [src] vomits up a thick purple substance and begins to shape it!"), 1) + switch(choice) + if("resin door") + new /obj/structure/mineral_door/resin(loc) + if("resin wall") + new /obj/effect/alien/resin/wall(loc) + if("resin membrane") + new /obj/effect/alien/resin/membrane(loc) + if("resin nest") + new /obj/structure/stool/bed/nest(loc) + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/alien/alien_species.dm b/code/modules/mob/living/carbon/human/alien/alien_species.dm new file mode 100644 index 0000000000..c1c820a17f --- /dev/null +++ b/code/modules/mob/living/carbon/human/alien/alien_species.dm @@ -0,0 +1,263 @@ +//Stand-in until this is made more lore-friendly. +/datum/species/xenos + name = "Xenomorph" + language = "Hivemind" + unarmed_type = /datum/unarmed_attack/claws/strong + secondary_unarmed_type = /datum/unarmed_attack/bite/strong + hud_type = /datum/hud_data/alien + rarity_value = 3 + + has_fine_manipulation = 0 + insulated = 1 + gluttonous = 2 + + eyes = "blank_eyes" + + brute_mod = 0.5 // Hardened carapace. + burn_mod = 2 // Weak to fire. + + warning_low_pressure = 50 + hazard_low_pressure = -1 + + cold_level_1 = 50 + cold_level_2 = -1 + cold_level_3 = -1 + + flags = IS_WHITELISTED | NO_BREATHE | NO_SCAN | NO_PAIN | NO_SLIP | NO_POISON + + reagent_tag = IS_XENOS + + blood_color = "#05EE05" + flesh_color = "#282846" + gibbed_anim = "gibbed-a" + dusted_anim = "dust-a" + death_message = "lets out a waning guttural screech, green blood bubbling from its maw." + death_sound = 'sound/voice/hiss6.ogg' + + breath_type = null + poison_type = null + + has_organ = list( + "heart" = /datum/organ/internal/heart, + "lungs" = /datum/organ/internal/lungs, + "brain" = /datum/organ/internal/brain, + "plasma vessel" = /datum/organ/internal/xenos/plasmavessel, + "hive node" = /datum/organ/internal/xenos/hivenode, + "nutrient vessel" = /datum/organ/internal/diona/nutrients + ) + + var/alien_number = 0 + var/caste_name = "creature" // Used to update alien name. + var/weeds_heal_rate = 1 // Health regen on weeds. + var/weeds_plasma_rate = 5 // Plasma regen on weeds. + +/datum/species/xenos/hug(var/mob/living/carbon/human/H,var/mob/living/target) + H.visible_message("[H] caresses [target] with its scythe-like arm.", \ + "You caress [target] with your scythe-like arm.") + +/datum/species/xenos/handle_post_spawn(var/mob/living/carbon/human/H) + + if(H.mind) + H.mind.assigned_role = "Alien" + H.mind.special_role = "Alien" + + alien_number++ //Keep track of how many aliens we've had so far. + H.real_name = "alien [caste_name] ([alien_number])" + H.name = H.real_name + + ..() + +/datum/species/xenos/handle_environment_special(var/mob/living/carbon/human/H) + + var/turf/T = H.loc + if(!T) return + var/datum/gas_mixture/environment = T.return_air() + if(!environment) return + + if(environment.gas["phoron"] > 0 || locate(/obj/effect/alien/weeds) in T) + if(H.health >= H.maxHealth - H.getCloneLoss()) + var/datum/organ/internal/xenos/plasmavessel/P = H.internal_organs_by_name["plasma vessel"] + P.stored_plasma += weeds_plasma_rate + P.stored_plasma = min(max(P.stored_plasma,0),P.max_plasma) + else + H.adjustBruteLoss(-weeds_heal_rate) + H.adjustFireLoss(-weeds_heal_rate) + H.adjustOxyLoss(-weeds_heal_rate) + H.adjustToxLoss(-weeds_heal_rate) + ..() + + +/datum/species/xenos/handle_login_special(var/mob/living/carbon/human/H) + H.AddInfectionImages() + ..() + +/datum/species/xenos/handle_logout_special(var/mob/living/carbon/human/H) + H.RemoveInfectionImages() + ..() + +/datum/species/xenos/drone + name = "Xenomorph Drone" + caste_name = "drone" + weeds_plasma_rate = 15 + slowdown = 2 + tail = "xenos_drone_tail" + rarity_value = 5 + + icobase = 'icons/mob/human_races/xenos/r_xenos_drone.dmi' + deform = 'icons/mob/human_races/xenos/r_xenos_drone.dmi' + + has_organ = list( + "heart" = /datum/organ/internal/heart, + "lungs" = /datum/organ/internal/lungs, + "brain" = /datum/organ/internal/brain, + "plasma vessel" = /datum/organ/internal/xenos/plasmavessel/queen, + "acid gland" = /datum/organ/internal/xenos/acidgland, + "hive node" = /datum/organ/internal/xenos/hivenode, + "resin spinner" = /datum/organ/internal/xenos/resinspinner, + "nutrient vessel" = /datum/organ/internal/diona/nutrients + ) + + inherent_verbs = list( + /mob/living/carbon/human/proc/regurgitate, + /mob/living/carbon/human/proc/plant, + /mob/living/carbon/human/proc/transfer_plasma, + /mob/living/carbon/human/proc/evolve, + /mob/living/carbon/human/proc/resin, + /mob/living/carbon/human/proc/corrosive_acid + ) + +/datum/species/xenos/drone/handle_post_spawn(var/mob/living/carbon/human/H) + + var/mob/living/carbon/human/A = H + if(!istype(A)) + return ..() + ..() + +/datum/species/xenos/hunter + + name = "Xenomorph Hunter" + weeds_plasma_rate = 5 + caste_name = "hunter" + slowdown = -1 + total_health = 150 + tail = "xenos_hunter_tail" + + icobase = 'icons/mob/human_races/xenos/r_xenos_hunter.dmi' + deform = 'icons/mob/human_races/xenos/r_xenos_hunter.dmi' + + has_organ = list( + "heart" = /datum/organ/internal/heart, + "lungs" = /datum/organ/internal/lungs, + "brain" = /datum/organ/internal/brain, + "plasma vessel" = /datum/organ/internal/xenos/plasmavessel/hunter, + "hive node" = /datum/organ/internal/xenos/hivenode, + "nutrient vessel" = /datum/organ/internal/diona/nutrients + ) + + inherent_verbs = list( + /mob/living/carbon/human/proc/tackle, + /mob/living/carbon/human/proc/gut, + /mob/living/carbon/human/proc/leap, + /mob/living/carbon/human/proc/psychic_whisper, + /mob/living/carbon/human/proc/regurgitate + ) + +/datum/species/xenos/sentinel + name = "Xenomorph Sentinel" + weeds_plasma_rate = 10 + caste_name = "sentinel" + slowdown = 1 + total_health = 125 + tail = "xenos_sentinel_tail" + + icobase = 'icons/mob/human_races/xenos/r_xenos_sentinel.dmi' + deform = 'icons/mob/human_races/xenos/r_xenos_sentinel.dmi' + + has_organ = list( + "heart" = /datum/organ/internal/heart, + "lungs" = /datum/organ/internal/lungs, + "brain" = /datum/organ/internal/brain, + "plasma vessel" = /datum/organ/internal/xenos/plasmavessel/sentinel, + "acid gland" = /datum/organ/internal/xenos/acidgland, + "hive node" = /datum/organ/internal/xenos/hivenode, + "nutrient vessel" = /datum/organ/internal/diona/nutrients + ) + + inherent_verbs = list( + /mob/living/carbon/human/proc/tackle, + /mob/living/carbon/human/proc/regurgitate, + /mob/living/carbon/human/proc/transfer_plasma, + /mob/living/carbon/human/proc/corrosive_acid, + /mob/living/carbon/human/proc/neurotoxin + ) + +/datum/species/xenos/queen + + name = "Xenomorph Queen" + weeds_heal_rate = 5 + weeds_plasma_rate = 20 + caste_name = "queen" + slowdown = 5 + tail = "xenos_queen_tail" + rarity_value = 10 + + icobase = 'icons/mob/human_races/xenos/r_xenos_queen.dmi' + deform = 'icons/mob/human_races/xenos/r_xenos_queen.dmi' + + has_organ = list( + "heart" = /datum/organ/internal/heart, + "lungs" = /datum/organ/internal/lungs, + "brain" = /datum/organ/internal/brain, + "egg sac" = /datum/organ/internal/xenos/eggsac, + "plasma vessel" = /datum/organ/internal/xenos/plasmavessel/queen, + "acid gland" = /datum/organ/internal/xenos/acidgland, + "hive node" = /datum/organ/internal/xenos/hivenode, + "resin spinner" = /datum/organ/internal/xenos/resinspinner, + "nutrient vessel" = /datum/organ/internal/diona/nutrients + ) + + inherent_verbs = list( + /mob/living/carbon/human/proc/psychic_whisper, + /mob/living/carbon/human/proc/regurgitate, + /mob/living/carbon/human/proc/lay_egg, + /mob/living/carbon/human/proc/plant, + /mob/living/carbon/human/proc/transfer_plasma, + /mob/living/carbon/human/proc/corrosive_acid, + /mob/living/carbon/human/proc/neurotoxin, + /mob/living/carbon/human/proc/resin + ) + + //maxHealth = 250 + //health = 250 + +/datum/species/xenos/queen/handle_login_special(var/mob/living/carbon/human/H) + ..() + // Make sure only one official queen exists at any point. + if(!alien_queen_exists(1,H)) + H.real_name = "alien queen ([alien_number])" + H.name = H.real_name + else + H.real_name = "alien princess ([alien_number])" + H.name = H.real_name + +/datum/hud_data/alien + + icon = 'icons/mob/screen1_alien.dmi' + has_a_intent = 1 + has_m_intent = 1 + has_warnings = 1 + has_hands = 1 + has_drop = 1 + has_throw = 1 + has_resist = 1 + has_pressure = 0 + has_nutrition = 0 + has_bodytemp = 0 + has_internals = 0 + + gear = list( + "o_clothing" = list("loc" = ui_belt, "slot" = slot_wear_suit, "state" = "equip", "dir" = SOUTH), + "head" = list("loc" = ui_id, "slot" = slot_head, "state" = "hair"), + "storage1" = list("loc" = ui_storage1, "slot" = slot_l_store, "state" = "pocket"), + "storage2" = list("loc" = ui_storage2, "slot" = slot_r_store, "state" = "pocket"), + ) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index e14cd9c534..f97397fe4c 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -19,10 +19,11 @@ // Override the current limb status and don't cause an explosion E.droplimb(1,1) - flick("gibbed-h", animation) if(species) + flick(species.gibbed_anim, animation) hgibs(loc, viruses, dna, species.flesh_color, species.blood_color) else + flick("gibbed-h", animation) hgibs(loc, viruses, dna) spawn(15) @@ -42,8 +43,8 @@ animation.icon = 'icons/mob/mob.dmi' animation.master = src - flick("dust-h", animation) - new /obj/effect/decal/remains/human(loc) + flick(species.dusted_anim, animation) + new species.remains_type(loc) spawn(15) if(animation) del(animation) @@ -97,7 +98,9 @@ vox_kills++ //Bad vox. Shouldn't be killing humans. if(!gibbed) - emote("deathgasp") //let the world KNOW WE ARE DEAD + + emote("deathgasp") //let the world KNOW WE ARE DEAD // Doing this with the deathgasp emote seems odd. + if(species && species.death_sound) playsound(loc, species.death_sound, 80, 1, 1) //For ninjas exploding when they die. if( istype(wear_suit, /obj/item/clothing/suit/space/space_ninja) && wear_suit:s_initialized ) diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 75eff694fa..9b5a526ca1 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -207,7 +207,7 @@ m_type = 2 if ("deathgasp") - message = "[src] seizes up and falls limp, \his eyes dead and lifeless..." + message = "[src] [species.death_message]" m_type = 1 if ("giggle") diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 2a9850171e..6196e71159 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -240,10 +240,11 @@ if(getBrainLoss() >= 60) msg += "[t_He] [t_has] a stupid expression on [t_his] face.\n" - if(!key && brain_op_stage != 4 && stat != DEAD) - msg += "[t_He] [t_is] fast asleep. It doesn't look like they are waking up anytime soon.\n" - else if(!client && brain_op_stage != 4 && stat != DEAD) - msg += "[t_He] [t_has] suddenly fallen asleep.\n" + if((!species.has_organ["brain"] || has_brain()) && stat != DEAD) + if(!key) + msg += "[t_He] [t_is] fast asleep. It doesn't look like they are waking up anytime soon.\n" + else if(!client) + msg += "[t_He] [t_has] suddenly fallen asleep.\n" var/list/wound_flavor_text = list() var/list/is_destroyed = list() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 131f0f724b..69653cd5a8 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -4,46 +4,20 @@ voice_name = "unknown" icon = 'icons/mob/human.dmi' icon_state = "body_m_s" + var/list/hud_list[9] var/datum/species/species //Contains icon generation and language information, set during New(). var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us. -/mob/living/carbon/human/dummy - real_name = "Test Dummy" - status_flags = GODMODE|CANPUSH - -/mob/living/carbon/human/skrell/New(var/new_loc) - h_style = "Skrell Male Tentacles" - ..(new_loc, "Skrell") - -/mob/living/carbon/human/tajaran/New(var/new_loc) - h_style = "Tajaran Ears" - ..(new_loc, "Tajaran") - -/mob/living/carbon/human/unathi/New(var/new_loc) - h_style = "Unathi Horns" - ..(new_loc, "Unathi") - -/mob/living/carbon/human/vox/New(var/new_loc) - h_style = "Short Vox Quills" - ..(new_loc, "Vox") - -/mob/living/carbon/human/voxarmalis/New(var/new_loc) - h_style = "Bald" - ..(new_loc, "Vox Armalis") - -/mob/living/carbon/human/diona/New(var/new_loc) - ..(new_loc, "Diona") - -/mob/living/carbon/human/machine/New(var/new_loc) - h_style = "blue IPC screen" - ..(new_loc, "Machine") - /mob/living/carbon/human/New(var/new_loc, var/new_species = null) + if(!dna) + dna = new /datum/dna(null) + // Species name is handled by set_species() + if(!species) if(new_species) - set_species(new_species,null,1) + set_species(new_species) else set_species() @@ -51,10 +25,6 @@ reagents = R R.my_atom = src - if(!dna) - dna = new /datum/dna(null) - dna.species=species.name - hud_list[HEALTH_HUD] = image('icons/mob/hud.dmi', src, "hudhealth100") hud_list[STATUS_HUD] = image('icons/mob/hud.dmi', src, "hudhealthy") hud_list[ID_HUD] = image('icons/mob/hud.dmi', src, "hudunknown") @@ -65,7 +35,6 @@ hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank") hud_list[STATUS_HUD_OOC] = image('icons/mob/hud.dmi', src, "hudhealthy") - ..() if(dna) @@ -176,6 +145,7 @@ stat(null, eta_status) if (client.statpanel == "Status") + if (internal) if (!internal.air_contents) del(internal) @@ -183,10 +153,15 @@ stat("Internal Atmosphere Info", internal.name) stat("Tank Pressure", internal.air_contents.return_pressure()) stat("Distribution Pressure", internal.distribute_pressure) + + var/datum/organ/internal/xenos/plasmavessel/P = internal_organs_by_name["plasma vessel"] + if(P) + stat(null, "Phoron Stored: [P.stored_plasma]/[P.max_plasma]") if(mind) if(mind.changeling) stat("Chemical Storage", mind.changeling.chem_charges) stat("Genetic Damage Time", mind.changeling.geneticdamage) + if (istype(wear_suit, /obj/item/clothing/suit/space/space_ninja)&&wear_suit:s_initialized) stat("Energy Charge", round(wear_suit:cell:charge/100)) @@ -299,7 +274,7 @@ return -/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M as mob) +/mob/living/carbon/human/attack_animal(mob/living/M as mob) if(M.melee_damage_upper == 0) M.emote("[M.friendly] [src]") else @@ -856,11 +831,21 @@ ..() return - ///eyecheck() ///Returns a number between -1 to 2 /mob/living/carbon/human/eyecheck() var/number = 0 + + if(!species.has_organ["eyes"]) //No eyes, can't hurt them. + return 2 + + if(internal_organs_by_name["eyes"]) // Eyes are fucked, not a 'weak point'. + var/datum/organ/internal/I = internal_organs_by_name["eyes"] + if(I.status & ORGAN_CUT_AWAY) + return 2 + else + return 2 + if(istype(src.head, /obj/item/clothing/head/welding)) if(!src.head:up) number += 2 @@ -878,7 +863,7 @@ /mob/living/carbon/human/IsAdvancedToolUser() - return 1//Humans can use guns and such + return species.has_fine_manipulation /mob/living/carbon/human/abiotic(var/full_body = 0) @@ -1135,12 +1120,12 @@ /mob/living/carbon/human/proc/is_lung_ruptured() var/datum/organ/internal/lungs/L = internal_organs_by_name["lungs"] - return L.is_bruised() + return L && L.is_bruised() /mob/living/carbon/human/proc/rupture_lung() var/datum/organ/internal/lungs/L = internal_organs_by_name["lungs"] - if(!L.is_bruised()) + if(L && !L.is_bruised()) src.custom_pain("You feel a stabbing pain in your chest!", 1) L.damage = L.min_bruised_damage @@ -1261,7 +1246,7 @@ else usr << "\blue [self ? "Your" : "[src]'s"] pulse is [src.get_pulse(GETPULSE_HAND)]." -/mob/living/carbon/human/proc/set_species(var/new_species, var/force_organs, var/default_colour) +/mob/living/carbon/human/proc/set_species(var/new_species, var/default_colour) if(!dna) if(!new_species) @@ -1272,16 +1257,15 @@ else dna.species = new_species - if(species && (species.name && species.name == new_species)) - return - - if(species && species.language) - remove_language(species.language) + if(species) + if(species.name && species.name == new_species) + return + if(species.language) + remove_language(species.language) species = all_species[new_species] - if(force_organs || !organs || !organs.len) - species.create_organs(src) + species.create_organs(src) if(species.language) add_language(species.language) @@ -1300,6 +1284,8 @@ spawn(0) update_icons() + vessel.add_reagent("blood",560-vessel.total_volume) + fixblood() if(species) return 1 @@ -1380,156 +1366,6 @@ // Might need re-wording. user << "There is no exposed flesh or thin material [target_zone == "head" ? "on their head" : "on their body"] to inject into." - -//Putting a couple of procs here that I don't know where else to dump. -//Mostly going to be used for Vox and Vox Armalis, but other human mobs might like them (for adminbuse). - -/mob/living/carbon/human/proc/leap() - set category = "IC" - set name = "Leap" - set desc = "Leap at a target and grab them aggressively." - - if(last_special > world.time) - return - - if(stat || paralysis || stunned || weakened || lying || restrained() || buckled) - src << "You cannot leap in your current state." - return - - var/list/choices = list() - for(var/mob/living/M in view(6,src)) - if(!istype(M,/mob/living/silicon)) - choices += M - choices -= src - - var/mob/living/T = input(src,"Who do you wish to leap at?") as null|anything in choices - - if(!T || !src || src.stat) return - - if(get_dist(get_turf(T), get_turf(src)) > 6) return - - if(last_special > world.time) - return - - if(stat || paralysis || stunned || weakened || lying || restrained() || buckled) - src << "You cannot leap in your current state." - return - - last_special = world.time + 75 - status_flags |= LEAPING - - src.visible_message("\The [src] leaps at [T]!") - src.throw_at(get_step(get_turf(T),get_turf(src)), 5, 1, src) - playsound(src.loc, 'sound/voice/shriek1.ogg', 50, 1) - - sleep(5) - - if(status_flags & LEAPING) status_flags &= ~LEAPING - - if(!src.Adjacent(T)) - src << "\red You miss!" - return - - T.Weaken(5) - - //Only official raider vox get the grab and no self-prone." - if(src.mind && src.mind.special_role != "Vox Raider") - src.Weaken(5) - return - - var/use_hand = "left" - if(l_hand) - if(r_hand) - src << "\red You need to have one hand free to grab someone." - return - else - use_hand = "right" - - src.visible_message("\The [src] seizes [T] aggressively!") - - var/obj/item/weapon/grab/G = new(src,T) - if(use_hand == "left") - l_hand = G - else - r_hand = G - - G.state = GRAB_AGGRESSIVE - G.icon_state = "grabbed1" - G.synch() - -/mob/living/carbon/human/proc/gut() - set category = "IC" - set name = "Gut" - set desc = "While grabbing someone aggressively, rip their guts out or tear them apart." - - if(last_special > world.time) - return - - if(stat || paralysis || stunned || weakened || lying) - src << "\red You cannot do that in your current state." - return - - var/obj/item/weapon/grab/G = locate() in src - if(!G || !istype(G)) - src << "\red You are not grabbing anyone." - return - - if(G.state < GRAB_AGGRESSIVE) - src << "\red You must have an aggressive grab to gut your prey!" - return - - last_special = world.time + 50 - - visible_message("\The [src] rips viciously at \the [G.affecting]'s body with its claws!") - - if(istype(G.affecting,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = G.affecting - H.apply_damage(50,BRUTE) - if(H.stat == 2) - H.gib() - else - var/mob/living/M = G.affecting - if(!istype(M)) return //wut - M.apply_damage(50,BRUTE) - if(M.stat == 2) - M.gib() - -/mob/living/carbon/human/proc/commune() - set category = "IC" - set name = "Commune with creature" - set desc = "Send a telepathic message to an unlucky recipient." - - var/list/targets = list() - var/target = null - var/text = null - - targets += getmobs() //Fill list, prompt user with list - target = input("Select a creature!", "Speak to creature", null, null) as null|anything in targets - - if(!target) return - - text = input("What would you like to say?", "Speak to creature", null, null) - - text = trim(copytext(sanitize(text), 1, MAX_MESSAGE_LEN)) - - if(!text) return - - var/mob/M = targets[target] - - if(istype(M, /mob/dead/observer) || M.stat == DEAD) - src << "Not even a [src.species.name] can speak to the dead." - return - - log_say("[key_name(src)] communed to [key_name(M)]: [text]") - - M << "\blue Like lead slabs crashing into the ocean, alien thoughts drop into your mind: [text]" - if(istype(M,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - if(H.species.name == src.species.name) - return - H << "\red Your nose begins to bleed..." - H.drip(1) - /mob/living/carbon/human/print_flavor_text() var/list/equipment = list(src.head,src.wear_mask,src.glasses,src.w_uniform,src.wear_suit,src.gloves,src.shoes) var/head_exposed = 1 @@ -1567,3 +1403,27 @@ flavor_text += flavor_texts[T] flavor_text += "\n\n" return ..() + +/mob/living/carbon/human/getDNA() + if(species.flags & NO_SCAN) + return null + ..() + +/mob/living/carbon/human/setDNA() + if(species.flags & NO_SCAN) + return + ..() + +/mob/living/carbon/human/has_brain() + if(internal_organs_by_name["brain"]) + var/datum/organ/internal/brain = internal_organs_by_name["brain"] + if(brain && istype(brain)) + return 1 + return 0 + +/mob/living/carbon/human/has_eyes() + if(internal_organs_by_name["eyes"]) + var/datum/organ/internal/eyes = internal_organs_by_name["eyes"] + if(eyes && istype(eyes) && !eyes.status & ORGAN_CUT_AWAY) + return 1 + return 0 diff --git a/code/modules/mob/living/carbon/human/human_attackalien.dm b/code/modules/mob/living/carbon/human/human_attackalien.dm deleted file mode 100644 index ea73d63f8d..0000000000 --- a/code/modules/mob/living/carbon/human/human_attackalien.dm +++ /dev/null @@ -1,62 +0,0 @@ -/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - if(check_shields(0, M.name)) - visible_message("\red [M] attempted to touch [src]!") - return 0 - - switch(M.a_intent) - if ("help") - visible_message(text("\blue [M] caresses [src] with its scythe like arm.")) - if ("grab") - if(M == src || anchored) - return - if (w_uniform) - w_uniform.add_fingerprint(M) - var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src) - - M.put_in_active_hand(G) - - grabbed_by += G - G.synch() - LAssailant = M - - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - visible_message(text("\red [] has grabbed [] passively!", M, src)) - - if("hurt") - if (w_uniform) - w_uniform.add_fingerprint(M) - var/damage = rand(15, 30) - if(!damage) - playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1) - visible_message("\red [M] has lunged at [src]!") - return 0 - var/datum/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting)) - var/armor_block = run_armor_check(affecting, "melee") - - playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) - visible_message("\red [M] has slashed at [src]!") - - apply_damage(damage, BRUTE, affecting, armor_block) - if (damage >= 25) - visible_message("\red [M] has wounded [src]!") - apply_effect(rand(0.5,3), WEAKEN, armor_block) - updatehealth() - - if("disarm") - if (prob(80)) - playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) - Weaken(rand(0.5,3)) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has tackled down []!", M, src), 1) - if (prob(25)) - M.Weaken(rand(2,4)) - else - if (prob(80)) - playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1) - drop_item() - visible_message(text("\red [] disarmed []!", M, src)) - else - playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1) - visible_message(text("\red [] has tried to disarm []!", M, src)) - return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index bacef8541b..46e70c06ac 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -111,7 +111,13 @@ return 1 if("hurt") + + // See if they can attack, and which attacks to use. var/datum/unarmed_attack/attack = M.species.unarmed + if(!attack.is_usable(M)) + attack = M.species.secondary_unarmed + if(!attack.is_usable(M)) + return 0 M.attack_log += text("\[[time_stamp()]\] [pick(attack.attack_verb)]ed [src.name] ([src.ckey])") src.attack_log += text("\[[time_stamp()]\] Has been [pick(attack.attack_verb)]ed by [M.name] ([M.ckey])") diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 01caff57e5..b115ffe94c 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -1,7 +1,8 @@ //Updates the mob's health from organs and mob damage variables /mob/living/carbon/human/updatehealth() + if(status_flags & GODMODE) - health = 100 + health = species.total_health stat = CONSCIOUS return var/total_burn = 0 @@ -9,21 +10,57 @@ for(var/datum/organ/external/O in organs) //hardcoded to streamline things a bit total_brute += O.brute_dam total_burn += O.burn_dam - health = 100 - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute + + var/oxy_l = (species.flags & NO_BREATHE ? 0 : getOxyLoss()) + var/tox_l = (species.flags & NO_POISON ? 0 : getToxLoss()) + var/clone_l = getCloneLoss() //TODO: link this to NO_SCAN + + health = species.total_health - oxy_l - tox_l - clone_l - total_burn - total_brute + //TODO: fix husking - if( ((100 - total_burn) < config.health_threshold_dead) && stat == DEAD) //100 only being used as the magic human max health number, feel free to change it if you add a var for it -- Urist + if( ((species.total_health - total_burn) < config.health_threshold_dead) && stat == DEAD) ChangeToHusk() return +/mob/living/carbon/human/adjustBrainLoss(var/amount) + + if(status_flags & GODMODE) return 0 //godmode + + if(species && species.has_organ["brain"]) + var/datum/organ/internal/brain/sponge = internal_organs_by_name["brain"] + if(sponge) + sponge.take_damage(amount) + sponge.damage = min(max(brainloss, 0),(maxHealth*2)) + brainloss = sponge.damage + else + brainloss = 200 + else + brainloss = 0 + +/mob/living/carbon/human/setBrainLoss(var/amount) + + if(status_flags & GODMODE) return 0 //godmode + + if(species && species.has_organ["brain"]) + var/datum/organ/internal/brain/sponge = internal_organs_by_name["brain"] + if(sponge) + sponge.damage = min(max(amount, 0),(maxHealth*2)) + brainloss = sponge.damage + else + brainloss = 200 + else + brainloss = 0 + /mob/living/carbon/human/getBrainLoss() - var/res = brainloss - var/datum/organ/internal/brain/sponge = internal_organs_by_name["brain"] - if (sponge.is_bruised()) - res += 20 - if (sponge.is_broken()) - res += 50 - res = min(res,maxHealth*2) - return res + + if(status_flags & GODMODE) return 0 //godmode + + if(species && species.has_organ["brain"]) + var/datum/organ/internal/brain/sponge = internal_organs_by_name["brain"] + brainloss = min(sponge.damage,maxHealth*2) + else + brainloss = 0 + return brainloss //These procs fetch a cumulative total damage from all organs /mob/living/carbon/human/getBruteLoss() @@ -264,20 +301,20 @@ This function restores all organs. /mob/living/carbon/human/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/sharp = 0, var/edge = 0, var/obj/used_weapon = null) //visible_message("Hit debug. [damage] | [damagetype] | [def_zone] | [blocked] | [sharp] | [used_weapon]") - + //Handle other types of damage if((damagetype != BRUTE) && (damagetype != BURN)) if(damagetype == HALLOSS) if ((damage > 25 && prob(20)) || (damage > 50 && prob(60))) emote("scream") - - + + ..(damage, damagetype, def_zone, blocked) return 1 //Handle BRUTE and BURN damage handle_suit_punctures(damagetype, damage) - + if(blocked >= 2) return 0 var/datum/organ/external/organ = null diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 337d32652c..30c883becb 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -1,8 +1,9 @@ /mob/living/carbon/human/movement_delay() + var/tally = 0 - if(species && species.flags & IS_SLOW) - tally = 7 + if(species.slowdown) + tally = species.slowdown if (istype(loc, /turf/space)) return -1 // It's hard to be slowed down in space by... anything @@ -79,6 +80,10 @@ /mob/living/carbon/human/Process_Spaceslipping(var/prob_slip = 5) //If knocked out we might just hit it and stop. This makes it possible to get dead bodies and such. + + if(species.flags & NO_SLIP) + return + if(stat) prob_slip = 0 // Changing this to zero to make it line up with the comment, and also, make more sense. diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm new file mode 100644 index 0000000000..1837380855 --- /dev/null +++ b/code/modules/mob/living/carbon/human/human_powers.dm @@ -0,0 +1,221 @@ +// These should all be procs, you can add them to humans/subspecies by +// species.dm's inherent_verbs ~ Z + +/mob/living/carbon/human/proc/tackle() + set category = "Abilities" + set name = "Tackle" + set desc = "Tackle someone down." + + if(last_special > world.time) + return + + if(stat || paralysis || stunned || weakened || lying || restrained() || buckled) + src << "You cannot tackle someone in your current state." + return + + var/list/choices = list() + for(var/mob/living/M in view(6,src)) + if(!istype(M,/mob/living/silicon)) + choices += M + choices -= src + + var/mob/living/T = input(src,"Who do you wish to tackle?") as null|anything in choices + + if(!T || !src || src.stat) return + + if(get_dist(get_turf(T), get_turf(src)) > 6) return + + if(last_special > world.time) + return + + if(stat || paralysis || stunned || weakened || lying || restrained() || buckled) + src << "You cannot leap in your current state." + return + + last_special = world.time + 50 + + var/failed + if(prob(75)) + T.Weaken(rand(0.5,3)) + else + src.Weaken(rand(2,4)) + failed = 1 + + playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) + if(failed) + src.Weaken(rand(2,4)) + + for(var/mob/O in viewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("\red [] [failed ? "tried to tackle" : "has tackled"] down []!", src, T), 1) + +/mob/living/carbon/human/proc/leap() + set category = "Abilities" + set name = "Leap" + set desc = "Leap at a target and grab them aggressively." + + if(last_special > world.time) + return + + if(stat || paralysis || stunned || weakened || lying || restrained() || buckled) + src << "You cannot leap in your current state." + return + + var/list/choices = list() + for(var/mob/living/M in view(6,src)) + if(!istype(M,/mob/living/silicon)) + choices += M + choices -= src + + var/mob/living/T = input(src,"Who do you wish to leap at?") as null|anything in choices + + if(!T || !src || src.stat) return + + if(get_dist(get_turf(T), get_turf(src)) > 6) return + + if(last_special > world.time) + return + + if(stat || paralysis || stunned || weakened || lying || restrained() || buckled) + src << "You cannot leap in your current state." + return + + last_special = world.time + 75 + status_flags |= LEAPING + + src.visible_message("\The [src] leaps at [T]!") + src.throw_at(get_step(get_turf(T),get_turf(src)), 5, 1, src) + playsound(src.loc, 'sound/voice/shriek1.ogg', 50, 1) + + sleep(5) + + if(status_flags & LEAPING) status_flags &= ~LEAPING + + if(!src.Adjacent(T)) + src << "\red You miss!" + return + + T.Weaken(5) + + //Only official cool kids get the grab and no self-prone. + if(src.mind && src.mind.special_role) + src.Weaken(5) + return + + var/use_hand = "left" + if(l_hand) + if(r_hand) + src << "\red You need to have one hand free to grab someone." + return + else + use_hand = "right" + + src.visible_message("\The [src] seizes [T] aggressively!") + + var/obj/item/weapon/grab/G = new(src,T) + if(use_hand == "left") + l_hand = G + else + r_hand = G + + G.state = GRAB_AGGRESSIVE + G.icon_state = "grabbed1" + G.synch() + +/mob/living/carbon/human/proc/gut() + set category = "Abilities" + set name = "Gut" + set desc = "While grabbing someone aggressively, rip their guts out or tear them apart." + + if(last_special > world.time) + return + + if(stat || paralysis || stunned || weakened || lying) + src << "\red You cannot do that in your current state." + return + + var/obj/item/weapon/grab/G = locate() in src + if(!G || !istype(G)) + src << "\red You are not grabbing anyone." + return + + if(G.state < GRAB_AGGRESSIVE) + src << "\red You must have an aggressive grab to gut your prey!" + return + + last_special = world.time + 50 + + visible_message("\The [src] rips viciously at \the [G.affecting]'s body with its claws!") + + if(istype(G.affecting,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = G.affecting + H.apply_damage(50,BRUTE) + if(H.stat == 2) + H.gib() + else + var/mob/living/M = G.affecting + if(!istype(M)) return //wut + M.apply_damage(50,BRUTE) + if(M.stat == 2) + M.gib() + +/mob/living/carbon/human/proc/commune() + set category = "Abilities" + set name = "Commune with creature" + set desc = "Send a telepathic message to an unlucky recipient." + + var/list/targets = list() + var/target = null + var/text = null + + targets += getmobs() //Fill list, prompt user with list + target = input("Select a creature!", "Speak to creature", null, null) as null|anything in targets + + if(!target) return + + text = input("What would you like to say?", "Speak to creature", null, null) + + text = trim(copytext(sanitize(text), 1, MAX_MESSAGE_LEN)) + + if(!text) return + + var/mob/M = targets[target] + + if(istype(M, /mob/dead/observer) || M.stat == DEAD) + src << "Not even a [src.species.name] can speak to the dead." + return + + log_say("[key_name(src)] communed to [key_name(M)]: [text]") + + M << "\blue Like lead slabs crashing into the ocean, alien thoughts drop into your mind: [text]" + if(istype(M,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + if(H.species.name == src.species.name) + return + H << "\red Your nose begins to bleed..." + H.drip(1) + +/mob/living/carbon/human/proc/regurgitate() + set name = "Regurgitate" + set desc = "Empties the contents of your stomach" + set category = "Abilities" + + if(stomach_contents.len) + for(var/mob/M in src) + if(M in stomach_contents) + stomach_contents.Remove(M) + M.loc = loc + src.visible_message("\red [src] hurls out the contents of their stomach!") + return + +/mob/living/carbon/human/proc/psychic_whisper(mob/M as mob in oview()) + set name = "Psychic Whisper" + set desc = "Whisper silently to someone over a distance." + set category = "Abilities" + + var/msg = sanitize(input("Message:", "Psychic Whisper") as text|null) + if(msg) + log_say("PsychicWhisper: [key_name(src)]->[M.key] : [msg]") + M << "\green You hear a strange, alien voice in your head... \italic [msg]" + src << "\green You said: \"[msg]\" to [M]" + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_species.dm b/code/modules/mob/living/carbon/human/human_species.dm new file mode 100644 index 0000000000..c313c6015e --- /dev/null +++ b/code/modules/mob/living/carbon/human/human_species.dm @@ -0,0 +1,34 @@ +// These may have some say.dm bugs regarding understanding common, +// might be worth adapting the bugs into a feature and using these +// subtypes as a basis for non-common-speaking alien foreigners. ~ Z + +/mob/living/carbon/human/dummy + real_name = "Test Dummy" + status_flags = GODMODE|CANPUSH + +/mob/living/carbon/human/skrell/New(var/new_loc) + h_style = "Skrell Male Tentacles" + ..(new_loc, "Skrell") + +/mob/living/carbon/human/tajaran/New(var/new_loc) + h_style = "Tajaran Ears" + ..(new_loc, "Tajaran") + +/mob/living/carbon/human/unathi/New(var/new_loc) + h_style = "Unathi Horns" + ..(new_loc, "Unathi") + +/mob/living/carbon/human/vox/New(var/new_loc) + h_style = "Short Vox Quills" + ..(new_loc, "Vox") + +/mob/living/carbon/human/voxarmalis/New(var/new_loc) + h_style = "Bald" + ..(new_loc, "Vox Armalis") + +/mob/living/carbon/human/diona/New(var/new_loc) + ..(new_loc, "Diona") + +/mob/living/carbon/human/machine/New(var/new_loc) + h_style = "blue IPC screen" + ..(new_loc, "Machine") \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index c5fb663116..e15a622950 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -95,6 +95,9 @@ //Disabilities handle_disabilities() + //Organ failure. + handle_organs() + //Random events (vomiting etc) handle_random_events() @@ -279,7 +282,8 @@ radiation = Clamp(radiation,0,100) if (radiation) - if(species.flags & RAD_ABSORB) + var/datum/organ/internal/diona/nutrients/rad_organ = locate() in internal_organs + if(!rad_organ || rad_organ.is_broken()) var/rads = radiation/25 radiation -= rads nutrition += rads @@ -635,9 +639,13 @@ return 1 proc/handle_environment(datum/gas_mixture/environment) + if(!environment) return + //Stuff like the xenomorph's plasma regen happens here. + species.handle_environment_special(src) + //Moved pressure calculations here for use in skip-processing check. var/pressure = environment.return_pressure() var/adjusted_pressure = calculate_affecting_pressure(pressure) @@ -977,7 +985,8 @@ if(status_flags & GODMODE) return 0 //godmode - if(species.flags & REQUIRE_LIGHT) + var/datum/organ/internal/diona/node/light_organ = locate() in internal_organs + if(light_organ && !light_organ.is_broken()) var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing if(isturf(loc)) //else, there's considered to be no light var/turf/T = loc @@ -1040,7 +1049,7 @@ if(overeatduration > 1) overeatduration -= 2 //doubled the unfat rate - if(species.flags & REQUIRE_LIGHT) + if(!light_organ || light_organ.is_broken()) if(nutrition < 200) take_overall_damage(2,0) traumatic_shock++ @@ -1081,7 +1090,7 @@ handle_organs() //Optimized. handle_blood() - if(health <= config.health_threshold_dead || brain_op_stage == 4.0) + if(health <= config.health_threshold_dead || (species.has_organ["brain"] && !has_brain())) death() blinded = 1 silent = 0 @@ -1160,15 +1169,23 @@ //Eyes - if(sdisabilities & BLIND) //disabled-blind, doesn't get better on its own - blinded = 1 - else if(eye_blind) //blindness, heals slowly over time - eye_blind = max(eye_blind-1,0) - blinded = 1 + if(!species.has_organ["eyes"]) // Presumably if a species has no eyes, they see via something else. + eye_blind = 0 + blinded = 0 + eye_blurry = 0 + else if(!has_eyes()) // Eyes cut out? Permablind. + eye_blind = 1 + blinded = 1 + eye_blurry = 1 + else if(sdisabilities & BLIND) // Disabled-blind, doesn't get better on its own + blinded = 1 + else if(eye_blind) // Blindness, heals slowly over time + eye_blind = max(eye_blind-1,0) + blinded = 1 else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) //resting your eyes with a blindfold heals blurry eyes faster eye_blurry = max(eye_blurry-3, 0) - blinded = 1 - else if(eye_blurry) //blurry eyes heal slowly + blinded = 1 + else if(eye_blurry) // Blurry eyes heal slowly eye_blurry = max(eye_blurry-1, 0) //Ears @@ -1649,8 +1666,8 @@ if(stat == 2) holder.icon_state = "hudhealth-100" // X_X else - holder.icon_state = "hud[RoundHealth(health)]" - + var/percentage_health = RoundHealth(((0.0+health)/species.total_health)*100) + holder.icon_state = "hud[percentage_health]" hud_list[HEALTH_HUD] = holder if(hud_updateflag & 1 << STATUS_HUD) diff --git a/code/modules/mob/living/carbon/human/login.dm b/code/modules/mob/living/carbon/human/login.dm index 80d6f00288..d18d503502 100644 --- a/code/modules/mob/living/carbon/human/login.dm +++ b/code/modules/mob/living/carbon/human/login.dm @@ -2,4 +2,5 @@ ..() update_hud() ticker.mode.update_all_synd_icons() //This proc only sounds CPU-expensive on paper. It is O(n^2), but the outer for-loop only iterates through syndicates, which are only prsenet in nuke rounds and even when they exist, there's usually 6 of them. - return + if(species) species.handle_login_special(src) + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/logout.dm b/code/modules/mob/living/carbon/human/logout.dm new file mode 100644 index 0000000000..f449ce991a --- /dev/null +++ b/code/modules/mob/living/carbon/human/logout.dm @@ -0,0 +1,4 @@ +/mob/living/carbon/human/Logout() + ..() + if(species) species.handle_logout_special(src) + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 8d361c7060..21b336a650 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -1,4 +1,7 @@ /mob/living/carbon/human/say(var/message) + + //TODO: Add checks for species who do not speak common. + var/verb = "says" var/alt_name = "" var/message_range = world.view @@ -16,9 +19,6 @@ var/message_mode = parse_message_mode(message, "headset") - if (istype(wear_mask, /obj/item/clothing/mask/muzzle) && message_mode != "changeling") //Todo: Add this to speech_problem_flag checks. - return - if(copytext(message,1,2) == "*") return emote(copytext(message,2)) @@ -38,6 +38,15 @@ verb = speaking.speech_verb message = copytext(message,3) + // This is broadcast to all mobs with the language, + // irrespective of distance or anything else. + if(speaking.flags & HIVEMIND) + speaking.broadcast(src,trim(message)) + return + + if (istype(wear_mask, /obj/item/clothing/mask/muzzle)) + return + message = capitalize(trim(message)) if(speech_problem_flag) @@ -103,16 +112,6 @@ if("whisper") whisper_say(message, speaking, alt_name) return - if("binary") - if(robot_talk_understand || binarycheck()) - robot_talk(message) - return - if("changeling") - if(mind && mind.changeling) - for(var/mob/Changeling in mob_list) - if((Changeling.mind && Changeling.mind.changeling) || istype(Changeling, /mob/dead/observer)) - Changeling << "[mind.changeling.changelingID]: [message]" - return else if(message_mode) if(message_mode in (radiochannels | "department")) @@ -125,8 +124,8 @@ var/sound/speech_sound var/sound_vol - if((species.name == "Vox" || species.name == "Vox Armalis") && prob(20)) - speech_sound = sound('sound/voice/shriek1.ogg') + if(species.speech_sounds && prob(20)) + speech_sound = sound(pick(species.speech_sounds)) sound_vol = 50 ..(message, speaking, verb, alt_name, italics, message_range, used_radios, speech_sound, sound_vol) //ohgod we should really be passing a datum here. @@ -172,8 +171,8 @@ //These only pertain to common. Languages are handled by mob/say_understands() if (!speaking) - if (istype(other, /mob/living/carbon/monkey/diona)) - if(other.languages.len >= 2) //They've sucked down some blood and can speak common now. + if (istype(other, /mob/living/carbon/alien/diona)) + if(other.languages.len >= 2) //They've sucked down some blood and can speak common now. return 1 if (istype(other, /mob/living/silicon)) return 1 diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm new file mode 100644 index 0000000000..6b4e3b4586 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species.dm @@ -0,0 +1,562 @@ +/* + Datum-based species. Should make for much cleaner and easier to maintain mutantrace code. +*/ + +/datum/species + + var/name // Species name. + + var/icobase = 'icons/mob/human_races/r_human.dmi' // Normal icon set. + var/deform = 'icons/mob/human_races/r_def_human.dmi' // Mutated icon set. + var/prone_icon // If set, draws this from icobase when mob is prone. + var/eyes = "eyes_s" // Icon for eyes. + + var/primitive // Lesser form, if any (ie. monkey for humans) + var/tail // Name of tail image in species effects icon file. + var/language // Default racial language, if any. + var/datum/unarmed_attack/unarmed // For empty hand harm-intent attack + var/datum/unarmed_attack/secondary_unarmed // For empty hand harm-intent attack if the first fails. + var/datum/hud_data/hud + var/hud_type + var/slowdown = 0 + var/gluttonous // Can eat some mobs. 1 for monkeys, 2 for people. + var/rarity_value = 1 // Relative rarity/collector value for this species. Only used by ninja and cultists atm. + var/unarmed_type = /datum/unarmed_attack + var/secondary_unarmed_type = /datum/unarmed_attack/bite + + var/secondary_langs = list() // The names of secondary languages that are available to this species. + var/mutantrace // Safeguard due to old code. + var/list/speech_sounds // A list of sounds to potentially play when speaking. + var/has_fine_manipulation = 1 // Can use small items. + var/insulated // Immune to electrocution and glass shards to the feet. + + // Some species-specific gibbing data. + var/gibbed_anim = "gibbed-h" + var/dusted_anim = "dust-h" + var/remains_type = /obj/effect/decal/remains/xeno + var/death_sound + var/death_message = "seizes up and falls limp, their eyes dead and lifeless..." + + var/breath_type = "oxygen" // Non-oxygen gas breathed, if any. + var/poison_type = "phoron" // Poisonous air. + var/exhale_type = "carbon_dioxide" // Exhaled gas type. + + var/total_health = 100 //Point at which the mob will enter crit. + + var/cold_level_1 = 260 // Cold damage level 1 below this point. + var/cold_level_2 = 200 // Cold damage level 2 below this point. + var/cold_level_3 = 120 // Cold damage level 3 below this point. + + var/heat_level_1 = 360 // Heat damage level 1 above this point. + var/heat_level_2 = 400 // Heat damage level 2 above this point. + var/heat_level_3 = 1000 // Heat damage level 2 above this point. + + var/body_temperature = 310.15 //non-IS_SYNTHETIC species will try to stabilize at this temperature. (also affects temperature processing) + var/synth_temp_gain = 0 //IS_SYNTHETIC species will gain this much temperature every second + var/reagent_tag //Used for metabolizing reagents. + + var/darksight = 2 + var/hazard_high_pressure = HAZARD_HIGH_PRESSURE // Dangerously high pressure. + var/warning_high_pressure = WARNING_HIGH_PRESSURE // High pressure warning. + var/warning_low_pressure = WARNING_LOW_PRESSURE // Low pressure warning. + var/hazard_low_pressure = HAZARD_LOW_PRESSURE // Dangerously low pressure. + + var/brute_mod = null // Physical damage reduction/malus. + var/burn_mod = null // Burn damage reduction/malus. + + var/flags = 0 // Various specific features. + + var/list/abilities = list() // For species-derived or admin-given powers + + var/blood_color = "#A10808" //Red. + var/flesh_color = "#FFC896" //Pink. + var/base_color //Used when setting species. + + //Used in icon caching. + var/race_key = 0 + var/icon/icon_template + + // Species-specific abilities. + var/list/inherent_verbs + var/list/has_organ = list( + "heart" = /datum/organ/internal/heart, + "lungs" = /datum/organ/internal/lungs, + "liver" = /datum/organ/internal/liver, + "kidneys" = /datum/organ/internal/kidney, + "brain" = /datum/organ/internal/brain, + "appendix" = /datum/organ/internal/appendix, + "eyes" = /datum/organ/internal/eyes + ) + +/datum/species/New() + if(hud_type) + hud = new hud_type() + else + hud = new() + + if(unarmed_type) unarmed = new unarmed_type() + if(secondary_unarmed_type) secondary_unarmed = new secondary_unarmed_type() + +/datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs. + + //Trying to work out why species changes aren't fixing organs properly. + if(H.organs) H.organs.Cut() + if(H.internal_organs) H.internal_organs.Cut() + if(H.organs_by_name) H.organs_by_name.Cut() + if(H.internal_organs_by_name) H.internal_organs_by_name.Cut() + + H.organs = list() + H.internal_organs = list() + H.organs_by_name = list() + H.internal_organs_by_name = list() + + //This is a basic humanoid limb setup. + H.organs_by_name["chest"] = new/datum/organ/external/chest() + H.organs_by_name["groin"] = new/datum/organ/external/groin(H.organs_by_name["chest"]) + H.organs_by_name["head"] = new/datum/organ/external/head(H.organs_by_name["chest"]) + H.organs_by_name["l_arm"] = new/datum/organ/external/l_arm(H.organs_by_name["chest"]) + H.organs_by_name["r_arm"] = new/datum/organ/external/r_arm(H.organs_by_name["chest"]) + H.organs_by_name["r_leg"] = new/datum/organ/external/r_leg(H.organs_by_name["groin"]) + H.organs_by_name["l_leg"] = new/datum/organ/external/l_leg(H.organs_by_name["groin"]) + H.organs_by_name["l_hand"] = new/datum/organ/external/l_hand(H.organs_by_name["l_arm"]) + H.organs_by_name["r_hand"] = new/datum/organ/external/r_hand(H.organs_by_name["r_arm"]) + H.organs_by_name["l_foot"] = new/datum/organ/external/l_foot(H.organs_by_name["l_leg"]) + H.organs_by_name["r_foot"] = new/datum/organ/external/r_foot(H.organs_by_name["r_leg"]) + + for(var/organ in has_organ) + var/organ_type = has_organ[organ] + H.internal_organs_by_name[organ] = new organ_type(H) + + for(var/name in H.organs_by_name) + H.organs += H.organs_by_name[name] + + for(var/datum/organ/external/O in H.organs) + O.owner = H + + if(flags & IS_SYNTHETIC) + for(var/datum/organ/external/E in H.organs) + if(E.status & ORGAN_CUT_AWAY || E.status & ORGAN_DESTROYED) continue + E.status |= ORGAN_ROBOT + for(var/datum/organ/internal/I in H.internal_organs) + I.mechanize() + +/datum/species/proc/hug(var/mob/living/carbon/human/H,var/mob/living/target) + + var/t_him = "them" + switch(target.gender) + if(MALE) + t_him = "him" + if(FEMALE) + t_him = "her" + + H.visible_message("[H] hugs [target] to make [t_him] feel better!", \ + "You hug [target] to make [t_him] feel better!") + +/datum/species/proc/remove_inherent_verbs(var/mob/living/carbon/human/H) + if(inherent_verbs) + for(var/verb_path in inherent_verbs) + H.verbs -= verb_path + return + +/datum/species/proc/add_inherent_verbs(var/mob/living/carbon/human/H) + if(inherent_verbs) + for(var/verb_path in inherent_verbs) + H.verbs |= verb_path + return + +/datum/species/proc/handle_post_spawn(var/mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment. + add_inherent_verbs(H) + +/datum/species/proc/handle_death(var/mob/living/carbon/human/H) //Handles any species-specific death events (such as dionaea nymph spawns). + if(flags & IS_SYNTHETIC) + H.h_style = "" + spawn(100) + H.update_hair() + return + +// Only used for alien plasma weeds atm, but could be used for Dionaea later. +/datum/species/proc/handle_environment_special(var/mob/living/carbon/human/H) + return + +// Used to update alien icons for aliens. +/datum/species/proc/handle_login_special(var/mob/living/carbon/human/H) + return + +// As above. +/datum/species/proc/handle_logout_special(var/mob/living/carbon/human/H) + return + +// Builds the HUD using species-specific icons and usable slots. +/datum/species/proc/build_hud(var/mob/living/carbon/human/H) + return + +// Grabs the window recieved when you click-drag someone onto you. +/datum/species/proc/get_inventory_dialogue(var/mob/living/carbon/human/H) + return + +/datum/species/human + name = "Human" + language = "Sol Common" + primitive = /mob/living/carbon/monkey + unarmed_type = /datum/unarmed_attack/punch + + flags = HAS_SKIN_TONE | HAS_LIPS | HAS_UNDERWEAR + + //If you wanted to add a species-level ability: + /*abilities = list(/client/proc/test_ability)*/ + +/datum/species/unathi + name = "Unathi" + icobase = 'icons/mob/human_races/r_lizard.dmi' + deform = 'icons/mob/human_races/r_def_lizard.dmi' + language = "Sinta'unathi" + tail = "sogtail" + unarmed_type = /datum/unarmed_attack/claws + secondary_unarmed_type = /datum/unarmed_attack/bite/strong + primitive = /mob/living/carbon/monkey/unathi + darksight = 3 + gluttonous = 1 + + cold_level_1 = 280 //Default 260 - Lower is better + cold_level_2 = 220 //Default 200 + cold_level_3 = 130 //Default 120 + + heat_level_1 = 420 //Default 360 - Higher is better + heat_level_2 = 480 //Default 400 + heat_level_3 = 1100 //Default 1000 + + flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL | HAS_SKIN_COLOR + + flesh_color = "#34AF10" + + reagent_tag = IS_UNATHI + base_color = "#066000" + +/datum/species/tajaran + name = "Tajaran" + icobase = 'icons/mob/human_races/r_tajaran.dmi' + deform = 'icons/mob/human_races/r_def_tajaran.dmi' + language = "Siik'tajr" + tail = "tajtail" + unarmed_type = /datum/unarmed_attack/claws + darksight = 8 + + cold_level_1 = 200 //Default 260 + cold_level_2 = 140 //Default 200 + cold_level_3 = 80 //Default 120 + + heat_level_1 = 330 //Default 360 + heat_level_2 = 380 //Default 400 + heat_level_3 = 800 //Default 1000 + + primitive = /mob/living/carbon/monkey/tajara + + flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL | HAS_SKIN_COLOR + + flesh_color = "#AFA59E" + base_color = "#333333" + +/datum/species/skrell + name = "Skrell" + icobase = 'icons/mob/human_races/r_skrell.dmi' + deform = 'icons/mob/human_races/r_def_skrell.dmi' + language = "Skrellian" + primitive = /mob/living/carbon/monkey/skrell + unarmed_type = /datum/unarmed_attack/punch + + flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR + + flesh_color = "#8CD7A3" + + reagent_tag = IS_SKRELL + +/datum/species/vox + name = "Vox" + icobase = 'icons/mob/human_races/r_vox.dmi' + deform = 'icons/mob/human_races/r_def_vox.dmi' + language = "Vox-pidgin" + unarmed_type = /datum/unarmed_attack/claws/strong + secondary_unarmed_type = /datum/unarmed_attack/bite/strong + rarity_value = 2 + + speech_sounds = list('sound/voice/shriek1.ogg') + + warning_low_pressure = 50 + hazard_low_pressure = 0 + + cold_level_1 = 80 + cold_level_2 = 50 + cold_level_3 = 0 + + eyes = "vox_eyes_s" + + breath_type = "nitrogen" + poison_type = "oxygen" + insulated = 1 + + flags = NO_SCAN + + blood_color = "#2299FC" + flesh_color = "#808D11" + + reagent_tag = IS_VOX + + inherent_verbs = list( + /mob/living/carbon/human/proc/leap + ) + + has_organ = list( + "heart" = /datum/organ/internal/heart, + "lungs" = /datum/organ/internal/lungs, + "liver" = /datum/organ/internal/liver, + "kidneys" = /datum/organ/internal/kidney, + "brain" = /datum/organ/internal/brain, + "eyes" = /datum/organ/internal/eyes, + "stack" = /datum/organ/internal/stack/vox + ) + +/datum/species/vox/armalis + name = "Vox Armalis" + icobase = 'icons/mob/human_races/r_armalis.dmi' + deform = 'icons/mob/human_races/r_armalis.dmi' + language = "Vox-pidgin" + rarity_value = 10 + + warning_low_pressure = 50 + hazard_low_pressure = 0 + + cold_level_1 = 80 + cold_level_2 = 50 + cold_level_3 = 0 + + heat_level_1 = 2000 + heat_level_2 = 3000 + heat_level_3 = 4000 + + brute_mod = 0.2 + burn_mod = 0.2 + + eyes = "blank_eyes" + breath_type = "nitrogen" + poison_type = "oxygen" + + flags = NO_SCAN | NO_BLOOD | HAS_TAIL | NO_PAIN + + blood_color = "#2299FC" + flesh_color = "#808D11" + + tail = "armalis_tail" + icon_template = 'icons/mob/human_races/r_armalis.dmi' + + reagent_tag = IS_VOX + + inherent_verbs = list( + /mob/living/carbon/human/proc/leap, + /mob/living/carbon/human/proc/gut, + /mob/living/carbon/human/proc/commune + ) + +/datum/species/diona + name = "Diona" + icobase = 'icons/mob/human_races/r_diona.dmi' + deform = 'icons/mob/human_races/r_def_plant.dmi' + language = "Rootspeak" + unarmed_type = /datum/unarmed_attack/diona + primitive = /mob/living/carbon/alien/diona + slowdown = 7 + rarity_value = 3 + + has_organ = list( + "nutrient channel" = /datum/organ/internal/diona/nutrients, + "neural strata" = /datum/organ/internal/diona/strata, + "response node" = /datum/organ/internal/diona/node, + "gas bladder" = /datum/organ/internal/diona/bladder, + "polyp segment" = /datum/organ/internal/diona/polyp, + "anchoring ligament" = /datum/organ/internal/diona/ligament + ) + + warning_low_pressure = 50 + hazard_low_pressure = -1 + + cold_level_1 = 50 + cold_level_2 = -1 + cold_level_3 = -1 + + heat_level_1 = 2000 + heat_level_2 = 3000 + heat_level_3 = 4000 + + body_temperature = T0C + 15 //make the plant people have a bit lower body temperature, why not + + flags = IS_WHITELISTED | NO_BREATHE | NO_SCAN | IS_PLANT | NO_BLOOD | NO_PAIN | NO_SLIP + + blood_color = "#004400" + flesh_color = "#907E4A" + + reagent_tag = IS_DIONA + +/datum/species/diona/handle_post_spawn(var/mob/living/carbon/human/H) + H.gender = NEUTER + return ..() + +/datum/species/diona/handle_death(var/mob/living/carbon/human/H) + + var/mob/living/carbon/alien/diona/S = new(get_turf(H)) + + if(H.mind) + H.mind.transfer_to(S) + + for(var/mob/living/carbon/alien/diona/D in H.contents) + if(D.client) + D.loc = H.loc + else + del(D) + + H.visible_message("\red[H] splits apart with a wet slithering noise!") + +/datum/species/machine + name = "Machine" + icobase = 'icons/mob/human_races/r_machine.dmi' + deform = 'icons/mob/human_races/r_machine.dmi' + language = "Tradeband" + unarmed_type = /datum/unarmed_attack/punch + rarity_value = 2 + + eyes = "blank_eyes" + brute_mod = 0.5 + burn_mod = 1 + + warning_low_pressure = 50 + hazard_low_pressure = 0 + + cold_level_1 = 50 + cold_level_2 = -1 + cold_level_3 = -1 + + heat_level_1 = 500 //gives them about 25 seconds in space before taking damage + heat_level_2 = 1000 + heat_level_3 = 2000 + + synth_temp_gain = 10 //this should cause IPCs to stabilize at ~80 C in a 20 C environment. + + flags = IS_WHITELISTED | NO_BREATHE | NO_SCAN | NO_BLOOD | NO_PAIN | IS_SYNTHETIC + + blood_color = "#1F181F" + flesh_color = "#575757" + + has_organ = list( + "heart" = /datum/organ/internal/heart, + "brain" = /datum/organ/internal/brain, + ) + +// Called when using the shredding behavior. +/datum/species/proc/can_shred(var/mob/living/carbon/human/H) + + if(H.a_intent != "hurt") + return 0 + + if(unarmed.shredding && unarmed.is_usable(H)) + return 1 + else if(secondary_unarmed.shredding && secondary_unarmed.is_usable(H)) + return 1 + + return 0 + +//Species unarmed attacks +/datum/unarmed_attack + var/attack_verb = list("attack") // Empty hand hurt intent verb. + var/damage = 0 // Extra empty hand attack damage. + var/attack_sound = "punch" + var/miss_sound = 'sound/weapons/punchmiss.ogg' + var/shredding = 0 // Calls the old attack_alien() behavior on objects/mobs when on harm intent. + var/sharp = 0 + var/edge = 0 + +/datum/unarmed_attack/proc/is_usable(var/mob/living/carbon/human/user) + if(user.restrained()) + return 0 + + // Check if they have a functioning hand. + var/datum/organ/external/E = user.organs_by_name["l_hand"] + if(E && !(E.status & ORGAN_DESTROYED)) + return 1 + + E = user.organs_by_name["r_hand"] + if(E && !(E.status & ORGAN_DESTROYED)) + return 1 + + return 0 + +/datum/unarmed_attack/bite + attack_verb = list("bite") // 'x has biteed y', needs work. + attack_sound = 'sound/weapons/bite.ogg' + shredding = 1 + damage = 5 + sharp = 1 + edge = 1 + +/datum/unarmed_attack/bite/is_usable(var/mob/living/carbon/human/user) + if (user.wear_mask && istype(user.wear_mask, /obj/item/clothing/mask/muzzle)) + return 0 + return 1 + +/datum/unarmed_attack/punch + attack_verb = list("punch") + damage = 3 + +/datum/unarmed_attack/diona + attack_verb = list("lash", "bludgeon") + damage = 5 + +/datum/unarmed_attack/claws + attack_verb = list("scratch", "claw") + attack_sound = 'sound/weapons/slice.ogg' + miss_sound = 'sound/weapons/slashmiss.ogg' + damage = 5 + sharp = 1 + edge = 1 + +/datum/unarmed_attack/claws/strong + attack_verb = list("slash") + damage = 10 + shredding = 1 + +/datum/unarmed_attack/bite/strong + attack_verb = list("maul") + damage = 15 + shredding = 1 + +/datum/hud_data + var/icon // If set, overrides ui_style. + var/has_a_intent = 1 // Set to draw intent box. + var/has_m_intent = 1 // Set to draw move intent box. + var/has_warnings = 1 // Set to draw environment warnings. + var/has_pressure = 1 // Draw the pressure indicator. + var/has_nutrition = 1 // Draw the nutrition indicator. + var/has_bodytemp = 1 // Draw the bodytemp indicator. + var/has_hands = 1 // Set to draw shand. + var/has_drop = 1 // Set to draw drop button. + var/has_throw = 1 // Set to draw throw button. + var/has_resist = 1 // Set to draw resist button. + var/has_internals = 1 // Set to draw the internals toggle button. + + // Contains information on the position and tag for all inventory slots + // to be drawn for the mob. This is fairly delicate, try to avoid messing with it + // unless you know exactly what it does. + var/list/gear = list( + "i_clothing" = list("loc" = ui_iclothing, "slot" = slot_w_uniform, "state" = "center", "toggle" = 1, "dir" = SOUTH), + "o_clothing" = list("loc" = ui_oclothing, "slot" = slot_wear_suit, "state" = "equip", "toggle" = 1, "dir" = SOUTH), + "mask" = list("loc" = ui_mask, "slot" = slot_wear_mask, "state" = "equip", "toggle" = 1, "dir" = NORTH), + "gloves" = list("loc" = ui_gloves, "slot" = slot_gloves, "state" = "gloves", "toggle" = 1), + "eyes" = list("loc" = ui_glasses, "slot" = slot_glasses, "state" = "glasses","toggle" = 1), + "l_ear" = list("loc" = ui_l_ear, "slot" = slot_l_ear, "state" = "ears", "toggle" = 1), + "r_ear" = list("loc" = ui_r_ear, "slot" = slot_r_ear, "state" = "ears", "toggle" = 1), + "head" = list("loc" = ui_head, "slot" = slot_head, "state" = "hair", "toggle" = 1), + "shoes" = list("loc" = ui_shoes, "slot" = slot_shoes, "state" = "shoes", "toggle" = 1), + "suit storage" = list("loc" = ui_sstore1, "slot" = slot_s_store, "state" = "belt", "dir" = 8), + "back" = list("loc" = ui_back, "slot" = slot_back, "state" = "back", "dir" = NORTH), + "id" = list("loc" = ui_id, "slot" = slot_wear_id, "state" = "id", "dir" = NORTH), + "storage1" = list("loc" = ui_storage1, "slot" = slot_l_store, "state" = "pocket"), + "storage2" = list("loc" = ui_storage2, "slot" = slot_r_store, "state" = "pocket"), + "belt" = list("loc" = ui_belt, "slot" = slot_belt, "state" = "belt") + ) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 2ae79230d2..a49760a527 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -161,7 +161,7 @@ Please contact me on #coderbus IRC. ~Carn x for(var/image/I in overlays_standing) overlays += I - if(lying) + if(lying && !species.prone_icon) //Only rotate them if we're not drawing a specific icon for being prone. var/matrix/M = matrix() M.Turn(90) M.Scale(size_multiplier) @@ -412,7 +412,7 @@ proc/get_damage_icon_part(damage_state, body_part) if(f_style) var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style] - if(facial_hair_style && src.species.name in facial_hair_style.species_allowed) + if(facial_hair_style && facial_hair_style.species_allowed && src.species.name in facial_hair_style.species_allowed) var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s") if(facial_hair_style.do_colouration) facial_s.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD) diff --git a/code/modules/mob/living/carbon/metroid/life.dm b/code/modules/mob/living/carbon/metroid/life.dm index c82d517d59..7820e2a416 100644 --- a/code/modules/mob/living/carbon/metroid/life.dm +++ b/code/modules/mob/living/carbon/metroid/life.dm @@ -362,11 +362,11 @@ else for(var/mob/living/carbon/C in targets) if(!Discipline && prob(5)) - if(ishuman(C) || isalienadult(C)) + if(ishuman(C)) Target = C break - if(islarva(C) || ismonkey(C)) + if(isalien(C) || ismonkey(C)) Target = C break diff --git a/code/modules/mob/living/carbon/metroid/metroid.dm b/code/modules/mob/living/carbon/metroid/metroid.dm index 67f0b904ed..df9d22c5dc 100644 --- a/code/modules/mob/living/carbon/metroid/metroid.dm +++ b/code/modules/mob/living/carbon/metroid/metroid.dm @@ -51,7 +51,12 @@ var/coretype = /obj/item/slime_extract/grey var/list/slime_mutation[4] + var/core_removal_stage = 0 //For removing cores. + /mob/living/carbon/slime/New() + + verbs += /mob/living/proc/ventcrawl + create_reagents(100) spawn (0) number = rand(1, 1000) @@ -272,7 +277,7 @@ updatehealth() return -/mob/living/carbon/slime/attack_animal(mob/living/simple_animal/M as mob) +/mob/living/carbon/slime/attack_animal(mob/living/M as mob) if(M.melee_damage_upper == 0) M.emote("[M.friendly] [src]") else @@ -445,93 +450,6 @@ visible_message("[M] has attempted to punch [src]!") return - - -/mob/living/carbon/slime/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - if (!ticker) - M << "You cannot attack people before the game has started." - return - - if (istype(loc, /turf) && istype(loc.loc, /area/start)) - M << "No attacking people at spawn, you jackass." - return - - switch(M.a_intent) - if ("help") - visible_message("[M] caresses [src] with its scythe like arm.") - - if ("hurt") - - if (prob(95)) - attacked += 10 - playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) - var/damage = rand(15, 30) - if (damage >= 25) - damage = rand(20, 40) - visible_message("[M] has attacked [name]!", \ - "[M] has attacked [name]!") - else - visible_message("[M] has wounded [name]!", \ - ")[M] has wounded [name]!") - adjustBruteLoss(damage) - updatehealth() - else - playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - visible_message("[M] has attempted to lunge at [name]!", \ - "[M] has attempted to lunge at [name]!") - - if ("grab") - if (M == src || anchored) - return - var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src ) - - M.put_in_active_hand(G) - - G.synch() - - LAssailant = M - - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - visible_message(" [M] has grabbed [name] passively!") - - if ("disarm") - playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) - var/damage = 5 - attacked += 10 - - if(prob(95)) - visible_message("[M] has tackled [name]!", \ - "[M] has tackled [name]!") - - if(Victim || Target) - Victim = null - Target = null - anchored = 0 - if(prob(80) && !client) - Discipline++ - if(!istype(src, /mob/living/carbon/slime)) - if(Discipline == 1) - attacked = 0 - - spawn() - SStun = 1 - sleep(rand(5,20)) - SStun = 0 - - spawn(0) - - step_away(src,M,15) - sleep(3) - step_away(src,M,15) - - else - drop_item() - visible_message("[M] has disarmed [name]!", - "[M] has disarmed [name]!") - adjustBruteLoss(damage) - updatehealth() - return - /mob/living/carbon/slime/attackby(obj/item/W, mob/user) if(W.force > 0) attacked += 10 @@ -613,6 +531,11 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 ++Discipline return +/mob/living/carbon/slime/can_use_vents() + if(Victim) + return "You cannot ventcrawl while feeding." + ..() + /obj/item/slime_extract name = "slime extract" desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"." @@ -984,6 +907,9 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 if(A) G << "Golem rune created in [A.name]." +/mob/living/carbon/slime/has_eyes() + return 0 + //////////////////////////////Old shit from metroids/RoRos, and the old cores, would not take much work to re-add them//////////////////////// /* diff --git a/code/modules/mob/living/carbon/metroid/powers.dm b/code/modules/mob/living/carbon/metroid/powers.dm index bb7dcbe7bb..15fdb60349 100644 --- a/code/modules/mob/living/carbon/metroid/powers.dm +++ b/code/modules/mob/living/carbon/metroid/powers.dm @@ -104,7 +104,7 @@ adjustBruteLoss(-10) adjustFireLoss(-10) adjustCloneLoss(-10) - + updatehealth() if(Victim) Victim.updatehealth() @@ -225,11 +225,4 @@ else src << "I am not ready to reproduce yet..." else - src << "I am not old enough to reproduce yet..." - -/mob/living/carbon/slime/verb/ventcrawl() - set name = "Crawl through Vent" - set desc = "Enter an air vent and crawl through the pipe system." - set category = "Slime" - if(Victim) return - handle_ventcrawl() \ No newline at end of file + src << "I am not old enough to reproduce yet..." \ No newline at end of file diff --git a/code/modules/mob/living/carbon/monkey/diona.dm b/code/modules/mob/living/carbon/monkey/diona.dm deleted file mode 100644 index 0a12334701..0000000000 --- a/code/modules/mob/living/carbon/monkey/diona.dm +++ /dev/null @@ -1,267 +0,0 @@ -/* - Tiny babby plant critter plus procs. -*/ - -//Mob defines. -/mob/living/carbon/monkey/diona - name = "diona nymph" - voice_name = "diona nymph" - speak_emote = list("chirrups") - icon_state = "nymph1" - var/list/donors = list() - var/ready_evolve = 0 - universal_understand = 0 // Dionaea do not need to speak to people - universal_speak = 0 // before becoming an adult. Use *chirp. - holder_type = /obj/item/weapon/holder/diona - -/mob/living/carbon/monkey/diona/attack_hand(mob/living/carbon/human/M as mob) - - //Let people pick the little buggers up. - if(M.a_intent == "help") - if(M.species && M.species.name == "Diona") - M << "You feel your being twine with that of [src] as it merges with your biomass." - src << "You feel your being twine with that of [M] as you merge with its biomass." - src.verbs += /mob/living/carbon/monkey/diona/proc/split - src.verbs -= /mob/living/carbon/monkey/diona/proc/merge - src.loc = M - else - get_scooped(M) - - ..() - -/mob/living/carbon/monkey/diona/New() - - ..() - gender = NEUTER - dna.mutantrace = "plant" - greaterform = "Diona" - add_language("Rootspeak") - src.verbs += /mob/living/carbon/monkey/diona/proc/merge - -//Verbs after this point. - -/mob/living/carbon/monkey/diona/proc/merge() - - set category = "Diona" - set name = "Merge with gestalt" - set desc = "Merge with another diona." - - if(istype(src.loc,/mob/living/carbon)) - src.verbs -= /mob/living/carbon/monkey/diona/proc/merge - return - - var/list/choices = list() - for(var/mob/living/carbon/C in view(1,src)) - - if(!(src.Adjacent(C)) || !(C.client)) continue - - if(istype(C,/mob/living/carbon/human)) - var/mob/living/carbon/human/D = C - if(D.species && D.species.name == "Diona") - choices += C - - var/mob/living/M = input(src,"Who do you wish to merge with?") in null|choices - - if(!M || !src || !(src.Adjacent(M))) return - - if(istype(M,/mob/living/carbon/human)) - M << "You feel your being twine with that of [src] as it merges with your biomass." - M.status_flags |= PASSEMOTES - - src << "You feel your being twine with that of [M] as you merge with its biomass." - src.loc = M - src.verbs += /mob/living/carbon/monkey/diona/proc/split - src.verbs -= /mob/living/carbon/monkey/diona/proc/merge - else - return - -/mob/living/carbon/monkey/diona/proc/split() - - set category = "Diona" - set name = "Split from gestalt" - set desc = "Split away from your gestalt as a lone nymph." - - if(!(istype(src.loc,/mob/living/carbon))) - src.verbs -= /mob/living/carbon/monkey/diona/proc/split - return - - src.loc << "You feel a pang of loss as [src] splits away from your biomass." - src << "You wiggle out of the depths of [src.loc]'s biomass and plop to the ground." - - var/mob/living/M = src.loc - - src.loc = get_turf(src) - src.verbs -= /mob/living/carbon/monkey/diona/proc/split - src.verbs += /mob/living/carbon/monkey/diona/proc/merge - - if(istype(M)) - for(var/atom/A in M.contents) - if(istype(A,/mob/living/simple_animal/borer) || istype(A,/obj/item/weapon/holder)) - return - M.status_flags &= ~PASSEMOTES - -/mob/living/carbon/monkey/diona/verb/fertilize_plant() - - set category = "Diona" - set name = "Fertilize plant" - set desc = "Turn your food into nutrients for plants." - - var/list/trays = list() - for(var/obj/machinery/portable_atmospherics/hydroponics/tray in range(1)) - if(tray.nutrilevel < 10 && src.Adjacent(tray)) - trays += tray - - var/obj/machinery/portable_atmospherics/hydroponics/target = input("Select a tray:") as null|anything in trays - - if(!src || !target || target.nutrilevel == 10) return //Sanity check. - - src.nutrition -= ((10-target.nutrilevel)*5) - target.nutrilevel = 10 - src.visible_message("\red [src] secretes a trickle of green liquid from its tail, refilling [target]'s nutrient tray.","\red You secrete a trickle of green liquid from your tail, refilling [target]'s nutrient tray.") - -/mob/living/carbon/monkey/diona/verb/eat_weeds() - - set category = "Diona" - set name = "Eat Weeds" - set desc = "Clean the weeds out of soil or a hydroponics tray." - - var/list/trays = list() - for(var/obj/machinery/portable_atmospherics/hydroponics/tray in range(1)) - if(tray.weedlevel > 0 && src.Adjacent(tray)) - trays += tray - - var/obj/machinery/portable_atmospherics/hydroponics/target = input("Select a tray:") as null|anything in trays - - if(!src || !target || target.weedlevel == 0) return //Sanity check. - - src.reagents.add_reagent("nutriment", target.weedlevel) - target.weedlevel = 0 - src.visible_message("\red [src] begins rooting through [target], ripping out weeds and eating them noisily.","\red You begin rooting through [target], ripping out weeds and eating them noisily.") - -/mob/living/carbon/monkey/diona/verb/evolve() - - set category = "Diona" - set name = "Evolve" - set desc = "Grow to a more complex form." - - if(!is_alien_whitelisted(src, "Diona") && config.usealienwhitelist) - src << alert("You are currently not whitelisted to play as a full diona.") - return 0 - - if(donors.len < 5) - src << "You are not yet ready for your growth..." - return - - if(nutrition < 400) - src << "You have not yet consumed enough to grow..." - return - - src.split() - src.visible_message("\red [src] begins to shift and quiver, and erupts in a shower of shed bark as it splits into a tangle of nearly a dozen new dionaea.","\red You begin to shift and quiver, feeling your awareness splinter. All at once, we consume our stored nutrients to surge with growth, splitting into a tangle of at least a dozen new dionaea. We have attained our gestalt form.") - - var/mob/living/carbon/human/adult = new(get_turf(src.loc)) - adult.set_species("Diona") - - if(istype(loc,/obj/item/weapon/holder/diona)) - var/obj/item/weapon/holder/diona/L = loc - src.loc = L.loc - del(L) - - for(var/datum/language/L in languages) - adult.add_language(L.name) - adult.regenerate_icons() - - adult.name = "diona ([rand(100,999)])" - adult.real_name = adult.name - adult.ckey = src.ckey - - for (var/obj/item/W in src.contents) - src.drop_from_inventory(W) - del(src) - -/mob/living/carbon/monkey/diona/verb/steal_blood() - set category = "Diona" - set name = "Steal Blood" - set desc = "Take a blood sample from a suitable donor." - - var/list/choices = list() - for(var/mob/living/carbon/human/H in oview(1,src)) - if(src.Adjacent(H)) - choices += H - - var/mob/living/carbon/human/M = input(src,"Who do you wish to take a sample from?") in null|choices - - if(!M || !src) return - - if(M.species.flags & NO_BLOOD) - src << "\red That donor has no blood to take." - return - - if(donors.Find(M.real_name)) - src << "\red That donor offers you nothing new." - return - - src.visible_message("\red [src] flicks out a feeler and neatly steals a sample of [M]'s blood.","\red You flick out a feeler and neatly steal a sample of [M]'s blood.") - donors += M.real_name - for(var/datum/language/L in M.languages) - languages |= L - - spawn(25) - update_progression() - -/mob/living/carbon/monkey/diona/proc/update_progression() - - if(!donors.len) - return - - if(donors.len == 5) - ready_evolve = 1 - src << "\green You feel ready to move on to your next stage of growth." - else if(donors.len == 3) - universal_understand = 1 - src << "\green You feel your awareness expand, and realize you know how to understand the creatures around you." - else - src << "\green The blood seeps into your small form, and you draw out the echoes of memories and personality from it, working them into your budding mind." - - -/mob/living/carbon/monkey/diona/say_understands(var/mob/other,var/datum/language/speaking = null) - - if (istype(other, /mob/living/carbon/human) && !speaking) - if(languages.len >= 2) // They have sucked down some blood. - return 1 - return ..() - -/mob/living/carbon/monkey/diona/say(var/message) - var/verb = "says" - var/message_range = world.view - - if(client) - if(client.prefs.muted & MUTE_IC) - src << "\red You cannot speak in IC (Muted)." - return - - message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) - - if(stat == 2) - return say_dead(message) - - var/datum/language/speaking = null - - if(length(message) >= 2) - var/channel_prefix = copytext(message, 1 ,3) - if(languages.len) - for(var/datum/language/L in languages) - if(lowertext(channel_prefix) == ":[L.key]") - verb = L.speech_verb - speaking = L - break - - if(speaking) - message = trim(copytext(message,3)) - - message = capitalize(trim_left(message)) - - if(!message || stat) - return - - ..(message, speaking, verb, null, null, message_range, null) diff --git a/code/modules/mob/living/carbon/monkey/emote.dm b/code/modules/mob/living/carbon/monkey/emote.dm index d5328183f3..92493b6d38 100644 --- a/code/modules/mob/living/carbon/monkey/emote.dm +++ b/code/modules/mob/living/carbon/monkey/emote.dm @@ -31,11 +31,6 @@ if ("custom") return custom_emote(m_type, message) - if ("chirp") - if(istype(src,/mob/living/carbon/monkey/diona)) - message = "The [src.name] chirps!" - playsound(src.loc, 'sound/misc/nymphchirp.ogg', 50, 0) - m_type = 2 if("sign") if (!src.restrained()) message = text("The monkey signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null)) @@ -119,10 +114,7 @@ message = "The [src.name] lets out a faint chimper as it collapses and stops moving..." m_type = 1 if("help") - var/text = "choke, " - if(istype(src,/mob/living/carbon/monkey/diona)) - text += "chirp, " - text += "collapse, dance, deathgasp, drool, gasp, shiver, gnarl, jump, paw, moan, nod, roar, roll, scratch,\nscretch, shake, sign-#, sit, sulk, sway, tail, twitch, whimper" + text += "choke, collapse, dance, deathgasp, drool, gasp, shiver, gnarl, jump, paw, moan, nod, roar, roll, scratch,\nscretch, shake, sign-#, sit, sulk, sway, tail, twitch, whimper" src << text else src << text("Invalid Emote: []", act) diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index ce68106358..50380a580a 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -23,16 +23,14 @@ environment = loc.return_air() if (stat != DEAD) - if(!istype(src,/mob/living/carbon/monkey/diona)) //still breathing - //First, resolve location and get a breath - if(air_master.current_cycle%4==2) - //Only try to take a breath every 4 seconds, unless suffocating - breathe() - else //Still give containing object the chance to interact - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - + //First, resolve location and get a breath + if(air_master.current_cycle%4==2) + //Only try to take a breath every 4 seconds, unless suffocating + breathe() + else //Still give containing object the chance to interact + if(istype(loc, /obj/)) + var/obj/location_as_object = loc + location_as_object.handle_internal_lifeform(src, 0) //Updates the number of stored chemicals for powers handle_changeling() @@ -122,15 +120,6 @@ if (radiation) - if(istype(src,/mob/living/carbon/monkey/diona)) //Filthy check. Dionaea don't take rad damage. - var/rads = radiation/25 - radiation -= rads - nutrition += rads - heal_overall_damage(rads,rads) - adjustOxyLoss(-(rads)) - adjustToxLoss(-(rads)) - return - if (radiation > 100) radiation = 100 Weaken(10) @@ -439,27 +428,8 @@ proc/handle_chemicals_in_body() - if(alien) //Diona nymphs are the only alien monkey currently. - var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing - if(isturf(loc)) //else, there's considered to be no light - var/turf/T = loc - var/area/A = T.loc - if(A) - if(A.lighting_use_dynamic) light_amount = min(10,T.lighting_lumcount) - 5 //hardcapped so it's not abused by having a ton of flashlights - else light_amount = 5 - - nutrition += light_amount - traumatic_shock -= light_amount - - if(nutrition > 500) - nutrition = 500 - if(light_amount > 2) //if there's enough light, heal - adjustBruteLoss(-1) - adjustToxLoss(-1) - adjustOxyLoss(-1) - if(reagents && reagents.reagent_list.len) - reagents.metabolize(src,alien) + reagents.metabolize(src) if (drowsyness) drowsyness-- @@ -485,7 +455,7 @@ silent = 0 else //ALIVE. LIGHTS ARE ON updatehealth() - if(health < config.health_threshold_dead || brain_op_stage == 4.0) + if(health < config.health_threshold_dead || !has_brain()) death() blinded = 1 stat = DEAD diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index 7bb9af2a15..a38ba9c695 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -14,7 +14,6 @@ //var/uni_append = "12C4E2" // Small appearance modifier for different species. var/list/uni_append = list(0x12C,0x4E2) // Same as above for DNA2. var/update_muts = 1 // Monkey gene must be set at start. - var/alien = 0 //Used for reagent metabolism. /mob/living/carbon/monkey/tajara name = "farwa" @@ -98,15 +97,6 @@ greaterform = "Tajaran" add_language("Siik'tajr") -/mob/living/carbon/monkey/diona/New() - - ..() - alien = 1 - gender = NEUTER - dna.mutantrace = "plant" - greaterform = "Diona" - add_language("Rootspeak") - /mob/living/carbon/monkey/movement_delay() var/tally = 0 if(reagents) @@ -121,42 +111,6 @@ tally += (283.222 - bodytemperature) / 10 * 1.75 return tally+config.monkey_delay -/mob/living/carbon/monkey/Bump(atom/movable/AM as mob|obj, yes) - - spawn( 0 ) - if ((!( yes ) || now_pushing)) - return - now_pushing = 1 - if(ismob(AM)) - var/mob/tmob = AM - if(istype(tmob, /mob/living/carbon/human) && (HULK in tmob.mutations)) - if(prob(70)) - usr << "\red You fail to push [tmob]'s fat ass out of the way." - now_pushing = 0 - return - if(!(tmob.status_flags & CANPUSH)) - now_pushing = 0 - return - - tmob.LAssailant = src - now_pushing = 0 - ..() - if (!( istype(AM, /atom/movable) )) - return - if (!( now_pushing )) - now_pushing = 1 - if (!( AM.anchored )) - var/t = get_dir(src, AM) - if (istype(AM, /obj/structure/window)) - if(AM:ini_dir == NORTHWEST || AM:ini_dir == NORTHEAST || AM:ini_dir == SOUTHWEST || AM:ini_dir == SOUTHEAST) - for(var/obj/structure/window/win in get_step(AM,t)) - now_pushing = 0 - return - step(AM, t) - now_pushing = null - return - return - /mob/living/carbon/monkey/Topic(href, href_list) ..() if (href_list["mach_close"]) @@ -301,78 +255,7 @@ O.show_message(text("\red [] has disarmed [name]!", M), 1) return -/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - if (!ticker) - M << "You cannot attack people before the game has started." - return - - if (istype(loc, /turf) && istype(loc.loc, /area/start)) - M << "No attacking people at spawn, you jackass." - return - - switch(M.a_intent) - if ("help") - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M] caresses [src] with its scythe like arm."), 1) - - if ("hurt") - if ((prob(95) && health > 0)) - playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) - var/damage = rand(15, 30) - if (damage >= 25) - damage = rand(20, 40) - if (paralysis < 15) - Paralyse(rand(10, 15)) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has wounded [name]!", M), 1) - else - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has slashed [name]!", M), 1) - adjustBruteLoss(damage) - updatehealth() - else - playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has attempted to lunge at [name]!", M), 1) - - if ("grab") - if (M == src) - return - var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, M, src ) - - M.put_in_active_hand(G) - - grabbed_by += G - G.synch() - - LAssailant = M - - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - O.show_message(text("\red [] has grabbed [name] passively!", M), 1) - - if ("disarm") - playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) - var/damage = 5 - if(prob(95)) - Weaken(15) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has tackled down [name]!", M), 1) - else - drop_item() - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has disarmed [name]!", M), 1) - adjustBruteLoss(damage) - updatehealth() - return - -/mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M as mob) +/mob/living/carbon/monkey/attack_animal(mob/living/M as mob) if(M.melee_damage_upper == 0) M.emote("[M.friendly] [src]") else diff --git a/code/modules/mob/living/carbon/monkey/powers.dm b/code/modules/mob/living/carbon/monkey/powers.dm deleted file mode 100644 index e7c6937cda..0000000000 --- a/code/modules/mob/living/carbon/monkey/powers.dm +++ /dev/null @@ -1,5 +0,0 @@ -/mob/living/carbon/monkey/verb/ventcrawl() - set name = "Crawl through Vent" - set desc = "Enter an air vent and crawl through the pipe system." - set category = "Monkey" - handle_ventcrawl() diff --git a/code/modules/mob/living/carbon/species.dm b/code/modules/mob/living/carbon/species.dm deleted file mode 100644 index 286bffb3a0..0000000000 --- a/code/modules/mob/living/carbon/species.dm +++ /dev/null @@ -1,359 +0,0 @@ -/* - Datum-based species. Should make for much cleaner and easier to maintain mutantrace code. -*/ - -/datum/species - var/name // Species name. - - var/icobase = 'icons/mob/human_races/r_human.dmi' // Normal icon set. - var/deform = 'icons/mob/human_races/r_def_human.dmi' // Mutated icon set. - var/eyes = "eyes_s" // Icon for eyes. - - var/primitive // Lesser form, if any (ie. monkey for humans) - var/tail // Name of tail image in species effects icon file. - var/language // Default racial language, if any. - var/unarmed //For empty hand harm-intent attack - var/unarmed_type = /datum/unarmed_attack - var/secondary_langs = list() // The names of secondary languages that are available to this species. - var/mutantrace // Safeguard due to old code. - - var/breath_type = "oxygen" // Non-oxygen gas breathed, if any. - var/poison_type = "phoron" // Poisonous air. - var/exhale_type = "carbon_dioxide" // Exhaled gas type. - - var/cold_level_1 = 260 // Cold damage level 1 below this point. - var/cold_level_2 = 200 // Cold damage level 2 below this point. - var/cold_level_3 = 120 // Cold damage level 3 below this point. - - var/heat_level_1 = 360 // Heat damage level 1 above this point. - var/heat_level_2 = 400 // Heat damage level 2 above this point. - var/heat_level_3 = 1000 // Heat damage level 2 above this point. - - var/body_temperature = 310.15 //non-IS_SYNTHETIC species will try to stabilize at this temperature. (also affects temperature processing) - var/synth_temp_gain = 0 //IS_SYNTHETIC species will gain this much temperature every second - var/reagent_tag //Used for metabolizing reagents. - - var/darksight = 2 - var/hazard_high_pressure = HAZARD_HIGH_PRESSURE // Dangerously high pressure. - var/warning_high_pressure = WARNING_HIGH_PRESSURE // High pressure warning. - var/warning_low_pressure = WARNING_LOW_PRESSURE // Low pressure warning. - var/hazard_low_pressure = HAZARD_LOW_PRESSURE // Dangerously low pressure. - - var/brute_mod = null // Physical damage reduction/malus. - var/burn_mod = null // Burn damage reduction/malus. - - var/flags = 0 // Various specific features. - - var/list/abilities = list() // For species-derived or admin-given powers - - var/blood_color = "#A10808" //Red. - var/flesh_color = "#FFC896" //Pink. - var/base_color //Used when setting species. - - //Used in icon caching. - var/race_key = 0 - var/icon/icon_template - -/datum/species/New() - unarmed = new unarmed_type() - -/datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs. - //This is a basic humanoid limb setup. - H.organs = list() - H.organs_by_name["chest"] = new/datum/organ/external/chest() - H.organs_by_name["groin"] = new/datum/organ/external/groin(H.organs_by_name["chest"]) - H.organs_by_name["head"] = new/datum/organ/external/head(H.organs_by_name["chest"]) - H.organs_by_name["l_arm"] = new/datum/organ/external/l_arm(H.organs_by_name["chest"]) - H.organs_by_name["r_arm"] = new/datum/organ/external/r_arm(H.organs_by_name["chest"]) - H.organs_by_name["r_leg"] = new/datum/organ/external/r_leg(H.organs_by_name["groin"]) - H.organs_by_name["l_leg"] = new/datum/organ/external/l_leg(H.organs_by_name["groin"]) - H.organs_by_name["l_hand"] = new/datum/organ/external/l_hand(H.organs_by_name["l_arm"]) - H.organs_by_name["r_hand"] = new/datum/organ/external/r_hand(H.organs_by_name["r_arm"]) - H.organs_by_name["l_foot"] = new/datum/organ/external/l_foot(H.organs_by_name["l_leg"]) - H.organs_by_name["r_foot"] = new/datum/organ/external/r_foot(H.organs_by_name["r_leg"]) - - H.internal_organs = list() - H.internal_organs_by_name["heart"] = new/datum/organ/internal/heart(H) - H.internal_organs_by_name["lungs"] = new/datum/organ/internal/lungs(H) - H.internal_organs_by_name["liver"] = new/datum/organ/internal/liver(H) - H.internal_organs_by_name["kidney"] = new/datum/organ/internal/kidney(H) - H.internal_organs_by_name["brain"] = new/datum/organ/internal/brain(H) - H.internal_organs_by_name["eyes"] = new/datum/organ/internal/eyes(H) - - for(var/name in H.organs_by_name) - H.organs += H.organs_by_name[name] - - for(var/datum/organ/external/O in H.organs) - O.owner = H - - if(flags & IS_SYNTHETIC) - for(var/datum/organ/external/E in H.organs) - if(E.status & ORGAN_CUT_AWAY || E.status & ORGAN_DESTROYED) continue - E.status |= ORGAN_ROBOT - for(var/datum/organ/internal/I in H.internal_organs) - I.mechanize() - -/datum/species/proc/handle_post_spawn(var/mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment. - return - -/datum/species/proc/handle_death(var/mob/living/carbon/human/H) //Handles any species-specific death events (such as dionaea nymph spawns). - if(flags & IS_SYNTHETIC) - //H.make_jittery(200) //S-s-s-s-sytem f-f-ai-i-i-i-i-lure-ure-ure-ure - H.h_style = "" - spawn(100) - //H.is_jittery = 0 - //H.jitteriness = 0 - H.update_hair() - return - -/datum/species/human - name = "Human" - language = "Sol Common" - primitive = /mob/living/carbon/monkey - unarmed_type = /datum/unarmed_attack/punch - - flags = HAS_SKIN_TONE | HAS_LIPS | HAS_UNDERWEAR - - //If you wanted to add a species-level ability: - /*abilities = list(/client/proc/test_ability)*/ - -/datum/species/unathi - name = "Unathi" - icobase = 'icons/mob/human_races/r_lizard.dmi' - deform = 'icons/mob/human_races/r_def_lizard.dmi' - language = "Sinta'unathi" - tail = "sogtail" - unarmed_type = /datum/unarmed_attack/claws - primitive = /mob/living/carbon/monkey/unathi - darksight = 3 - - cold_level_1 = 280 //Default 260 - Lower is better - cold_level_2 = 220 //Default 200 - cold_level_3 = 130 //Default 120 - - heat_level_1 = 420 //Default 360 - Higher is better - heat_level_2 = 480 //Default 400 - heat_level_3 = 1100 //Default 1000 - - flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL | HAS_SKIN_COLOR - - flesh_color = "#34AF10" - - reagent_tag = IS_UNATHI - base_color = "#066000" - -/datum/species/tajaran - name = "Tajaran" - icobase = 'icons/mob/human_races/r_tajaran.dmi' - deform = 'icons/mob/human_races/r_def_tajaran.dmi' - language = "Siik'tajr" - tail = "tajtail" - unarmed_type = /datum/unarmed_attack/claws - darksight = 8 - - cold_level_1 = 200 //Default 260 - cold_level_2 = 140 //Default 200 - cold_level_3 = 80 //Default 120 - - heat_level_1 = 330 //Default 360 - heat_level_2 = 380 //Default 400 - heat_level_3 = 800 //Default 1000 - - primitive = /mob/living/carbon/monkey/tajara - - flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL | HAS_SKIN_COLOR - - flesh_color = "#AFA59E" - base_color = "#333333" - -/datum/species/skrell - name = "Skrell" - icobase = 'icons/mob/human_races/r_skrell.dmi' - deform = 'icons/mob/human_races/r_def_skrell.dmi' - language = "Skrellian" - primitive = /mob/living/carbon/monkey/skrell - unarmed_type = /datum/unarmed_attack/punch - - flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR - - flesh_color = "#8CD7A3" - - reagent_tag = IS_SKRELL - -/datum/species/vox - name = "Vox" - icobase = 'icons/mob/human_races/r_vox.dmi' - deform = 'icons/mob/human_races/r_def_vox.dmi' - language = "Vox-pidgin" - unarmed_type = /datum/unarmed_attack/claws //I dont think it will hurt to give vox claws too. - - warning_low_pressure = 50 - hazard_low_pressure = 0 - - cold_level_1 = 80 - cold_level_2 = 50 - cold_level_3 = 0 - - eyes = "vox_eyes_s" - - breath_type = "nitrogen" - poison_type = "oxygen" - - flags = NO_SCAN - - blood_color = "#2299FC" - flesh_color = "#808D11" - - reagent_tag = IS_VOX - -/datum/species/vox/handle_post_spawn(var/mob/living/carbon/human/H) - - H.verbs += /mob/living/carbon/human/proc/leap - ..() - -/datum/species/vox/armalis/handle_post_spawn(var/mob/living/carbon/human/H) - - H.verbs += /mob/living/carbon/human/proc/gut - H.verbs += /mob/living/carbon/human/proc/commune - ..() - -/datum/species/vox/armalis - name = "Vox Armalis" - icobase = 'icons/mob/human_races/r_armalis.dmi' - deform = 'icons/mob/human_races/r_armalis.dmi' - language = "Vox-pidgin" - unarmed_type = /datum/unarmed_attack/claws/armalis - - warning_low_pressure = 50 - hazard_low_pressure = 0 - - cold_level_1 = 80 - cold_level_2 = 50 - cold_level_3 = 0 - - heat_level_1 = 2000 - heat_level_2 = 3000 - heat_level_3 = 4000 - - brute_mod = 0.2 - burn_mod = 0.2 - - eyes = "blank_eyes" - breath_type = "nitrogen" - poison_type = "oxygen" - - flags = NO_SCAN | NO_BLOOD | HAS_TAIL | NO_PAIN - - blood_color = "#2299FC" - flesh_color = "#808D11" - - tail = "armalis_tail" - icon_template = 'icons/mob/human_races/r_armalis.dmi' - - reagent_tag = IS_VOX - -/datum/species/diona - name = "Diona" - icobase = 'icons/mob/human_races/r_diona.dmi' - deform = 'icons/mob/human_races/r_def_plant.dmi' - language = "Rootspeak" - unarmed_type = /datum/unarmed_attack/diona - primitive = /mob/living/carbon/monkey/diona - - warning_low_pressure = 50 - hazard_low_pressure = -1 - - cold_level_1 = 50 - cold_level_2 = -1 - cold_level_3 = -1 - - heat_level_1 = 2000 - heat_level_2 = 3000 - heat_level_3 = 4000 - - body_temperature = T0C + 15 //make the plant people have a bit lower body temperature, why not - - flags = IS_WHITELISTED | NO_BREATHE | REQUIRE_LIGHT | NO_SCAN | IS_PLANT | RAD_ABSORB | NO_BLOOD | IS_SLOW | NO_PAIN - - blood_color = "#004400" - flesh_color = "#907E4A" - - reagent_tag = IS_DIONA - -/datum/species/diona/handle_post_spawn(var/mob/living/carbon/human/H) - H.gender = NEUTER - - return ..() - -/datum/species/diona/handle_death(var/mob/living/carbon/human/H) - - var/mob/living/carbon/monkey/diona/S = new(get_turf(H)) - - if(H.mind) - H.mind.transfer_to(S) - - for(var/mob/living/carbon/monkey/diona/D in H.contents) - if(D.client) - D.loc = H.loc - else - del(D) - - H.visible_message("\red[H] splits apart with a wet slithering noise!") - -/datum/species/machine - name = "Machine" - icobase = 'icons/mob/human_races/r_machine.dmi' - deform = 'icons/mob/human_races/r_machine.dmi' - language = "Tradeband" - unarmed_type = /datum/unarmed_attack/punch - - eyes = "blank_eyes" - brute_mod = 0.5 - burn_mod = 1 - - warning_low_pressure = 50 - hazard_low_pressure = 0 - - cold_level_1 = 50 - cold_level_2 = -1 - cold_level_3 = -1 - - heat_level_1 = 500 //gives them about 25 seconds in space before taking damage - heat_level_2 = 1000 - heat_level_3 = 2000 - - synth_temp_gain = 10 //this should cause IPCs to stabilize at ~80 C in a 20 C environment. - - flags = IS_WHITELISTED | NO_BREATHE | NO_SCAN | NO_BLOOD | NO_PAIN | IS_SYNTHETIC - - blood_color = "#1F181F" - flesh_color = "#575757" - -//Species unarmed attacks - -/datum/unarmed_attack - var/attack_verb = list("attack") // Empty hand hurt intent verb. - var/damage = 0 // Extra empty hand attack damage. - var/attack_sound = "punch" - var/miss_sound = 'sound/weapons/punchmiss.ogg' - var/sharp = 0 - var/edge = 0 - -/datum/unarmed_attack/punch - attack_verb = list("punch") - -/datum/unarmed_attack/diona - attack_verb = list("lash", "bludgeon") - damage = 5 - -/datum/unarmed_attack/claws - attack_verb = list("scratch", "claw") - attack_sound = 'sound/weapons/slice.ogg' - miss_sound = 'sound/weapons/slashmiss.ogg' - damage = 5 - sharp = 1 - edge = 1 - -/datum/unarmed_attack/claws/armalis - attack_verb = list("slash", "claw") - damage = 10 //they're huge! they should do a little more damage, i'd even go for 15-20 maybe... diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index daf0e37004..5c5805bfaf 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1,4 +1,3 @@ - /mob/living/verb/succumb() set hidden = 1 if ((src.health < 0 && src.health > -95.0)) @@ -611,7 +610,16 @@ if(CM.handcuffed && CM.canmove && (CM.last_special <= world.time)) CM.next_move = world.time + 100 CM.last_special = world.time + 100 - if(isalienadult(CM) || (HULK in usr.mutations))//Don't want to do a lot of logic gating here. + + var/can_break_cuffs + if(HULK in usr.mutations) + can_break_cuffs = 1 + else if(istype(CM,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = CM + if(H.species.can_shred(H)) + can_break_cuffs = 1 + + if(can_break_cuffs) //Don't want to do a lot of logic gating here. usr << "\red You attempt to break your handcuffs. (This will take around 5 seconds and you need to stand still)" for(var/mob/O in viewers(CM)) O.show_message(text("\red [] is trying to break the handcuffs!", CM), 1) @@ -648,7 +656,16 @@ else if(CM.legcuffed && CM.canmove && (CM.last_special <= world.time)) CM.next_move = world.time + 100 CM.last_special = world.time + 100 - if(isalienadult(CM) || (HULK in usr.mutations))//Don't want to do a lot of logic gating here. + + var/can_break_cuffs + if(HULK in usr.mutations) + can_break_cuffs = 1 + else if(istype(CM,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = CM + if(H.species.can_shred(H)) + can_break_cuffs = 1 + + if(can_break_cuffs) //Don't want to do a lot of logic gating here. usr << "\red You attempt to break your legcuffs. (This will take around 5 seconds and you need to stand still)" for(var/mob/O in viewers(CM)) O.show_message(text("\red [] is trying to break the legcuffs!", CM), 1) @@ -699,6 +716,11 @@ src << "You can't vent crawl while you're stunned!" return + var/special_fail_msg = can_use_vents() + if(special_fail_msg) + src << "\red [special_fail_msg]" + return + if(vent_found) // one was passed in, probably from vent/AltClick() if(vent_found.welded) src << "That vent is welded shut." @@ -784,3 +806,12 @@ var/area/new_area = get_area(loc) if(new_area) new_area.Entered(src) +/mob/living/proc/can_use_vents() + return "You can't fit into that vent." + + +/mob/living/proc/has_brain() + return 1 + +/mob/living/proc/has_eyes() + return 1 \ No newline at end of file diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 312bccff0f..1ac5faa11f 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -38,3 +38,11 @@ var/tod = null // Time of death var/update_slimes = 1 var/silent = null //Can't talk. Value goes down every life proc. + + // Putting these here for attack_animal(). + var/melee_damage_lower = 0 + var/melee_damage_upper = 0 + var/attacktext = "attacks" + var/attack_sound = null + var/friendly = "nuzzles" + var/wall_smash = 0 \ No newline at end of file diff --git a/code/modules/mob/living/living_powers.dm b/code/modules/mob/living/living_powers.dm new file mode 100644 index 0000000000..d2a8e35320 --- /dev/null +++ b/code/modules/mob/living/living_powers.dm @@ -0,0 +1,18 @@ +/mob/living/proc/ventcrawl() + set name = "Crawl through Vent" + set desc = "Enter an air vent and crawl through the pipe system." + set category = "Abilities" + handle_ventcrawl() + return + +/mob/living/proc/hide() + set name = "Hide" + set desc = "Allows to hide beneath tables or certain items. Toggled on or off." + set category = "Abilities" + + if (layer != TURF_LAYER+0.2) + layer = TURF_LAYER+0.2 + src << text("\blue You are now hiding.") + else + layer = MOB_LAYER + src << text("\blue You have stopped hiding.") \ No newline at end of file diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 95dd82aafe..f778e46209 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -9,12 +9,8 @@ var/list/department_radio_keys = list( ":e" = "Engineering", "#e" = "Engineering", ".e" = "Engineering", ":s" = "Security", "#s" = "Security", ".s" = "Security", ":w" = "whisper", "#w" = "whisper", ".w" = "whisper", - ":b" = "binary", "#b" = "binary", ".b" = "binary", - ":a" = "alientalk", "#a" = "alientalk", ".a" = "alientalk", ":t" = "Syndicate", "#t" = "Syndicate", ".t" = "Syndicate", ":u" = "Supply", "#u" = "Supply", ".u" = "Supply", - ":g" = "changeling", "#g" = "changeling", ".g" = "changeling", - ":d" = "dronechat", "#d" = "dronechat", ".d" = "dronechat", ":R" = "right ear", "#R" = "right ear", ".R" = "right ear", ":L" = "left ear", "#L" = "left ear", ".L" = "left ear", @@ -26,12 +22,8 @@ var/list/department_radio_keys = list( ":E" = "Engineering", "#E" = "Engineering", ".E" = "Engineering", ":S" = "Security", "#S" = "Security", ".S" = "Security", ":W" = "whisper", "#W" = "whisper", ".W" = "whisper", - ":B" = "binary", "#B" = "binary", ".B" = "binary", - ":A" = "alientalk", "#A" = "alientalk", ".A" = "alientalk", ":T" = "Syndicate", "#T" = "Syndicate", ".T" = "Syndicate", ":U" = "Supply", "#U" = "Supply", ".U" = "Supply", - ":G" = "changeling", "#G" = "changeling", ".G" = "changeling", - ":D" = "dronechat", "#D" = "dronechat", ".D" = "dronechat", //kinda localization -- rastaf0 //same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding. @@ -45,33 +37,18 @@ var/list/department_radio_keys = list( ":ó" = "Engineering", "#ó" = "Engineering", ".ó" = "Engineering", ":û" = "Security", "#û" = "Security", ".û" = "Security", ":ö" = "whisper", "#ö" = "whisper", ".ö" = "whisper", - ":è" = "binary", "#è" = "binary", ".è" = "binary", - ":ô" = "alientalk", "#ô" = "alientalk", ".ô" = "alientalk", ":å" = "Syndicate", "#å" = "Syndicate", ".å" = "Syndicate", ":é" = "Supply", "#é" = "Supply", ".é" = "Supply", - ":ï" = "changeling", "#ï" = "changeling", ".ï" = "changeling" ) /mob/living/proc/binarycheck() + if (istype(src, /mob/living/silicon/pai)) return - if (issilicon(src)) - return 1 + if (!ishuman(src)) return - var/mob/living/carbon/human/H = src - if (H.l_ear || H.r_ear) - var/obj/item/device/radio/headset/dongle - if(istype(H.l_ear,/obj/item/device/radio/headset)) - dongle = H.l_ear - else - dongle = H.r_ear - if(!istype(dongle)) return - if(dongle.translate_binary) return 1 -/mob/living/proc/hivecheck() - if (isalien(src)) return 1 - if (!ishuman(src)) return var/mob/living/carbon/human/H = src if (H.l_ear || H.r_ear) var/obj/item/device/radio/headset/dongle diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 1fd5dff535..c84c5b4355 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -511,41 +511,7 @@ var/list/ai_verbs_default = list( updatehealth() return 2 -/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - if (!ticker) - M << "You cannot attack people before the game has started." - return - - if (istype(loc, /turf) && istype(loc.loc, /area/start)) - M << "No attacking people at spawn, you jackass." - return - - switch(M.a_intent) - - if ("help") - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M] caresses [src]'s plating with its scythe like arm."), 1) - - else //harm - var/damage = rand(10, 20) - if (prob(90)) - playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has slashed at []!", M, src), 1) - if(prob(8)) - flick("noise", flash) - adjustBruteLoss(damage) - updatehealth() - else - playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] took a swipe at []!", M, src), 1) - return - -/mob/living/silicon/ai/attack_animal(mob/living/simple_animal/M as mob) +/mob/living/silicon/ai/attack_animal(mob/living/M as mob) if(M.melee_damage_upper == 0) M.emote("[M.friendly] [src]") else diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 6015ab1302..6c6904e310 100755 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -3,7 +3,6 @@ icon = 'icons/mob/pai.dmi' icon_state = "repairbot" - robot_talk_understand = 0 emote_type = 2 // pAIs emotes are heard, not seen, so they can be seen through a container (eg. person) small = 1 pass_flags = 1 @@ -204,40 +203,6 @@ //mob/living/silicon/pai/bullet_act(var/obj/item/projectile/Proj) -/mob/living/silicon/pai/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - if (!ticker) - M << "You cannot attack people before the game has started." - return - - if (istype(src.loc, /turf) && istype(src.loc.loc, /area/start)) - M << "You cannot attack someone in the spawn area." - return - - switch(M.a_intent) - - if ("help") - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M] caresses [src]'s casing with its scythe like arm."), 1) - - else //harm - var/damage = rand(10, 20) - if (prob(90)) - playsound(src.loc, 'sound/weapons/slash.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has slashed at []!", M, src), 1) - if(prob(8)) - flick("noise", src.flash) - src.adjustBruteLoss(damage) - src.updatehealth() - else - playsound(src.loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] took a swipe at []!", M, src), 1) - return - ///mob/living/silicon/pai/attack_hand(mob/living/carbon/M as mob) /mob/living/silicon/pai/proc/switchCamera(var/obj/machinery/camera/C) @@ -470,4 +435,8 @@ pose = addtext(pose,".") //Makes sure all emotes end with a period. msg += "\nIt is [pose]" - usr << msg \ No newline at end of file + usr << msg + +// No binary for pAIs. +/mob/living/silicon/pai/binarycheck() + return 0 \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm index be9a36c819..cdca3b18ef 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone.dm @@ -13,6 +13,8 @@ lawupdate = 0 density = 1 req_access = list(access_engine, access_robotics) + integrated_light_power = 2 + local_transmit = 1 // We need to keep track of a few module items so we don't need to do list operations // every time we need them. These get set in New() after the module is chosen. @@ -30,6 +32,13 @@ ..() + verbs += /mob/living/proc/ventcrawl + verbs += /mob/living/proc/hide + + remove_language("Robot Talk") + add_language("Robot Talk", 0) + add_language("Drone Talk", 1) + if(camera && "Robots" in camera.network) camera.network.Add("Engineering") @@ -87,57 +96,6 @@ /mob/living/silicon/robot/drone/pick_module() return -//Drones can only use binary and say emotes. NOTHING else. -//TBD, fix up boilerplate. ~ Z -/mob/living/silicon/robot/drone/say(var/message) - - if (!message) - return - - if (src.client) - if(client.prefs.muted & MUTE_IC) - src << "You cannot send IC messages (muted)." - return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return - - message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) - - if (stat == 2) - return say_dead(message) - - if(copytext(message,1,2) == "*") - return emote(copytext(message,2)) - else if(length(message) >= 2) - - if(parse_message_mode(message, "NONE") == "dronechat") - - if(!is_component_functioning("radio")) - src << "\red Your radio transmitter isn't functional." - return - - for (var/mob/living/S in living_mob_list) - if(istype(S, /mob/living/silicon/robot/drone)) - S << "Drone Talk, [name] transmits, \"[trim(copytext(message,3))]\"" - - for (var/mob/M in dead_mob_list) - if(!istype(M,/mob/new_player) && !istype(M,/mob/living/carbon/brain)) - M << "Drone Talk, [name] transmits, \"[trim(copytext(message,3))]\"" - - else - - var/list/listeners = hearers(5,src) - listeners |= src - - for(var/mob/living/silicon/robot/drone/D in listeners) - if(D.client) D << "[src] transmits, \"[message]\"" - - for (var/mob/M in player_list) - if (istype(M, /mob/new_player)) - continue - else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS) - if(M.client) M << "[src] transmits, \"[message]\"" - //Drones cannot be upgraded with borg modules so we need to catch some items before they get used in ..(). /mob/living/silicon/robot/drone/attackby(obj/item/weapon/W as obj, mob/user as mob) diff --git a/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm b/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm index 2c45af24d1..bac16de92e 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm @@ -21,28 +21,6 @@ return -/mob/living/silicon/robot/drone/verb/hide() - set name = "Hide" - set desc = "Allows you to hide beneath tables or certain items. Toggled on or off." - set category = "Drone" - - if (layer != TURF_LAYER+0.2) - layer = TURF_LAYER+0.2 - src << text("\blue You are now hiding.") - else - layer = MOB_LAYER - src << text("\blue You have stopped hiding.") - -/mob/living/silicon/robot/drone/verb/light() - set name = "Light On/Off" - set desc = "Activate a low power omnidirectional LED. Toggled on or off." - set category = "Drone" - - if(luminosity) - SetLuminosity(0) - return - SetLuminosity(2) - //Actual picking-up event. /mob/living/silicon/robot/drone/attack_hand(mob/living/carbon/human/M as mob) diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm index 94a9e138e9..50806f0da2 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm @@ -80,14 +80,14 @@ wrapped = thing break - if(wrapped) //Already have an item. - + if(wrapped) //Already have an item. + //Temporary put wrapped into user so target's attackby() checks pass. wrapped.loc = user - + //Pass the attack on to the target. This might delete/relocate wrapped. target.attackby(wrapped,user) - + //If wrapped did neither get deleted nor put into target, put it back into the gripper. if(wrapped && user && (wrapped.loc == user)) wrapped.loc = src diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index a39f27022c..667aeb186d 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -19,6 +19,7 @@ var/list/robot_verbs_default = list( var/custom_sprite = 0 //Due to all the sprites involved, a var for our custom borgs may be best var/crisis //Admin-settable for combat module use. var/crisis_override = 0 + var/integrated_light_power = 5 //Hud stuff @@ -79,6 +80,8 @@ var/list/robot_verbs_default = list( spark_system.set_up(5, 0, src) spark_system.attach(src) + add_language("Robot Talk", 1) + ident = rand(1, 999) updatename("Default") updateicon() @@ -846,72 +849,6 @@ var/list/robot_verbs_default = list( spark_system.start() return ..() -/mob/living/silicon/robot/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - if (!ticker) - M << "You cannot attack people before the game has started." - return - - if (istype(loc, /turf) && istype(loc.loc, /area/start)) - M << "No attacking people at spawn, you jackass." - return - - switch(M.a_intent) - - if ("help") - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M] caresses [src]'s plating with its scythe-like arm."), 1) - - if ("grab") - if (M == src) - return - var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, M, src ) - - M.put_in_active_hand(G) - - grabbed_by += G - G.synch() - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) - - if ("hurt") - var/damage = rand(10, 20) - if (prob(90)) - - playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - O.show_message(text("\red [] has slashed at []!", M, src), 1) - if(prob(8)) - flick("noise", flash) - adjustBruteLoss(damage) - updatehealth() - else - playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] took a swipe at []!", M, src), 1) - - if ("disarm") - if(!(lying)) - if (rand(1,100) <= 85) - Stun(7) - step(src,get_dir(M,src)) - spawn(5) step(src,get_dir(M,src)) - playsound(loc, 'sound/weapons/pierce.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has forced back []!", M, src), 1) - else - playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] attempted to force back []!", M, src), 1) - return - - - /mob/living/silicon/robot/attack_slime(mob/living/carbon/slime/M as mob) if (!ticker) M << "You cannot attack people before the game has started." @@ -970,7 +907,7 @@ var/list/robot_verbs_default = list( return -/mob/living/silicon/robot/attack_animal(mob/living/simple_animal/M as mob) +/mob/living/silicon/robot/attack_animal(mob/living/M as mob) if(M.melee_damage_upper == 0) M.emote("[M.friendly] [src]") else @@ -1337,7 +1274,6 @@ var/list/robot_verbs_default = list( /mob/living/silicon/robot/proc/remove_robot_verbs() src.verbs -= robot_verbs_default - // Uses power from cyborg's cell. Returns 1 on success or 0 on failure. // Properly converts using CELLRATE now! Amount is in Joules. /mob/living/silicon/robot/proc/cell_use_power(var/amount = 0) @@ -1352,4 +1288,11 @@ var/list/robot_verbs_default = list( if(cell.use(amount * CELLRATE * CYBORG_POWER_USAGE_MULTIPLIER)) used_power_this_tick += amount * CYBORG_POWER_USAGE_MULTIPLIER return 1 - return 0 + return 0 + +/mob/living/silicon/robot/binarycheck() + if(is_component_functioning("comms")) + var/datum/robot_component/RC = get_component("comms") + use_power(RC.active_usage) + return 1 + return 0 \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/robot_powers.dm b/code/modules/mob/living/silicon/robot/robot_powers.dm new file mode 100644 index 0000000000..f51af52b18 --- /dev/null +++ b/code/modules/mob/living/silicon/robot/robot_powers.dm @@ -0,0 +1,9 @@ +/mob/living/silicon/robot/verb/light() + set name = "Light On/Off" + set desc = "Activate your inbuilt light. Toggled on or off." + set category = "Robot Commands" + + if(luminosity) + SetLuminosity(0) + return + SetLuminosity(integrated_light_power) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index c979eec0dc..7f04c7b3ee 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -54,7 +54,6 @@ var/mob/living/silicon/robot/R = src var/mob/living/silicon/pai/P = src - //Must be concious to speak if (stat) return @@ -69,21 +68,35 @@ else message = trim(copytext(message,3)) - if(message_mode && bot_type == IS_ROBOT && message_mode != "binary" && !R.is_component_functioning("radio")) - src << "\red Your radio isn't functional at this time." - return - if(bot_type == IS_ROBOT && message_mode != "binary") - var/datum/robot_component/radio/RA = R.get_component("radio") - if (!R.cell_use_power(RA.active_usage)) - usr << "\red Not enough power to transmit message." - return - //parse language key and consume it var/datum/language/speaking = parse_language(message) if (speaking) verb = speaking.speech_verb message = copytext(message,3) + if(speaking.flags & HIVEMIND) + speaking.broadcast(src,trim(message)) + return + + // Currently used by drones. + if(local_transmit) + var/list/listeners = hearers(5,src) + listeners |= src + + for(var/mob/living/silicon/D in listeners) + if(D.client && istype(D,src.type)) + D << "[src] transmits, \"[message]\"" + + for (var/mob/M in player_list) + if (istype(M, /mob/new_player)) + continue + else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS) + if(M.client) M << "[src] transmits, \"[message]\"" + return + + if(message_mode && bot_type == IS_ROBOT && !R.is_component_functioning("radio")) + src << "\red Your radio isn't functional at this time." + return switch(message_mode) if("department") @@ -98,21 +111,6 @@ P.radio.talk_into(src,message,message_mode,verb,speaking) return 1 - if("binary") - switch(bot_type) - if(IS_ROBOT) - if(!R.is_component_functioning("comms")) - src << "\red Your binary communications component isn't functional." - return - var/datum/robot_component/binary_communication/B = R.get_component("comms") - if(!R.cell_use_power(B.active_usage)) - src << "\red Not enough power to transmit message." - return - if(IS_PAI) - src << "You do not appear to have that function" - return - - robot_talk(message) return 1 if("general") switch(bot_type) @@ -185,64 +183,6 @@ return return 1 -/mob/living/proc/robot_talk(var/message) - - log_say("[key_name(src)] : [message]") - - message = trim(message) - - if (!message) - return - - var/verb = say_quote(message) - - - var/rendered = "Robotic Talk, [name] [verb], \"[message]\"" - - for (var/mob/living/S in living_mob_list) - if(S.robot_talk_understand && (S.robot_talk_understand == robot_talk_understand)) // This SHOULD catch everything caught by the one below, but I'm not going to change it. - if(istype(S , /mob/living/silicon/ai)) - var/renderedAI = "Robotic Talk, [name] [verb], \"[message]\"" - S.show_message(renderedAI, 2) - else - var/mob/living/silicon/robot/borg = S - if(istype(borg) && borg.is_component_functioning("comms")) - var/datum/robot_component/RC = borg.get_component("comms") - if(!borg.use_power(RC.active_usage)) - continue // No power. - S.show_message(rendered, 2) - - - else if (S.binarycheck()) - if(istype(S , /mob/living/silicon/ai)) - var/renderedAI = "Robotic Talk, [name] [verb], \"[message]\"" - S.show_message(renderedAI, 2) - else - S.show_message(rendered, 2) - - var/list/listening = hearers(1, src) - listening -= src - - var/list/heard = list() - for (var/mob/M in listening) - if(!istype(M, /mob/living/silicon) && !M.robot_talk_understand) - heard += M - if (length(heard)) - var/message_beep - verb = "beeps" - message_beep = "beep beep beep" - - rendered = "[voice_name] [verb], \"[message_beep]\"" - - for (var/mob/M in heard) - M.show_message(rendered, 2) - - rendered = "Robotic Talk, [name] [verb], \"[message]\"" - - for (var/mob/M in dead_mob_list) - if(!istype(M,/mob/new_player) && !istype(M,/mob/living/carbon/brain)) //No meta-evesdropping - M.show_message(rendered, 2) - #undef IS_AI #undef IS_ROBOT #undef IS_PAI diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 6f0778a056..692609afb8 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -1,6 +1,5 @@ /mob/living/silicon gender = NEUTER - robot_talk_understand = 1 voice_name = "synthesized voice" var/syndicate = 0 var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS @@ -14,6 +13,7 @@ var/speak_query = "queries" var/pose //Yes, now AIs can pose too. var/obj/item/device/camera/siliconcam/aiCamera = null //photography + var/local_transmit //If set, can only speak to others of the same type within a short range. var/sensor_mode = 0 //Determines the current HUD. #define SEC_HUD 1 //Security HUD mode @@ -214,4 +214,7 @@ set desc = "Sets an extended description of your character's features." set category = "IC" - flavor_text = copytext(sanitize(input(usr, "Please enter your new flavour text.", "Flavour text", null) as text), 1) \ No newline at end of file + flavor_text = copytext(sanitize(input(usr, "Please enter your new flavour text.", "Flavour text", null) as text), 1) + +/mob/living/silicon/binarycheck() + return 1 \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/borer.dm b/code/modules/mob/living/simple_animal/borer.dm deleted file mode 100644 index f377a846c6..0000000000 --- a/code/modules/mob/living/simple_animal/borer.dm +++ /dev/null @@ -1,580 +0,0 @@ -/datum/game_mode/var/list/borers = list() - -/mob/living/captive_brain - name = "host brain" - real_name = "host brain" - universal_understand = 1 - -/mob/living/captive_brain/say(var/message) - - if (src.client) - if(client.prefs.muted & MUTE_IC) - src << "\red You cannot speak in IC (muted)." - return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return - - if(istype(src.loc,/mob/living/simple_animal/borer)) - - message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) - if (!message) - return - log_say("[key_name(src)] : [message]") - if (stat == 2) - return say_dead(message) - - var/mob/living/simple_animal/borer/B = src.loc - src << "You whisper silently, \"[message]\"" - B.host << "The captive mind of [src] whispers, \"[message]\"" - - for (var/mob/M in player_list) - if (istype(M, /mob/new_player)) - continue - else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS) - M << "The captive mind of [src] whispers, \"[message]\"" - -/mob/living/captive_brain/emote(var/message) - return - -/mob/living/simple_animal/borer - name = "cortical borer" - real_name = "cortical borer" - desc = "A small, quivering sluglike creature." - speak_emote = list("chirrups") - emote_hear = list("chirrups") - response_help = "pokes" - response_disarm = "prods the" - response_harm = "stomps on the" - icon_state = "brainslug" - icon_living = "brainslug" - icon_dead = "brainslug_dead" - speed = 5 - a_intent = "harm" - stop_automated_movement = 1 - status_flags = CANPUSH - attacktext = "nips" - friendly = "prods" - wander = 0 - pass_flags = PASSTABLE - universal_understand = 1 - holder_type = /obj/item/weapon/holder/borer - - var/used_dominate - var/chemicals = 10 // Chemicals used for reproduction and spitting neurotoxin. - var/mob/living/carbon/human/host // Human host for the brain worm. - var/truename // Name used for brainworm-speak. - var/mob/living/captive_brain/host_brain // Used for swapping control of the body back and forth. - var/controlling // Used in human death check. - var/docile = 0 // Sugar can stop borers from acting. - var/has_reproduced - var/roundstart - -/mob/living/simple_animal/borer/roundstart - roundstart = 1 - -/mob/living/simple_animal/borer/Life() - - ..() - - if(host) - - if(!stat && !host.stat) - - if(host.reagents.has_reagent("sugar")) - if(!docile) - if(controlling) - host << "\blue You feel the soporific flow of sugar in your host's blood, lulling you into docility." - else - src << "\blue You feel the soporific flow of sugar in your host's blood, lulling you into docility." - docile = 1 - else - if(docile) - if(controlling) - host << "\blue You shake off your lethargy as the sugar leaves your host's blood." - else - src << "\blue You shake off your lethargy as the sugar leaves your host's blood." - docile = 0 - - if(chemicals < 250) - chemicals++ - if(controlling) - - if(docile) - host << "\blue You are feeling far too docile to continue controlling your host..." - host.release_control() - return - - if(prob(5)) - host.adjustBrainLoss(rand(1,2)) - - if(prob(host.brainloss/20)) - host.say("*[pick(list("blink","blink_r","choke","aflap","drool","twitch","twitch_s","gasp"))]") - -/mob/living/simple_animal/borer/New() - ..() - truename = "[pick("Primary","Secondary","Tertiary","Quaternary")] [rand(1000,9999)]" - if(!roundstart) request_player() - -/mob/living/simple_animal/borer/say(var/message) - - message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) - message = capitalize(message) - - if(!message) - return - - if (stat == 2) - return say_dead(message) - - if (stat) - return - - if (src.client) - if(client.prefs.muted & MUTE_IC) - src << "\red You cannot speak in IC (muted)." - return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return - - if (copytext(message, 1, 2) == "*") - return emote(copytext(message, 2)) - - if (copytext(message, 1, 2) == ";") //Brain borer hivemind. - return borer_speak(message) - - if(!host) - //TODO: have this pick a random mob within 3 tiles to speak for the borer. - src << "You have no host to speak to." - return //No host, no audible speech. - - src << "You drop words into [host]'s mind: \"[message]\"" - host << "Your own thoughts speak: \"[message]\"" - - for (var/mob/M in player_list) - if (istype(M, /mob/new_player)) - continue - else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS) - M << "[src.truename] whispers to [host], \"[message]\"" - -/mob/living/simple_animal/borer/Stat() - ..() - statpanel("Status") - - if(emergency_shuttle) - var/eta_status = emergency_shuttle.get_status_panel_eta() - if(eta_status) - stat(null, eta_status) - - if (client.statpanel == "Status") - stat("Chemicals", chemicals) - -// VERBS! - -/mob/living/simple_animal/borer/proc/borer_speak(var/message) - if(!message) - return - - for(var/mob/M in mob_list) - if(M.mind && (istype(M, /mob/living/simple_animal/borer) || istype(M, /mob/dead/observer))) - M << "Cortical link, [truename]: [copytext(message, 2)]" - -/mob/living/simple_animal/borer/verb/dominate_victim() - set category = "Alien" - set name = "Paralyze Victim" - set desc = "Freeze the limbs of a potential host with supernatural fear." - - if(world.time - used_dominate < 150) - src << "You cannot use that ability again so soon." - return - - if(host) - src << "You cannot do that from within a host body." - return - - if(src.stat) - src << "You cannot do that in your current state." - return - - var/list/choices = list() - for(var/mob/living/carbon/C in view(3,src)) - if(C.stat != 2) - choices += C - - if(world.time - used_dominate < 150) - src << "You cannot use that ability again so soon." - return - - var/mob/living/carbon/M = input(src,"Who do you wish to dominate?") in null|choices - - if(!M || !src) return - - if(M.has_brain_worms()) - src << "You cannot infest someone who is already infested!" - return - - src << "\red You focus your psychic lance on [M] and freeze their limbs with a wave of terrible dread." - M << "\red You feel a creeping, horrible sense of dread come over you, freezing your limbs and setting your heart racing." - M.Weaken(10) - - used_dominate = world.time - -/mob/living/simple_animal/borer/verb/bond_brain() - set category = "Alien" - set name = "Assume Control" - set desc = "Fully connect to the brain of your host." - - if(!host) - src << "You are not inside a host body." - return - - if(src.stat) - src << "You cannot do that in your current state." - return - - if(docile) - src << "\blue You are feeling far too docile to do that." - return - - src << "You begin delicately adjusting your connection to the host brain..." - - spawn(100+(host.brainloss*5)) - - if(!host || !src || controlling) - return - else - src << "\red You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system." - host << "\red You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours." - - // host -> brain - var/h2b_id = host.computer_id - var/h2b_ip= host.lastKnownIP - host.computer_id = null - host.lastKnownIP = null - - del(host_brain) - host_brain = new(src) - - host_brain.ckey = host.ckey - - host_brain.name = host.name - - if(!host_brain.computer_id) - host_brain.computer_id = h2b_id - - if(!host_brain.lastKnownIP) - host_brain.lastKnownIP = h2b_ip - - // self -> host - var/s2h_id = src.computer_id - var/s2h_ip= src.lastKnownIP - src.computer_id = null - src.lastKnownIP = null - - host.ckey = src.ckey - - if(!host.computer_id) - host.computer_id = s2h_id - - if(!host.lastKnownIP) - host.lastKnownIP = s2h_ip - - controlling = 1 - - host.verbs += /mob/living/carbon/proc/release_control - host.verbs += /mob/living/carbon/proc/punish_host - host.verbs += /mob/living/carbon/proc/spawn_larvae - - return - -/mob/living/simple_animal/borer/verb/secrete_chemicals() - set category = "Alien" - set name = "Secrete Chemicals" - set desc = "Push some chemicals into your host's bloodstream." - - if(!host) - src << "You are not inside a host body." - return - - if(stat) - src << "You cannot secrete chemicals in your current state." - - if(docile) - src << "\blue You are feeling far too docile to do that." - return - - if(chemicals < 50) - src << "You don't have enough chemicals!" - - var/chem = input("Select a chemical to secrete.", "Chemicals") in list("bicaridine","tramadol","hyperzine","alkysine") - - if(chemicals < 50 || !host || controlling || !src || stat) //Sanity check. - return - - src << "\red You squirt a measure of [chem] from your reservoirs into [host]'s bloodstream." - host.reagents.add_reagent(chem, 10) - chemicals -= 50 - -/mob/living/simple_animal/borer/verb/release_host() - set category = "Alien" - set name = "Release Host" - set desc = "Slither out of your host." - - if(!host) - src << "You are not inside a host body." - return - - if(stat) - src << "You cannot leave your host in your current state." - - if(docile) - src << "\blue You are feeling far too docile to do that." - return - - if(!host || !src) return - - src << "You begin disconnecting from [host]'s synapses and prodding at their internal ear canal." - - if(!host.stat) - host << "An odd, uncomfortable pressure begins to build inside your skull, behind your ear..." - - spawn(100) - - if(!host || !src) return - - if(src.stat) - src << "You cannot release your host in your current state." - return - - src << "You wiggle out of [host]'s ear and plop to the ground." - if(!host.stat) - host << "Something slimy wiggles out of your ear and plops to the ground!" - - detatch() - leave_host() - -/mob/living/simple_animal/borer/proc/detatch() - - if(!host || !controlling) return - - if(istype(host,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = host - var/datum/organ/external/head = H.get_organ("head") - head.implants -= src - - controlling = 0 - - host.verbs -= /mob/living/carbon/proc/release_control - host.verbs -= /mob/living/carbon/proc/punish_host - host.verbs -= /mob/living/carbon/proc/spawn_larvae - - if(host_brain) - - // these are here so bans and multikey warnings are not triggered on the wrong people when ckey is changed. - // computer_id and IP are not updated magically on their own in offline mobs -walter0o - - // host -> self - var/h2s_id = host.computer_id - var/h2s_ip= host.lastKnownIP - host.computer_id = null - host.lastKnownIP = null - - src.ckey = host.ckey - - if(!src.computer_id) - src.computer_id = h2s_id - - if(!host_brain.lastKnownIP) - src.lastKnownIP = h2s_ip - - // brain -> host - var/b2h_id = host_brain.computer_id - var/b2h_ip= host_brain.lastKnownIP - host_brain.computer_id = null - host_brain.lastKnownIP = null - - host.ckey = host_brain.ckey - - if(!host.computer_id) - host.computer_id = b2h_id - - if(!host.lastKnownIP) - host.lastKnownIP = b2h_ip - - del(host_brain) - -/mob/living/simple_animal/borer/proc/leave_host() - - if(!host) return - - src.loc = get_turf(host) - - reset_view(null) - machine = null - - host.reset_view(null) - host.machine = null - - var/mob/living/H = host - H.status_flags &= ~PASSEMOTES - host = null - return - -/mob/living/simple_animal/borer/verb/infest() - set category = "Alien" - set name = "Infest" - set desc = "Infest a suitable humanoid host." - - if(host) - src << "You are already within a host." - return - - if(stat) - src << "You cannot infest a target in your current state." - return - - var/list/choices = list() - for(var/mob/living/carbon/C in view(1,src)) - if(C.stat != 2 && src.Adjacent(C)) - choices += C - - var/mob/living/carbon/M = input(src,"Who do you wish to infest?") in null|choices - - if(!M || !src) return - - if(!(src.Adjacent(M))) return - - if(M.has_brain_worms()) - src << "You cannot infest someone who is already infested!" - return - - if(istype(M,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - if(H.check_head_coverage()) - src << "You cannot get through that host's protective gear." - return - - M << "Something slimy begins probing at the opening of your ear canal..." - src << "You slither up [M] and begin probing at their ear canal..." - - if(!do_after(src,30)) - src << "As [M] moves away, you are dislodged and fall to the ground." - return - - if(!M || !src) return - - if(src.stat) - src << "You cannot infest a target in your current state." - return - - if(M.stat == 2) - src << "That is not an appropriate target." - return - - if(M in view(1, src)) - src << "You wiggle into [M]'s ear." - if(!M.stat) - M << "Something disgusting and slimy wiggles into your ear!" - - src.host = M - src.loc = M - - if(istype(M,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - var/datum/organ/external/head = H.get_organ("head") - head.implants += src - - host.status_flags |= PASSEMOTES - - return - else - src << "They are no longer in range!" - return - -/mob/living/simple_animal/borer/verb/ventcrawl() - set name = "Crawl through Vent" - set desc = "Enter an air vent and crawl through the pipe system." - set category = "Alien" - -// if(!istype(V,/obj/machinery/atmoalter/siphs/fullairsiphon/air_vent)) -// return - var/obj/machinery/atmospherics/unary/vent_pump/vent_found - var/welded = 0 - for(var/obj/machinery/atmospherics/unary/vent_pump/v in range(1,src)) - if(!v.welded) - vent_found = v - break - else - welded = 1 - if(vent_found) - if(vent_found.network&&vent_found.network.normal_members.len) - var/list/vents = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in vent_found.network.normal_members) - if(temp_vent.loc == loc) - continue - vents.Add(temp_vent) - var/list/choices = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/vent in vents) - if(vent.loc.z != loc.z) - continue - var/atom/a = get_turf(vent) - choices.Add(a.loc) - var/turf/startloc = loc - var/obj/selection = input("Select a destination.", "Duct System") in choices - var/selection_position = choices.Find(selection) - if(loc==startloc) - var/obj/target_vent = vents[selection_position] - if(target_vent) - loc = target_vent.loc - else - src << "\blue You need to remain still while entering a vent." - else - src << "\blue This vent is not connected to anything." - else if(welded) - src << "\red That vent is welded." - else - src << "\blue You must be standing on or beside an air vent to enter it." - return - -//copy paste from alien/larva, if that func is updated please update this one alsoghost -/mob/living/simple_animal/borer/verb/hide() - set name = "Hide" - set desc = "Allows to hide beneath tables or certain items. Toggled on or off." - set category = "Alien" - - if (layer != TURF_LAYER+0.2) - layer = TURF_LAYER+0.2 - src << text("\blue You are now hiding.") - else - layer = MOB_LAYER - src << text("\blue You have stopped hiding.") - -//Procs for grabbing players. -/mob/living/simple_animal/borer/proc/request_player() - for(var/mob/dead/observer/O in player_list) - if(jobban_isbanned(O, "Syndicate")) - continue - if(O.client) - if(O.client.prefs.be_special & BE_ALIEN) - question(O.client) - -/mob/living/simple_animal/borer/proc/question(var/client/C) - spawn(0) - if(!C) return - var/response = alert(C, "A cortical borer needs a player. Are you interested?", "Cortical borer request", "Yes", "No", "Never for this round") - if(!C || ckey) - return - if(response == "Yes") - transfer_personality(C) - else if (response == "Never for this round") - C.prefs.be_special ^= BE_ALIEN - -/mob/living/simple_animal/borer/proc/transfer_personality(var/client/candidate) - - if(!candidate) - return - - src.mind = candidate.mob.mind - src.ckey = candidate.ckey - if(src.mind) - src.mind.assigned_role = "Cortical Borer" - src.mind.special_role = "Cortical Borer" diff --git a/code/modules/mob/living/simple_animal/borer/borer.dm b/code/modules/mob/living/simple_animal/borer/borer.dm new file mode 100644 index 0000000000..2cfdc1f8c4 --- /dev/null +++ b/code/modules/mob/living/simple_animal/borer/borer.dm @@ -0,0 +1,207 @@ +/datum/game_mode/var/list/borers = list() + +/mob/living/simple_animal/borer + name = "cortical borer" + real_name = "cortical borer" + desc = "A small, quivering sluglike creature." + speak_emote = list("chirrups") + emote_hear = list("chirrups") + response_help = "pokes" + response_disarm = "prods the" + response_harm = "stomps on the" + icon_state = "brainslug" + icon_living = "brainslug" + icon_dead = "brainslug_dead" + speed = 5 + a_intent = "harm" + stop_automated_movement = 1 + status_flags = CANPUSH + attacktext = "nips" + friendly = "prods" + wander = 0 + pass_flags = PASSTABLE + universal_understand = 1 + holder_type = /obj/item/weapon/holder/borer + + var/used_dominate + var/chemicals = 10 // Chemicals used for reproduction and spitting neurotoxin. + var/mob/living/carbon/human/host // Human host for the brain worm. + var/truename // Name used for brainworm-speak. + var/mob/living/captive_brain/host_brain // Used for swapping control of the body back and forth. + var/controlling // Used in human death check. + var/docile = 0 // Sugar can stop borers from acting. + var/has_reproduced + var/roundstart + +/mob/living/simple_animal/borer/roundstart + roundstart = 1 + +/mob/living/simple_animal/borer/New() + ..() + + add_language("Cortical Link") + verbs += /mob/living/proc/ventcrawl + verbs += /mob/living/proc/hide + + truename = "[pick("Primary","Secondary","Tertiary","Quaternary")] [rand(1000,9999)]" + if(!roundstart) request_player() + +/mob/living/simple_animal/borer/Life() + + ..() + + if(host) + + if(!stat && !host.stat) + + if(host.reagents.has_reagent("sugar")) + if(!docile) + if(controlling) + host << "\blue You feel the soporific flow of sugar in your host's blood, lulling you into docility." + else + src << "\blue You feel the soporific flow of sugar in your host's blood, lulling you into docility." + docile = 1 + else + if(docile) + if(controlling) + host << "\blue You shake off your lethargy as the sugar leaves your host's blood." + else + src << "\blue You shake off your lethargy as the sugar leaves your host's blood." + docile = 0 + + if(chemicals < 250) + chemicals++ + if(controlling) + + if(docile) + host << "\blue You are feeling far too docile to continue controlling your host..." + host.release_control() + return + + if(prob(5)) + host.adjustBrainLoss(rand(1,2)) + + if(prob(host.brainloss/20)) + host.say("*[pick(list("blink","blink_r","choke","aflap","drool","twitch","twitch_s","gasp"))]") + +/mob/living/simple_animal/borer/Stat() + ..() + statpanel("Status") + + if(emergency_shuttle) + var/eta_status = emergency_shuttle.get_status_panel_eta() + if(eta_status) + stat(null, eta_status) + + if (client.statpanel == "Status") + stat("Chemicals", chemicals) + +/mob/living/simple_animal/borer/proc/detatch() + + if(!host || !controlling) return + + if(istype(host,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = host + var/datum/organ/external/head = H.get_organ("head") + head.implants -= src + + controlling = 0 + + host.remove_language("Cortical Link") + host.verbs -= /mob/living/carbon/proc/release_control + host.verbs -= /mob/living/carbon/proc/punish_host + host.verbs -= /mob/living/carbon/proc/spawn_larvae + + if(host_brain) + + // these are here so bans and multikey warnings are not triggered on the wrong people when ckey is changed. + // computer_id and IP are not updated magically on their own in offline mobs -walter0o + + // host -> self + var/h2s_id = host.computer_id + var/h2s_ip= host.lastKnownIP + host.computer_id = null + host.lastKnownIP = null + + src.ckey = host.ckey + + if(!src.computer_id) + src.computer_id = h2s_id + + if(!host_brain.lastKnownIP) + src.lastKnownIP = h2s_ip + + // brain -> host + var/b2h_id = host_brain.computer_id + var/b2h_ip= host_brain.lastKnownIP + host_brain.computer_id = null + host_brain.lastKnownIP = null + + host.ckey = host_brain.ckey + + if(!host.computer_id) + host.computer_id = b2h_id + + if(!host.lastKnownIP) + host.lastKnownIP = b2h_ip + + del(host_brain) + +/mob/living/simple_animal/borer/proc/leave_host() + + if(!host) return + + if(host.mind) + //If they're not a proper traitor, reset their antag status. + if(host.mind.special_role == "Borer Thrall") + host << "You are no longer an antagonist." + ticker.mode.borers -= host.mind + host.mind.special_role = null + + src.loc = get_turf(host) + + reset_view(null) + machine = null + + host.reset_view(null) + host.machine = null + + var/mob/living/H = host + H.status_flags &= ~PASSEMOTES + host = null + return + +//Procs for grabbing players. +/mob/living/simple_animal/borer/proc/request_player() + for(var/mob/dead/observer/O in player_list) + if(jobban_isbanned(O, "Syndicate")) + continue + if(O.client) + if(O.client.prefs.be_special & BE_ALIEN) + question(O.client) + +/mob/living/simple_animal/borer/proc/question(var/client/C) + spawn(0) + if(!C) return + var/response = alert(C, "A cortical borer needs a player. Are you interested?", "Cortical borer request", "Yes", "No", "Never for this round") + if(!C || ckey) + return + if(response == "Yes") + transfer_personality(C) + else if (response == "Never for this round") + C.prefs.be_special ^= BE_ALIEN + +/mob/living/simple_animal/borer/proc/transfer_personality(var/client/candidate) + + if(!candidate) + return + + src.mind = candidate.mob.mind + src.ckey = candidate.ckey + if(src.mind) + src.mind.assigned_role = "Cortical Borer" + src.mind.special_role = "Cortical Borer" + ticker.mode.borers |= src.mind + +/mob/living/carbon/alien/can_use_vents() + return \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/borer/borer_captive.dm b/code/modules/mob/living/simple_animal/borer/borer_captive.dm new file mode 100644 index 0000000000..808a2199f1 --- /dev/null +++ b/code/modules/mob/living/simple_animal/borer/borer_captive.dm @@ -0,0 +1,35 @@ +/mob/living/captive_brain + name = "host brain" + real_name = "host brain" + universal_understand = 1 + +/mob/living/captive_brain/say(var/message) + + if (src.client) + if(client.prefs.muted & MUTE_IC) + src << "\red You cannot speak in IC (muted)." + return + if (src.client.handle_spam_prevention(message,MUTE_IC)) + return + + if(istype(src.loc,/mob/living/simple_animal/borer)) + + message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) + if (!message) + return + log_say("[key_name(src)] : [message]") + if (stat == 2) + return say_dead(message) + + var/mob/living/simple_animal/borer/B = src.loc + src << "You whisper silently, \"[message]\"" + B.host << "The captive mind of [src] whispers, \"[message]\"" + + for (var/mob/M in player_list) + if (istype(M, /mob/new_player)) + continue + else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS) + M << "The captive mind of [src] whispers, \"[message]\"" + +/mob/living/captive_brain/emote(var/message) + return \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/borer/borer_powers.dm b/code/modules/mob/living/simple_animal/borer/borer_powers.dm new file mode 100644 index 0000000000..9f47dd6cf4 --- /dev/null +++ b/code/modules/mob/living/simple_animal/borer/borer_powers.dm @@ -0,0 +1,348 @@ +/mob/living/simple_animal/borer/verb/release_host() + set category = "Abilities" + set name = "Release Host" + set desc = "Slither out of your host." + + if(!host) + src << "You are not inside a host body." + return + + if(stat) + src << "You cannot leave your host in your current state." + + if(docile) + src << "\blue You are feeling far too docile to do that." + return + + if(!host || !src) return + + src << "You begin disconnecting from [host]'s synapses and prodding at their internal ear canal." + + if(!host.stat) + host << "An odd, uncomfortable pressure begins to build inside your skull, behind your ear..." + + spawn(100) + + if(!host || !src) return + + if(src.stat) + src << "You cannot release your host in your current state." + return + + src << "You wiggle out of [host]'s ear and plop to the ground." + if(host.mind) + if(!host.stat) + host << "Something slimy wiggles out of your ear and plops to the ground!" + host << "As though waking from a dream, you shake off the insidious mind control of the brain worm. Your thoughts are your own again." + + detatch() + leave_host() + +/mob/living/simple_animal/borer/verb/infest() + set category = "Abilities" + set name = "Infest" + set desc = "Infest a suitable humanoid host." + + if(host) + src << "You are already within a host." + return + + if(stat) + src << "You cannot infest a target in your current state." + return + + var/list/choices = list() + for(var/mob/living/carbon/C in view(1,src)) + if(src.Adjacent(C)) + choices += C + + var/mob/living/carbon/M = input(src,"Who do you wish to infest?") in null|choices + + if(!M || !src) return + + if(!(src.Adjacent(M))) return + + if(M.has_brain_worms()) + src << "You cannot infest someone who is already infested!" + return + + if(istype(M,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + + if(!H.species.has_organ["brain"]) + src << "\The [H] does not seem to have an ear canal to breach." + return + + if(H.check_head_coverage()) + src << "You cannot get through that host's protective gear." + return + + M << "Something slimy begins probing at the opening of your ear canal..." + src << "You slither up [M] and begin probing at their ear canal..." + + if(!do_after(src,30)) + src << "As [M] moves away, you are dislodged and fall to the ground." + return + + if(!M || !src) return + + if(src.stat) + src << "You cannot infest a target in your current state." + return + + if(M in view(1, src)) + src << "You wiggle into [M]'s ear." + if(!M.stat) + M << "Something disgusting and slimy wiggles into your ear!" + + src.host = M + src.host.status_flags |= PASSEMOTES + src.loc = M + + //Update their traitor status. + if(host.mind) + if(!host.mind.special_role) + ticker.mode.borers |= host.mind + host.mind.special_role = "Borer Thrall" + host << "A creeping lassitude surrounds you. Your mind is being invaded by an alien intelligence and that's just fine." + host << "You are now a thrall to a cortical borer. Please listen to what they have to say; they're in your head." + show_generic_antag_text(host.mind) + + if(istype(M,/mob/living/carbon/human)) + + var/mob/living/carbon/human/H = M + var/datum/organ/internal/I = H.internal_organs_by_name["brain"] + if(!I) // No brain organ, so the borer moves in and replaces it permanently. + replace_brain() + else + // If they're in normally, implant removal can get them out. + var/datum/organ/external/head = H.get_organ("head") + head.implants += src + + return + else + src << "They are no longer in range!" + return + +/mob/living/simple_animal/borer/verb/devour_brain() + set category = "Abilities" + set name = "Devour Brain" + set desc = "Take permanent control of a dead host." + + if(!host) + src << "You are not inside a host body." + return + + if(host.stat != 2) + src << "Your host is still alive." + return + + if(stat) + src << "You cannot do that in your current state." + + if(docile) + src << "\blue You are feeling far too docile to do that." + return + + + src << "It only takes a few moments to render the dead host brain down into a nutrient-rich slurry..." + replace_brain() + +// BRAIN WORM ZOMBIES AAAAH. +/mob/living/simple_animal/borer/proc/replace_brain() + + var/mob/living/carbon/human/H = host + + if(!istype(host)) + src << "This host does not have a suitable brain." + return + + src << "You settle into the empty brainpan and begin to expand, fusing inextricably with the dead flesh of [H]." + + H.add_language("Cortical Link") + + if(host.stat == 2) + H.verbs |= /mob/living/carbon/human/proc/jumpstart + + H.verbs |= /mob/living/carbon/human/proc/psychic_whisper + H.verbs |= /mob/living/carbon/human/proc/tackle + H.verbs |= /mob/living/carbon/proc/spawn_larvae + + if(H.client) + H.ghostize(0) + + if(src.mind) + src.mind.special_role = "Borer Husk" + src.mind.transfer_to(host) + + H.ChangeToHusk() + + var/datum/organ/internal/borer/B = new(H) + H.internal_organs_by_name["brain"] = B + H.internal_organs |= B + + var/s2h_id = src.computer_id + var/s2h_ip= src.lastKnownIP + src.computer_id = null + src.lastKnownIP = null + + if(!H.computer_id) + H.computer_id = s2h_id + + if(!H.lastKnownIP) + H.lastKnownIP = s2h_ip + +/mob/living/simple_animal/borer/verb/secrete_chemicals() + set category = "Abilities" + set name = "Secrete Chemicals" + set desc = "Push some chemicals into your host's bloodstream." + + if(!host) + src << "You are not inside a host body." + return + + if(stat) + src << "You cannot secrete chemicals in your current state." + + if(docile) + src << "\blue You are feeling far too docile to do that." + return + + if(chemicals < 50) + src << "You don't have enough chemicals!" + + var/chem = input("Select a chemical to secrete.", "Chemicals") in list("bicaridine","tramadol","hyperzine","alkysine") + + if(chemicals < 50 || !host || controlling || !src || stat) //Sanity check. + return + + src << "\red You squirt a measure of [chem] from your reservoirs into [host]'s bloodstream." + host.reagents.add_reagent(chem, 10) + chemicals -= 50 + +/mob/living/simple_animal/borer/verb/dominate_victim() + set category = "Abilities" + set name = "Paralyze Victim" + set desc = "Freeze the limbs of a potential host with supernatural fear." + + if(world.time - used_dominate < 150) + src << "You cannot use that ability again so soon." + return + + if(host) + src << "You cannot do that from within a host body." + return + + if(src.stat) + src << "You cannot do that in your current state." + return + + var/list/choices = list() + for(var/mob/living/carbon/C in view(3,src)) + if(C.stat != 2) + choices += C + + if(world.time - used_dominate < 150) + src << "You cannot use that ability again so soon." + return + + var/mob/living/carbon/M = input(src,"Who do you wish to dominate?") in null|choices + + if(!M || !src) return + + if(M.has_brain_worms()) + src << "You cannot infest someone who is already infested!" + return + + src << "\red You focus your psychic lance on [M] and freeze their limbs with a wave of terrible dread." + M << "\red You feel a creeping, horrible sense of dread come over you, freezing your limbs and setting your heart racing." + M.Weaken(10) + + used_dominate = world.time + +/mob/living/simple_animal/borer/verb/bond_brain() + set category = "Abilities" + set name = "Assume Control" + set desc = "Fully connect to the brain of your host." + + if(!host) + src << "You are not inside a host body." + return + + if(src.stat) + src << "You cannot do that in your current state." + return + + if(docile) + src << "\blue You are feeling far too docile to do that." + return + + src << "You begin delicately adjusting your connection to the host brain..." + + spawn(100+(host.brainloss*5)) + + if(!host || !src || controlling) + return + else + + src << "\red You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system." + host << "\red You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours." + host.add_language("Cortical Link") + + // host -> brain + var/h2b_id = host.computer_id + var/h2b_ip= host.lastKnownIP + host.computer_id = null + host.lastKnownIP = null + + del(host_brain) + host_brain = new(src) + + host_brain.ckey = host.ckey + + host_brain.name = host.name + + if(!host_brain.computer_id) + host_brain.computer_id = h2b_id + + if(!host_brain.lastKnownIP) + host_brain.lastKnownIP = h2b_ip + + // self -> host + var/s2h_id = src.computer_id + var/s2h_ip= src.lastKnownIP + src.computer_id = null + src.lastKnownIP = null + + host.ckey = src.ckey + + if(!host.computer_id) + host.computer_id = s2h_id + + if(!host.lastKnownIP) + host.lastKnownIP = s2h_ip + + controlling = 1 + + host.verbs += /mob/living/carbon/proc/release_control + host.verbs += /mob/living/carbon/proc/punish_host + host.verbs += /mob/living/carbon/proc/spawn_larvae + + return + +/mob/living/carbon/human/proc/jumpstart() + set category = "Abilities" + set name = "Revive Host" + set desc = "Send a jolt of electricity through your host, reviving them." + + if(stat != 2) + usr << "Your host is already alive." + return + + verbs -= /mob/living/carbon/human/proc/jumpstart + visible_message("With a hideous, rattling moan, [src] shudders back to life!") + + rejuvenate() + vessel.add_reagent("blood",560-vessel.total_volume) + fixblood() + update_canmove() \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/borer/say.dm b/code/modules/mob/living/simple_animal/borer/say.dm new file mode 100644 index 0000000000..c0bfb0711f --- /dev/null +++ b/code/modules/mob/living/simple_animal/borer/say.dm @@ -0,0 +1,42 @@ +/mob/living/simple_animal/borer/say(var/message) + + message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) + message = capitalize(message) + + if(!message) + return + + if (stat == 2) + return say_dead(message) + + if (stat) + return + + if (src.client) + if(client.prefs.muted & MUTE_IC) + src << "\red You cannot speak in IC (muted)." + return + if (src.client.handle_spam_prevention(message,MUTE_IC)) + return + + if (copytext(message, 1, 2) == "*") + return emote(copytext(message, 2)) + + var/datum/language/L = parse_language(message) + if(L && L.flags & HIVEMIND) + L.broadcast(src,trim(copytext(message,3)),src.truename) + return + + if(!host) + //TODO: have this pick a random mob within 3 tiles to speak for the borer. + src << "You have no host to speak to." + return //No host, no audible speech. + + src << "You drop words into [host]'s mind: \"[message]\"" + host << "Your own thoughts speak: \"[message]\"" + + for (var/mob/M in player_list) + if (istype(M, /mob/new_player)) + continue + else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS) + M << "[src.truename] whispers to [host], \"[message]\"" \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 48dc61b08e..d3aa156ea4 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -88,7 +88,7 @@ now_pushing = null -/mob/living/simple_animal/construct/attack_animal(mob/living/simple_animal/M as mob) +/mob/living/simple_animal/construct/attack_animal(mob/living/M as mob) if(istype(M, /mob/living/simple_animal/construct/builder)) health += 5 M.emote("mends some of \the [src]'s wounds.") diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index 5a13dccc49..4f5eda2af9 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -51,6 +51,10 @@ /mob/living/simple_animal/mouse/New() ..() + + verbs += /mob/living/proc/ventcrawl + verbs += /mob/living/proc/hide + name = "[name] ([rand(1, 1000)])" if(!body_color) body_color = pick( list("brown","gray","white") ) @@ -59,7 +63,6 @@ icon_dead = "mouse_[body_color]_dead" desc = "It's a small [body_color] rodent, often seen hiding in maintenance areas and making a nuisance of itself." - /mob/living/simple_animal/mouse/proc/splat() src.health = 0 src.stat = DEAD @@ -69,59 +72,6 @@ if(client) client.time_died_as_mouse = world.time -/mob/living/simple_animal/mouse/verb/ventcrawl() - set name = "Crawl through Vent" - set desc = "Enter an air vent and crawl through the pipe system." - set category = "Mouse" - handle_ventcrawl() - return - -//copy paste from alien/larva, if that func is updated please update this one alsoghost -/mob/living/simple_animal/mouse/verb/hide() - set name = "Hide" - set desc = "Allows to hide beneath tables or certain items. Toggled on or off." - set category = "Mouse" - - if (layer != TURF_LAYER+0.2) - layer = TURF_LAYER+0.2 - src << text("\blue You are now hiding.") - /* - for(var/mob/O in oviewers(src, null)) - if ((O.client && !( O.blinded ))) - O << text("[] scurries to the ground!", src) - */ - else - layer = MOB_LAYER - src << text("\blue You have stopped hiding.") - /* - for(var/mob/O in oviewers(src, null)) - if ((O.client && !( O.blinded ))) - O << text("[] slowly peaks up from the ground...", src) - */ - -//make mice fit under tables etc? this was hacky, and not working -/* -/mob/living/simple_animal/mouse/Move(var/dir) - - var/turf/target_turf = get_step(src,dir) - //CanReachThrough(src.loc, target_turf, src) - var/can_fit_under = 0 - if(target_turf.ZCanPass(get_turf(src),1)) - can_fit_under = 1 - - ..(dir) - if(can_fit_under) - src.loc = target_turf - for(var/d in cardinal) - var/turf/O = get_step(T,d) - //Simple pass check. - if(O.ZCanPass(T, 1) && !(O in open) && !(O in closed) && O in possibles) - open += O - */ - -///mob/living/simple_animal/mouse/restrained() //Hotfix to stop mice from doing things with MouseDrop -// return 1 - /mob/living/simple_animal/mouse/start_pulling(var/atom/movable/AM)//Prevents mouse from pulling things src << "You are too small to pull anything." return @@ -163,3 +113,6 @@ response_help = "pets" response_disarm = "gently pushes aside" response_harm = "splats" + +/mob/living/carbon/alien/can_use_vents() + return \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm index 1c489f4902..4c95c54c7b 100644 --- a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm +++ b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm @@ -215,67 +215,7 @@ src.Del() return -//copy paste from alien/larva, if that func is updated please update this one also -/mob/living/simple_animal/spiderbot/verb/ventcrawl() - set name = "Crawl through Vent" - set desc = "Enter an air vent and crawl through the pipe system." - set category = "Spiderbot" - -// if(!istype(V,/obj/machinery/atmoalter/siphs/fullairsiphon/air_vent)) -// return - var/obj/machinery/atmospherics/unary/vent_pump/vent_found - var/welded = 0 - for(var/obj/machinery/atmospherics/unary/vent_pump/v in range(1,src)) - if(!v.welded) - vent_found = v - break - else - welded = 1 - if(vent_found) - if(vent_found.network&&vent_found.network.normal_members.len) - var/list/vents = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in vent_found.network.normal_members) - if(temp_vent.loc == loc) - continue - vents.Add(temp_vent) - var/list/choices = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/vent in vents) - if(vent.loc.z != loc.z) - continue - var/atom/a = get_turf(vent) - choices.Add(a.loc) - var/turf/startloc = loc - var/obj/selection = input("Select a destination.", "Duct System") in choices - var/selection_position = choices.Find(selection) - if(loc==startloc) - var/obj/target_vent = vents[selection_position] - if(target_vent) - loc = target_vent.loc - else - src << "\blue You need to remain still while entering a vent." - else - src << "\blue This vent is not connected to anything." - else if(welded) - src << "\red That vent is welded." - else - src << "\blue You must be standing on or beside an air vent to enter it." - return - -//copy paste from alien/larva, if that func is updated please update this one alsoghost -/mob/living/simple_animal/spiderbot/verb/hide() - set name = "Hide" - set desc = "Allows to hide beneath tables or certain items. Toggled on or off." - set category = "Spiderbot" - - if (layer != TURF_LAYER+0.2) - layer = TURF_LAYER+0.2 - src << text("\blue You are now hiding.") - else - layer = MOB_LAYER - src << text("\blue You have stopped hiding.") - //Cannibalized from the parrot mob. ~Zuhayr - /mob/living/simple_animal/spiderbot/verb/drop_held_item() set name = "Drop held item" set category = "Spiderbot" diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index 5740e51b1e..000b125673 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -135,8 +135,8 @@ if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) return - //Is the usr's mob type able to do this? (lolaliens) - if(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr)) + //Is the usr's mob type able to do this? + if(ishuman(usr) || ismonkey(usr) || isrobot(usr)) //Removing from inventory if(href_list["remove_inv"]) @@ -235,11 +235,8 @@ /mob/living/simple_animal/parrot/attack_paw(mob/living/carbon/monkey/M as mob) attack_hand(M) -/mob/living/simple_animal/parrot/attack_alien(mob/living/carbon/monkey/M as mob) - attack_hand(M) - //Simple animals -/mob/living/simple_animal/parrot/attack_animal(mob/living/simple_animal/M as mob) +/mob/living/simple_animal/parrot/attack_animal(mob/living/M as mob) if(client) return diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index e5f9136362..b9e6e714dd 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -44,17 +44,14 @@ var/min_n2 = 0 var/max_n2 = 0 var/unsuitable_atoms_damage = 2 //This damage is taken when atmos doesn't fit all the requirements above - + var/speed = 0 //LETS SEE IF I CAN SET SPEEDS FOR SIMPLE MOBS WITHOUT DESTROYING EVERYTHING. Higher speed is slower, negative speed is faster //LETTING SIMPLE ANIMALS ATTACK? WHAT COULD GO WRONG. Defaults to zero so Ian can still be cuddly - var/melee_damage_lower = 0 - var/melee_damage_upper = 0 - var/attacktext = "attacks" - var/attack_sound = null - var/friendly = "nuzzles" //If the mob does no damage with it's attack - var/wall_smash = 0 //if they can smash walls - - var/speed = 0 //LETS SEE IF I CAN SET SPEEDS FOR SIMPLE MOBS WITHOUT DESTROYING EVERYTHING. Higher speed is slower, negative speed is faster + melee_damage_lower = 0 + melee_damage_upper = 0 + attacktext = "attacks" + attack_sound = null + friendly = "nuzzles" //If the mob does no damage with it's attack /mob/living/simple_animal/New() ..() @@ -212,7 +209,7 @@ if(act == "scream") act = "whimper" //ugly hack to stop animals screaming when crushed :P ..(act, type, desc) -/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M as mob) +/mob/living/simple_animal/attack_animal(mob/living/M as mob) if(M.melee_damage_upper == 0) M.emote("[M.friendly] [src]") else @@ -228,7 +225,7 @@ /mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj) if(!Proj || Proj.nodamage) return - + adjustBruteLoss(Proj.damage) return 0 @@ -270,59 +267,6 @@ return -/mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M as mob) - - switch(M.a_intent) - - if ("help") - - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M] caresses [src] with its scythe like arm."), 1) - if ("grab") - if(M == src) - return - if(!(status_flags & CANPUSH)) - return - - var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, M, src ) - - M.put_in_active_hand(G) - - grabbed_by += G - G.synch() - G.affecting = src - LAssailant = M - - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) - - if("hurt", "disarm") - var/damage = rand(15, 30) - visible_message("\red [M] has slashed at [src]!") - adjustBruteLoss(damage) - - return - -/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L as mob) - - switch(L.a_intent) - if("help") - visible_message("\blue [L] rubs it's head against [src]") - - - else - - var/damage = rand(5, 10) - visible_message("\red [L] bites [src]!") - - if(stat != DEAD) - adjustBruteLoss(damage) - L.amount_grown = min(L.amount_grown + damage, L.max_grown) - - /mob/living/simple_animal/attack_slime(mob/living/carbon/slime/M as mob) if (!ticker) M << "You cannot attack people before the game has started." @@ -461,4 +405,4 @@ message = capitalize(trim_left(message)) - ..(message, null, verb) + ..(message, null, verb) \ No newline at end of file diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index bf5be72fc4..4b9d28402c 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -45,15 +45,4 @@ client.eye = src client.perspective = MOB_PERSPECTIVE - //Clear ability list and update from mob. - client.verbs -= ability_verbs - - if(abilities) - client.verbs |= abilities - - if(istype(src,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = src - if(H.species && H.species.abilities) - client.verbs |= H.species.abilities - nanomanager.send_resources(client) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index e264395b15..d7bd050e9c 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1070,3 +1070,12 @@ mob/proc/yank_out_object() if(paralysis) AdjustParalysis(-1) return paralysis + +//Check for brain worms in head. +/mob/proc/has_brain_worms() + + for(var/I in contents) + if(istype(I,/mob/living/simple_animal/borer)) + return I + + return 0 diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index f781616120..08e01d2b88 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -88,7 +88,6 @@ var/list/pinned = list() // List of things pinning this creature to walls (see living_defense.dm) var/list/embedded = list() // Embedded items, since simple mobs don't have organs. var/list/languages = list() // For speaking/listening. - var/list/abilities = list() // For species-derived or admin-given powers. var/list/speak_emote = list("says") // Verbs used when speaking. Defaults to 'say' if speak_emote is null. var/emote_type = 1 // Define emote default type, 1 for seen emotes, 2 for heard emotes @@ -97,7 +96,6 @@ var/timeofdeath = 0.0//Living var/cpr_time = 1.0//Carbon - var/bodytemperature = 310.055 //98.7 F var/old_x = 0 var/old_y = 0 @@ -214,8 +212,6 @@ //Whether or not mobs can understand other mobtypes. These stay in /mob so that ghosts can hear everything. var/universal_speak = 0 // Set to 1 to enable the mob to speak to everyone -- TLE var/universal_understand = 0 // Set to 1 to enable the mob to understand everyone, not necessarily speak - var/robot_talk_understand = 0 - var/alien_talk_understand = 0 var/has_limbs = 1 //Whether this mob have any limbs he can move with var/can_stand = 1 //Whether this mob have ability to stand diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index a95f8612c1..ad8915f5e3 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -191,10 +191,22 @@ return if(M == assailant && state >= GRAB_AGGRESSIVE) - if( (ishuman(user) && (FAT in user.mutations) && ismonkey(affecting) ) || ( isalien(user) && iscarbon(affecting) ) ) + var/can_eat + + if((FAT in user.mutations) && ismonkey(affecting)) + can_eat = 1 + else + var/mob/living/carbon/human/H = user + if(istype(H) && iscarbon(affecting) && H.species.gluttonous) + if(H.species.gluttonous == 2) + can_eat = 2 + else if(!ishuman(affecting)) + can_eat = 1 + + if(can_eat) var/mob/living/carbon/attacker = user user.visible_message("[user] is attempting to devour [affecting]!") - if(istype(user, /mob/living/carbon/alien/humanoid/hunter)) + if(can_eat == 2) if(!do_mob(user, affecting)||!do_after(user, 30)) return else if(!do_mob(user, affecting)||!do_after(user, 100)) return diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 93cca72284..51676ca04f 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -5,6 +5,11 @@ return 1 return 0 +/proc/isalien(A) + if(istype(A, /mob/living/carbon/alien)) + return 1 + return 0 + /proc/ismonkey(A) if(A && istype(A, /mob/living/carbon/monkey)) return 1 @@ -15,21 +20,6 @@ return 1 return 0 -/proc/isalien(A) - if(istype(A, /mob/living/carbon/alien)) - return 1 - return 0 - -/proc/isalienadult(A) - if(istype(A, /mob/living/carbon/alien/humanoid)) - return 1 - return 0 - -/proc/islarva(A) - if(istype(A, /mob/living/carbon/alien/larva)) - return 1 - return 0 - /proc/isslime(A) if(istype(A, /mob/living/carbon/slime)) return 1 @@ -189,7 +179,7 @@ var/list/global/organ_rel_size = list( var/ran_zone = zone while (ran_zone == zone) - ran_zone = pick ( + ran_zone = pick ( organ_rel_size["head"]; "head", organ_rel_size["chest"]; "chest", organ_rel_size["groin"]; "groin", @@ -202,7 +192,7 @@ var/list/global/organ_rel_size = list( organ_rel_size["l_foot"]; "l_foot", organ_rel_size["r_foot"]; "r_foot", ) - + return ran_zone // Emulates targetting a specific body part, and miss chances @@ -399,7 +389,7 @@ var/list/intents = list("help","disarm","grab","hurt") set name = "a-intent" set hidden = 1 - if(ishuman(src) || isalienadult(src) || isbrain(src)) + if(ishuman(src) || isbrain(src)) switch(input) if("help","disarm","grab","hurt") a_intent = input @@ -410,7 +400,7 @@ var/list/intents = list("help","disarm","grab","hurt") if(hud_used && hud_used.action_intent) hud_used.action_intent.icon_state = "intent_[a_intent]" - else if(isrobot(src) || ismonkey(src) || islarva(src)) + else if(isrobot(src) || ismonkey(src)) switch(input) if("help") a_intent = "help" diff --git a/code/modules/mob/mob_transformation_simple.dm b/code/modules/mob/mob_transformation_simple.dm index bea08693fb..f07cadb9e8 100644 --- a/code/modules/mob/mob_transformation_simple.dm +++ b/code/modules/mob/mob_transformation_simple.dm @@ -2,7 +2,7 @@ //This proc is the most basic of the procs. All it does is make a new mob on the same tile and transfer over a few variables. //Returns the new mob //Note that this proc does NOT do MMI related stuff! -/mob/proc/change_mob_type(var/new_type = null, var/turf/location = null, var/new_name = null as text, var/delete_old_mob = 0 as num) +/mob/proc/change_mob_type(var/new_type = null, var/turf/location = null, var/new_name = null as text, var/delete_old_mob = 0 as num, var/subspecies) if(istype(src,/mob/new_player)) usr << "\red cannot convert players who have not entered yet." @@ -48,6 +48,10 @@ else M.key = key + if(subspecies && istype(M,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + H.set_species(subspecies) + if(delete_old_mob) spawn(1) del(src) diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index 6d5e308c7a..27ecfcc87e 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -90,8 +90,6 @@ return 1 if (istype(other, src.type) || istype(src, other.type)) return 1 - if(src.alien_talk_understand && other.alien_talk_understand) - return 1 return 0 //Language check. diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 200d3e342b..1ed8bc43b1 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -198,14 +198,7 @@ del(t) var/alien_caste = pick("Hunter","Sentinel","Drone") - var/mob/living/carbon/alien/humanoid/new_xeno - switch(alien_caste) - if("Hunter") - new_xeno = new /mob/living/carbon/alien/humanoid/hunter(loc) - if("Sentinel") - new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(loc) - if("Drone") - new_xeno = new /mob/living/carbon/alien/humanoid/drone(loc) + var/mob/living/carbon/human/new_xeno = create_new_xenomorph(alien_caste,loc) new_xeno.a_intent = "hurt" new_xeno.key = key diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm index 3a691d9d35..45eb41585d 100644 --- a/code/modules/organs/blood.dm +++ b/code/modules/organs/blood.dm @@ -30,8 +30,9 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 /mob/living/carbon/human/proc/fixblood() for(var/datum/reagent/blood/B in vessel.reagent_list) if(B.id == "blood") - B.data = list( "donor"=src,"viruses"=null,"blood_DNA"=dna.unique_enzymes,"blood_type"=dna.b_type, \ + B.data = list( "donor"=src,"viruses"=null,"species"=species.name,"blood_DNA"=dna.unique_enzymes,"blood_colour"= species.blood_color,"blood_type"=dna.b_type, \ "resistances"=null,"trace_chem"=null, "virus2" = null, "antibodies" = null) + B.color = B.data["blood_color"] // Takes care blood loss and regeneration /mob/living/carbon/human/proc/handle_blood() @@ -63,14 +64,17 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 // Damaged heart virtually reduces the blood volume, as the blood isn't // being pumped properly anymore. - var/datum/organ/internal/heart/heart = internal_organs_by_name["heart"] + if(species && species.has_organ["heart"]) + var/datum/organ/internal/heart/heart = internal_organs_by_name["heart"] - if(heart.damage > 1 && heart.damage < heart.min_bruised_damage) - blood_volume *= 0.8 - else if(heart.damage >= heart.min_bruised_damage && heart.damage < heart.min_broken_damage) - blood_volume *= 0.6 - else if(heart.damage >= heart.min_broken_damage && heart.damage < INFINITY) - blood_volume *= 0.3 + if(!heart) + blood_volume = 0 + else if(heart.damage > 1 && heart.damage < heart.min_bruised_damage) + blood_volume *= 0.8 + else if(heart.damage >= heart.min_bruised_damage && heart.damage < heart.min_broken_damage) + blood_volume *= 0.6 + else if(heart.damage >= heart.min_broken_damage && heart.damage < INFINITY) + blood_volume *= 0.3 //Effects of bloodloss switch(blood_volume) @@ -141,31 +145,8 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 if(!amt) return - var/turf/T = get_turf(src) - var/list/obj/effect/decal/cleanable/blood/drip/nums = list() - var/list/iconL = list("1","2","3","4","5") - vessel.remove_reagent("blood",amt) - - for(var/obj/effect/decal/cleanable/blood/drip/G in T) - nums += G - iconL.Remove(G.icon_state) - - if (nums.len < 5) - var/obj/effect/decal/cleanable/blood/drip/this = new(T) - this.icon_state = pick(iconL) - this.blood_DNA = list() - this.blood_DNA[dna.unique_enzymes] = dna.b_type - for (var/ID in virus2) - var/datum/disease2/disease/V = virus2[ID] - this.virus2[ID] = V.getcopy() - if (species) this.basecolor = species.blood_color - this.update_icon() - - else - for(var/obj/effect/decal/cleanable/blood/drip/G in nums) - del G - T.add_blood(src) + blood_splatter(src,src) /**************************************************** BLOOD TRANSFERS @@ -193,6 +174,12 @@ var/const/BLOOD_VOLUME_SURVIVE = 122 B.data["resistances"] = src.resistances.Copy() B.data["blood_type"] = copytext(src.dna.b_type,1,0) + // Putting this here due to return shenanigans. + if(istype(src,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = src + B.data["blood_colour"] = H.species.blood_color + B.color = B.data["blood_colour"] + var/list/temp_chem = list() for(var/datum/reagent/R in src.reagents.reagent_list) temp_chem += R.id @@ -279,4 +266,71 @@ proc/blood_incompatible(donor,receiver) if("O") if(donor_antigen != "O") return 1 //AB is a universal receiver. - return 0 \ No newline at end of file + return 0 + +proc/blood_splatter(var/target,var/datum/reagent/blood/source,var/large) + + var/obj/effect/decal/cleanable/blood/B + var/decal_type = /obj/effect/decal/cleanable/blood/splatter + var/turf/T = get_turf(target) + + if(istype(source,/mob/living/carbon/human)) + var/mob/living/carbon/human/M = source + source = M.get_blood(M.vessel) + else if(istype(source,/mob/living/carbon/monkey)) + var/mob/living/carbon/monkey/donor = source + if(donor.dna) + source = new() + source.data["blood_DNA"] = donor.dna.unique_enzymes + source.data["blood_type"] = donor.dna.b_type + + // Are we dripping or splattering? + if(!large) + + // Only a certain number of drips can be on a given turf. + var/list/drips = list() + var/list/drip_icons = list("1","2","3","4","5") + + for(var/obj/effect/decal/cleanable/blood/drip/drop in T) + drips += drop + drip_icons.Remove(drop.icon_state) + + // If we have too many drips, remove them and spawn a proper blood splatter. + if(drips.len >= 5) + //TODO: copy all virus data from drips to new splatter? + for(var/obj/effect/decal/cleanable/blood/drip/drop in drips) + del drop + else + decal_type = /obj/effect/decal/cleanable/blood/drip + + // Find a blood decal or create a new one. + B = locate(decal_type) in T + if(!B) + B = new decal_type(T) + + // If there's no data to copy, call it quits here. + if(!source) + return B + + // Update appearance. + if(source.data["blood_colour"]) + B.basecolor = source.data["blood_colour"] + B.update_icon() + + // Update blood information. + if(source.data["blood_DNA"]) + B.blood_DNA = list() + if(source.data["blood_type"]) + B.blood_DNA[source.data["blood_DNA"]] = source.data["blood_type"] + else + B.blood_DNA[source.data["blood_DNA"]] = "O+" + + // Update virus information. //Looks like this is out of date. + //for(var/datum/disease/D in source.data["viruses"]) + // var/datum/disease/new_virus = D.Copy(1) + // source.viruses += new_virus + // new_virus.holder = B + if(source.data["virus2"]) + B.virus2 = virus_copylist(source.data["virus2"]) + + return B \ No newline at end of file diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index f0c28d87c3..a69ee36c7d 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -1,6 +1,8 @@ /datum/organ var/name = "organ" var/mob/living/carbon/human/owner = null + var/status = 0 + var/vital //Lose a vital limb, die immediately. var/list/datum/autopsy_data/autopsy_data = list() var/list/trace_chemicals = list() // traces of chemicals in the organ, @@ -56,6 +58,7 @@ // Takes care of organ related updates, such as broken and missing limbs /mob/living/carbon/human/proc/handle_organs() + number_wounds = 0 var/leg_tally = 2 var/force_process = 0 diff --git a/code/modules/organs/organ_alien.dm b/code/modules/organs/organ_alien.dm new file mode 100644 index 0000000000..8eb5f12a31 --- /dev/null +++ b/code/modules/organs/organ_alien.dm @@ -0,0 +1,212 @@ +//DIONA ORGANS. +/datum/organ/internal/diona + removed_type = /obj/item/organ/diona + +/datum/organ/internal/diona/process() + return + +/datum/organ/internal/diona/strata + name = "neural strata" + parent_organ = "chest" + +/datum/organ/internal/diona/bladder + name = "gas bladder" + parent_organ = "head" + +/datum/organ/internal/diona/polyp + name = "polyp segment" + parent_organ = "groin" + +/datum/organ/internal/diona/ligament + name = "anchoring ligament" + parent_organ = "groin" + +/datum/organ/internal/diona/node + name = "receptor node" + parent_organ = "head" + removed_type = /obj/item/organ/diona/node + +/datum/organ/internal/diona/nutrients + name = "nutrient vessel" + parent_organ = "chest" + removed_type = /obj/item/organ/diona/nutrients + +/obj/item/organ/diona + name = "diona nymph" + icon = 'icons/obj/objects.dmi' + icon_state = "nymph" + organ_tag = "special" // Turns into a nymph instantly, no transplanting possible. + +/obj/item/organ/diona/removed(var/mob/living/target,var/mob/living/user) + + var/mob/living/carbon/human/H = target + if(!istype(target)) + del(src) + + if(!H.internal_organs.len) + H.death() + + //This is a terrible hack and I should be ashamed. + var/datum/seed/diona = seed_types["diona"] + if(!diona) + del(src) + + var/mob/living/carbon/alien/diona/D = new(get_turf(src)) + diona.request_player(D) + + del(src) + +//These are different to the standard diona organs as they have a purpose in other +// species (absorbing radiation and light respectively) +/obj/item/organ/diona/nutrients + name = "nutrient vessel" + organ_tag = "nutrient vessel" + +/obj/item/organ/diona/nutrients/removed() + return + +/obj/item/organ/diona/node + name = "receptor node" + organ_tag = "receptor node" + +/obj/item/organ/diona/node/removed() + return + +//CORTICAL BORER ORGANS. +/datum/organ/internal/borer + name = "cortical borer" + parent_organ = "head" + removed_type = /obj/item/organ/borer + vital = 1 + +/datum/organ/internal/borer/process() + + // Borer husks regenerate health, feel no pain, and are resistant to stuns and brainloss. + for(var/chem in list("tricordrazine","tramadol","hyperzine","alkysine")) + if(owner.reagents.get_reagent_amount(chem) < 3) + owner.reagents.add_reagent(chem, 5) + + // They're also super gross and ooze ichor. + if(prob(5)) + var/obj/effect/decal/cleanable/blood/splatter/goo = new(get_turf(owner)) + goo.name = "husk ichor" + goo.desc = "It's thick and stinks of decay." + goo.basecolor = "#412464" + goo.update_icon() + +/obj/item/organ/borer + name = "cortical borer" + icon = 'icons/obj/objects.dmi' + icon_state = "borer" + organ_tag = "brain" + desc = "A disgusting space slug." + +/obj/item/organ/borer/removed(var/mob/living/target,var/mob/living/user) + + + ..() + + var/mob/living/simple_animal/borer/B = target.has_brain_worms() + if(B) + B.leave_host() + B.ckey = target.ckey + + spawn(0) + del(src) + +//XENOMORPH ORGANS +/datum/organ/internal/xenos/eggsac + name = "egg sac" + parent_organ = "groin" + removed_type = /obj/item/organ/xenos/eggsac + +/datum/organ/internal/xenos/plasmavessel + name = "plasma vessel" + parent_organ = "chest" + removed_type = /obj/item/organ/xenos/plasmavessel + var/stored_plasma = 0 + var/max_plasma = 500 + +/datum/organ/internal/xenos/plasmavessel/queen + name = "bloated plasma vessel" + stored_plasma = 200 + max_plasma = 500 + +/datum/organ/internal/xenos/plasmavessel/sentinel + stored_plasma = 100 + max_plasma = 250 + +/datum/organ/internal/xenos/plasmavessel/hunter + name = "tiny plasma vessel" + stored_plasma = 100 + max_plasma = 150 + +/datum/organ/internal/xenos/acidgland + name = "acid gland" + parent_organ = "head" + removed_type = /obj/item/organ/xenos/acidgland + +/datum/organ/internal/xenos/hivenode + name = "hive node" + parent_organ = "chest" + removed_type = /obj/item/organ/xenos/hivenode + +/datum/organ/internal/xenos/resinspinner + name = "resin spinner" + parent_organ = "head" + removed_type = /obj/item/organ/xenos/resinspinner + +/obj/item/organ/xenos + name = "xeno organ" + icon = 'icons/effects/blood.dmi' + desc = "It smells like an accident in a chemical factory." + organ_tag = "special" //TODO functionality for transplants. + +/obj/item/organ/xenos/eggsac + name = "egg sac" + icon_state = "xgibmid1" + +/obj/item/organ/xenos/plasmavessel + name = "plasma vessel" + icon_state = "xgibdown" + +/obj/item/organ/xenos/acidgland + name = "acid gland" + icon_state = "xgibtorso" + +/obj/item/organ/xenos/hivenode + name = "hive node" + icon_state = "xgibmid2" + +/obj/item/organ/xenos/resinspinner + name = "hive node" + icon_state = "xgibmid2" + +//VOX ORGANS. +/datum/organ/internal/stack + name = "cortical stack" + removed_type = /obj/item/organ/stack + parent_organ = "head" + robotic = 2 + vital = 1 + var/backup_time = 0 + var/datum/mind/backup + +/datum/organ/internal/stack/process() + if(owner && owner.stat != 2 && !is_broken()) + backup_time = world.time + if(owner.mind) backup = owner.mind + +/datum/organ/internal/stack/vox + removed_type = /obj/item/organ/stack/vox + +/datum/organ/internal/stack/vox/stack + +/obj/item/organ/stack + name = "cortical stack" + icon_state = "brain-prosthetic" + organ_tag = "stack" + robotic = 2 + +/obj/item/organ/stack/vox + name = "vox cortical stack" \ No newline at end of file diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 79bbe771b3..c4df67cc87 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -32,12 +32,11 @@ var/damage_msg = "\red You feel an intense pain" var/broken_description - var/vital //Lose a vital limb, die immediately. - var/status = 0 var/open = 0 var/stage = 0 var/cavity = 0 - var/sabotaged = 0 //If a prosthetic limb is emagged, it will detonate when it fails. + var/sabotaged = 0 // If a prosthetic limb is emagged, it will detonate when it fails. + var/encased // Needs to be opened with a saw to access the organs. var/obj/item/hidden = null var/list/implants = list() @@ -855,6 +854,7 @@ Note that amputating the affected organ does in fact remove the infection from t min_broken_damage = 40 body_part = UPPER_TORSO vital = 1 + encased = "ribcage" /datum/organ/external/groin name = "groin" @@ -958,6 +958,7 @@ Note that amputating the affected organ does in fact remove the infection from t body_part = HEAD var/disfigured = 0 vital = 1 + encased = "skull" /datum/organ/external/head/get_icon(var/icon/race_icon, var/icon/deform_icon) if (!owner) @@ -1062,6 +1063,7 @@ obj/item/weapon/organ/r_hand obj/item/weapon/organ/r_leg name = "right leg" icon_state = "r_leg" + obj/item/weapon/organ/head name = "head" icon_state = "head_m" @@ -1158,11 +1160,12 @@ obj/item/weapon/organ/head/attackby(obj/item/weapon/W as obj, mob/user as mob) brainmob.attack_log += "\[[time_stamp()]\] Debrained by [user.name] ([user.ckey]) with [W.name] (INTENT: [uppertext(user.a_intent)])" msg_admin_attack("[user] ([user.ckey]) debrained [brainmob] ([brainmob.ckey]) (INTENT: [uppertext(user.a_intent)]) (JMP)") + //TODO: ORGAN REMOVAL UPDATE. if(istype(src,/obj/item/weapon/organ/head/posi)) var/obj/item/device/mmi/posibrain/B = new(loc) B.transfer_identity(brainmob) else - var/obj/item/brain/B = new(loc) + var/obj/item/organ/brain/B = new(loc) B.transfer_identity(brainmob) brain_op_stage = 4.0 diff --git a/code/modules/organs/organ_internal.dm b/code/modules/organs/organ_internal.dm index 4ed1004756..39840c88f0 100644 --- a/code/modules/organs/organ_internal.dm +++ b/code/modules/organs/organ_internal.dm @@ -1,8 +1,10 @@ +#define PROCESS_ACCURACY 10 + /**************************************************** INTERNAL ORGANS ****************************************************/ -/mob/living/carbon/human/var/list/internal_organs = list() +/mob/living/carbon/var/list/internal_organs = list() /datum/organ/internal var/damage = 0 // amount of damage to the organ @@ -10,7 +12,10 @@ var/min_broken_damage = 30 var/parent_organ = "chest" var/robotic = 0 //For being a robot - + var/removed_type //When removed, forms this object. + var/rejecting // Is this organ already being rejected? + var/obj/item/organ/organ_holder // If not in a body, held in this item. + var/list/transplant_data /datum/organ/internal/proc/rejuvenate() damage=0 @@ -18,22 +23,25 @@ return damage >= min_bruised_damage /datum/organ/internal/proc/is_broken() - return damage >= min_broken_damage + return damage >= min_broken_damage || status & ORGAN_CUT_AWAY - - -/datum/organ/internal/New(mob/living/carbon/human/H) +/datum/organ/internal/New(mob/living/carbon/M) ..() - var/datum/organ/external/E = H.organs_by_name[src.parent_organ] - if(E.internal_organs == null) - E.internal_organs = list() - E.internal_organs |= src - H.internal_organs |= src - src.owner = H + if(M && istype(M)) + + M.internal_organs |= src + src.owner = M + + var/mob/living/carbon/human/H = M + if(istype(H)) + var/datum/organ/external/E = H.organs_by_name[src.parent_organ] + if(E.internal_organs == null) + E.internal_organs = list() + E.internal_organs |= src /datum/organ/internal/process() - //Process infections + //Process infections if (robotic >= 2 || (owner.species && owner.species.flags & IS_PLANT)) //TODO make robotic internal and external organs separate types of organ instead of a flag germ_level = 0 return @@ -44,10 +52,10 @@ //** Handle the effects of infections var/antibiotics = owner.reagents.get_reagent_amount("spaceacillin") - + if (germ_level > 0 && germ_level < INFECTION_LEVEL_ONE/2 && prob(30)) germ_level-- - + if (germ_level >= INFECTION_LEVEL_ONE/2) //aiming for germ level to go from ambient to INFECTION_LEVEL_TWO in an average of 15 minutes if(antibiotics < 5 && prob(round(germ_level/6))) @@ -58,10 +66,33 @@ //spread germs if (antibiotics < 5 && parent.germ_level < germ_level && ( parent.germ_level < INFECTION_LEVEL_ONE*2 || prob(30) )) parent.germ_level++ - + if (prob(3)) //about once every 30 seconds take_damage(1,silent=prob(30)) + // Process unsuitable transplants. TODO: consider some kind of + // immunosuppressant that changes transplant data to make it match. + if(transplant_data) + if(!rejecting) //Should this transplant reject? + if(owner.species != transplant_data["species"]) //Nope. + rejecting = 1 + else if(prob(20) && owner.dna && blood_incompatible(transplant_data["blood_type"],owner.dna.b_type)) + rejecting = 1 + else + rejecting++ //Rejection severity increases over time. + if(rejecting % 10 == 0) //Only fire every ten rejection ticks. + switch(rejecting) + if(1 to 50) + take_damage(rand(1,2)) + if(51 to 200) + take_damage(rand(2,3)) + if(201 to 500) + take_damage(rand(3,4)) + owner.reagents.add_reagent("toxin", 1) + if(501 to INFINITY) + take_damage(5) + owner.reagents.add_reagent("toxin", rand(3,5)) + /datum/organ/internal/proc/take_damage(amount, var/silent=0) if(src.robotic == 2) src.damage += (amount * 0.8) @@ -111,21 +142,22 @@ INTERNAL ORGANS DEFINES ****************************************************/ -/datum/organ/internal/heart +/datum/organ/internal/heart // This is not set to vital because death immediately occurs in blood.dm if it is removed. name = "heart" parent_organ = "chest" - + removed_type = /obj/item/organ/heart /datum/organ/internal/lungs name = "lungs" parent_organ = "chest" + removed_type = /obj/item/organ/lungs process() ..() if (germ_level > INFECTION_LEVEL_ONE) if(prob(5)) owner.emote("cough") //respitory tract infection - + if(is_bruised()) if(prob(2)) spawn owner.emote("me", 1, "coughs up blood!") @@ -137,57 +169,90 @@ /datum/organ/internal/liver name = "liver" parent_organ = "chest" - var/process_accuracy = 10 + removed_type = /obj/item/organ/liver process() + ..() + if (germ_level > INFECTION_LEVEL_ONE) if(prob(1)) owner << "\red Your skin itches." if (germ_level > INFECTION_LEVEL_TWO) if(prob(1)) spawn owner.vomit() - - if(owner.life_tick % process_accuracy == 0) - if(src.damage < 0) - src.damage = 0 + + if(owner.life_tick % PROCESS_ACCURACY == 0) //High toxins levels are dangerous if(owner.getToxLoss() >= 60 && !owner.reagents.has_reagent("anti_toxin")) //Healthy liver suffers on its own if (src.damage < min_broken_damage) - src.damage += 0.2 * process_accuracy + src.damage += 0.2 * PROCESS_ACCURACY //Damaged one shares the fun else var/datum/organ/internal/O = pick(owner.internal_organs) if(O) - O.damage += 0.2 * process_accuracy + O.damage += 0.2 * PROCESS_ACCURACY //Detox can heal small amounts of damage if (src.damage && src.damage < src.min_bruised_damage && owner.reagents.has_reagent("anti_toxin")) - src.damage -= 0.2 * process_accuracy + src.damage -= 0.2 * PROCESS_ACCURACY - // Damaged liver means some chemicals are very dangerous - if(src.damage >= src.min_bruised_damage) - for(var/datum/reagent/R in owner.reagents.reagent_list) - // Ethanol and all drinks are bad - if(istype(R, /datum/reagent/ethanol)) - owner.adjustToxLoss(0.1 * process_accuracy) - // Can't cope with toxins at all - if(istype(R, /datum/reagent/toxin)) - owner.adjustToxLoss(0.3 * process_accuracy) + if(src.damage < 0) + src.damage = 0 + + // Get the effectiveness of the liver. + var/filter_effect = 3 + if(is_bruised()) + filter_effect -= 1 + if(is_broken()) + filter_effect -= 2 + + // Do some reagent filtering/processing. + for(var/datum/reagent/R in owner.reagents.reagent_list) + // Damaged liver means some chemicals are very dangerous + // The liver is also responsible for clearing out alcohol and toxins. + // Ethanol and all drinks are bad.K + if(istype(R, /datum/reagent/ethanol)) + if(filter_effect < 3) + owner.adjustToxLoss(0.1 * PROCESS_ACCURACY) + owner.reagents.remove_reagent(R.id, R.custom_metabolism*filter_effect) + // Can't cope with toxins at all + else if(istype(R, /datum/reagent/toxin)) + if(filter_effect < 3) + owner.adjustToxLoss(0.3 * PROCESS_ACCURACY) + owner.reagents.remove_reagent(R.id, ALCOHOL_METABOLISM*filter_effect) /datum/organ/internal/kidney - name = "kidney" - parent_organ = "chest" + name = "kidneys" + parent_organ = "groin" + removed_type = /obj/item/organ/kidneys + + process() + + ..() + + // Coffee is really bad for you with busted kidneys. + // This should probably be expanded in some way, but fucked if I know + // what else kidneys can process in our reagent list. + var/datum/reagent/coffee = locate(/datum/reagent/drink/coffee) in owner.reagents.reagent_list + if(coffee) + if(is_bruised()) + owner.adjustToxLoss(0.1 * PROCESS_ACCURACY) + else if(is_broken()) + owner.adjustToxLoss(0.3 * PROCESS_ACCURACY) /datum/organ/internal/brain name = "brain" parent_organ = "head" + removed_type = /obj/item/organ/brain + vital = 1 /datum/organ/internal/eyes name = "eyes" parent_organ = "head" + removed_type = /obj/item/organ/eyes process() //Eye damage replaces the old eye_stat var. ..() @@ -195,3 +260,21 @@ owner.eye_blurry = 20 if(is_broken()) owner.eye_blind = 20 + +/datum/organ/internal/appendix + name = "appendix" + parent_organ = "groin" + removed_type = /obj/item/organ/appendix + +/datum/organ/internal/proc/remove(var/mob/user) + + if(!removed_type) return 0 + + var/obj/item/organ/removed_organ = new removed_type(get_turf(user)) + + if(istype(removed_organ)) + removed_organ.organ_data = src + removed_organ.update() + organ_holder = removed_organ + + return removed_organ \ No newline at end of file diff --git a/code/modules/organs/organ_objects.dm b/code/modules/organs/organ_objects.dm new file mode 100644 index 0000000000..c48a9d4b54 --- /dev/null +++ b/code/modules/organs/organ_objects.dm @@ -0,0 +1,232 @@ +/obj/item/organ + name = "organ" + desc = "It looks like it probably just plopped out." + icon = 'icons/obj/surgery.dmi' + icon_state = "appendix" + + health = 100 // Process() ticks before death. + + var/fresh = 3 // Squirts of blood left in it. + var/dead_icon // Icon used when the organ dies. + var/robotic // Is the limb prosthetic? + var/organ_tag // What slot does it go in? + var/organ_type = /datum/organ/internal // Used to spawn the relevant organ data when produced via a machine or spawn(). + var/datum/organ/internal/organ_data // Stores info when removed. + var/prosthetic_name = "prosthetic organ" // Flavour string for robotic organ. + var/prosthetic_icon // Icon for robotic organ. + +/obj/item/organ/attack_self(mob/user as mob) + + // Convert it to an edible form, yum yum. + if(!robotic && user.a_intent == "help" && user.zone_sel.selecting == "mouth") + bitten(user) + return + +/obj/item/organ/New() + ..() + create_reagents(5) + if(!robotic) + processing_objects += src + spawn(1) + update() + +/obj/item/organ/Del() + if(!robotic) processing_objects -= src + ..() + +/obj/item/organ/process() + + if(robotic) + processing_objects -= src + return + + // Don't process if we're in a freezer, an MMI or a stasis bag. //TODO: ambient temperature? + if(istype(loc,/obj/item/device/mmi) || istype(loc,/obj/item/bodybag/cryobag) || istype(loc,/obj/structure/closet/crate/freezer)) + return + + if(fresh && prob(40)) + fresh-- + var/datum/reagent/blood = reagents.reagent_list["blood"] + blood_splatter(src,blood,1) + + health -= rand(1,3) + if(health <= 0) + die() + +/obj/item/organ/proc/die() + name = "dead [initial(name)]" + if(dead_icon) icon_state = dead_icon + health = 0 + processing_objects -= src + //TODO: Grey out the icon state. + //TODO: Inject an organ with peridaxon to make it alive again. + +/obj/item/organ/proc/roboticize() + + robotic = (organ_data && organ_data.robotic) ? organ_data.robotic : 1 + + if(prosthetic_name) + name = prosthetic_name + + if(prosthetic_icon) + icon_state = prosthetic_icon + else + //TODO: convert to greyscale. + +/obj/item/organ/proc/update() + + if(!organ_data) + organ_data = new /datum/organ/internal() + + if(robotic) + organ_data.robotic = robotic + + if(organ_data.robotic >= 2) + roboticize() + +// Brain is defined in brain_item.dm. +/obj/item/organ/heart + name = "heart" + icon_state = "heart-on" + prosthetic_name = "circulatory pump" + prosthetic_icon = "heart-prosthetic" + organ_tag = "heart" + fresh = 6 // Juicy. + dead_icon = "heart-off" + +/obj/item/organ/lungs + name = "lungs" + icon_state = "lungs" + prosthetic_name = "gas exchange system" + prosthetic_icon = "lungs-prosthetic" + organ_tag = "lungs" + +/obj/item/organ/kidneys + name = "kidneys" + icon_state = "kidneys" + prosthetic_name = "prosthetic kidneys" + prosthetic_icon = "kidneys-prosthetic" + organ_tag = "kidneys" + +/obj/item/organ/eyes + name = "eyeballs" + icon_state = "eyes" + prosthetic_name = "visual prosthesis" + prosthetic_icon = "eyes-prosthetic" + organ_tag = "eyes" + + var/eye_colour + +/obj/item/organ/liver + name = "liver" + icon_state = "liver" + prosthetic_name = "toxin filter" + prosthetic_icon = "liver-prosthetic" + organ_tag = "liver" + +/obj/item/organ/appendix + name = "appendix" + icon_state = "appendix" + organ_tag = "appendix" + +//These are here so they can be printed out via the fabricator. +/obj/item/organ/heart/prosthetic + robotic = 2 + +/obj/item/organ/lungs/prosthetic + robotic = 2 + +/obj/item/organ/kidneys/prosthetic + robotic = 2 + +/obj/item/organ/eyes/prosthetic + robotic = 2 + +/obj/item/organ/liver/prosthetic + robotic = 2 + +/obj/item/organ/appendix + name = "appendix" + +/obj/item/organ/proc/removed(var/mob/living/target,var/mob/living/user) + + if(!target || !user) + return + + if(organ_data.vital) + user.attack_log += "\[[time_stamp()]\] removed a vital organ ([src]) from [target.name] ([target.ckey]) (INTENT: [uppertext(user.a_intent)])" + target.attack_log += "\[[time_stamp()]\] had a vital organ ([src]) removed by [user.name] ([user.ckey]) (INTENT: [uppertext(user.a_intent)])" + msg_admin_attack("[user.name] ([user.ckey]) removed a vital organ ([src]) from [target.name] ([target.ckey]) (INTENT: [uppertext(user.a_intent)]) (JMP)") + target.death() + +/obj/item/organ/appendix/removed(var/mob/living/target,var/mob/living/user) + + ..() + + var/inflamed = 0 + for(var/datum/disease/appendicitis/appendicitis in target.viruses) + inflamed = 1 + appendicitis.cure() + target.resistances += appendicitis + + if(inflamed) + icon_state = "appendixinflamed" + name = "inflamed appendix" + +/obj/item/organ/eyes/removed(var/mob/living/target,var/mob/living/user) + + if(!eye_colour) + eye_colour = list(0,0,0) + + ..() //Make sure target is set so we can steal their eye colour for later. + var/mob/living/carbon/human/H = target + if(istype(H)) + eye_colour = list( + H.r_eyes ? H.r_eyes : 0, + H.g_eyes ? H.g_eyes : 0, + H.b_eyes ? H.b_eyes : 0 + ) + + // Leave bloody red pits behind! + H.r_eyes = 128 + H.g_eyes = 0 + H.b_eyes = 0 + H.update_body() + +/obj/item/organ/proc/replaced(var/mob/living/target) + return + +/obj/item/organ/eyes/replaced(var/mob/living/target) + + // Apply our eye colour to the target. + var/mob/living/carbon/human/H = target + if(istype(H) && eye_colour) + H.r_eyes = eye_colour[1] + H.g_eyes = eye_colour[2] + H.b_eyes = eye_colour[3] + H.update_body() + +/obj/item/organ/proc/bitten(mob/user) + + if(robotic) + return + + user << "\blue You take an experimental bite out of \the [src]." + var/datum/reagent/blood = reagents.reagent_list["blood"] + blood_splatter(src,blood,1) + + + user.drop_from_inventory(src) + var/obj/item/weapon/reagent_containers/food/snacks/organ/O = new(get_turf(src)) + O.name = name + O.icon_state = dead_icon ? dead_icon : icon_state + + // Pass over the blood. + reagents.trans_to(O, reagents.total_volume) + + if(fingerprints) O.fingerprints = fingerprints.Copy() + if(fingerprintshidden) O.fingerprintshidden = fingerprintshidden.Copy() + if(fingerprintslast) O.fingerprintslast = fingerprintslast + + user.put_in_active_hand(O) + del(src) \ No newline at end of file diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 64f53e5e55..e3b758e6b2 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -161,8 +161,6 @@ spawn(5) src.update() - - /obj/machinery/power/apc/proc/make_terminal() // create a terminal object at the same position as original turf loc // wires will attach to this @@ -627,15 +625,16 @@ // attack with hand - remove cell (if cover open) or interact with the APC /obj/machinery/power/apc/attack_hand(mob/user) -// if (!can_use(user)) This already gets called in interact() and in topic() -// return + if(!user) return + src.add_fingerprint(user) - //Synthetic human mob goes here. + //Human mob special interaction goes here. if(istype(user,/mob/living/carbon/human)) var/mob/living/carbon/human/H = user + if(H.species.flags & IS_SYNTHETIC && H.a_intent == "grab") if(emagged || stat & BROKEN) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread @@ -663,6 +662,28 @@ else user << "There is no charge to draw from that APC." return + else if(H.species.can_shred(H)) + user.visible_message("\red [user.name] slashes at the [src.name]!", "\blue You slash at the [src.name]!") + playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1) + var/allcut = 1 + for(var/wire in apcwirelist) + if(!isWireCut(apcwirelist[wire])) + allcut = 0 + break + if(beenhit >= pick(3, 4) && wiresexposed != 1) + wiresexposed = 1 + src.update_icon() + src.visible_message("\red The [src.name]'s cover flies open, exposing the wires!") + + else if(wiresexposed == 1 && allcut == 0) + for(var/wire in apcwirelist) + cut(apcwirelist[wire]) + src.update_icon() + src.visible_message("\red The [src.name]'s wires are shredded!") + else + beenhit += 1 + return + if(usr == user && opened && (!issilicon(user))) if(cell) @@ -683,32 +704,6 @@ //user.set_machine(src) src.interact(user) -/obj/machinery/power/apc/attack_alien(mob/living/carbon/alien/humanoid/user) - if(!user) - return - user.visible_message("\red [user.name] slashes at the [src.name]!", "\blue You slash at the [src.name]!") - playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1) - var/allcut = 1 - for(var/wire in apcwirelist) - if(!isWireCut(apcwirelist[wire])) - allcut = 0 - break - if(beenhit >= pick(3, 4) && wiresexposed != 1) - wiresexposed = 1 - src.update_icon() - src.visible_message("\red The [src.name]'s cover flies open, exposing the wires!") - - else if(wiresexposed == 1 && allcut == 0) - for(var/wire in apcwirelist) - cut(apcwirelist[wire]) - src.update_icon() - src.visible_message("\red The [src.name]'s wires are shredded!") - else - beenhit += 1 - return - - - /obj/machinery/power/apc/interact(mob/user) if(!user) return diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 067b207d13..9f82dbec05 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -454,18 +454,7 @@ src.flicker(1) return -// Aliens smash the bulb but do not get electrocuted./N -/obj/machinery/light/attack_alien(mob/living/carbon/alien/humanoid/user)//So larva don't go breaking light bulbs. - if(status == LIGHT_EMPTY||status == LIGHT_BROKEN) - user << "\green That object is useless to you." - return - else if (status == LIGHT_OK||status == LIGHT_BURNED) - for(var/mob/M in viewers(src)) - M.show_message("\red [user.name] smashed the light!", 3, "You hear a tinkle of breaking glass", 2) - broken() - return - -/obj/machinery/light/attack_animal(mob/living/simple_animal/M) +/obj/machinery/light/attack_animal(mob/living/M) if(M.melee_damage_upper == 0) return if(status == LIGHT_EMPTY||status == LIGHT_BROKEN) M << "\red That object is useless to you." @@ -486,6 +475,14 @@ user << "There is no [fitting] in this light." return + if(istype(user,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = user + if(H.species.can_shred(H)) + for(var/mob/M in viewers(src)) + M.show_message("\red [user.name] smashed the light!", 3, "You hear a tinkle of breaking glass", 2) + broken() + return + // make it burn hands if not wearing fire-insulated gloves if(on) var/prot = 0 diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index e6b49ec298..82936a1dc8 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -78,7 +78,7 @@ has_power = master_area.powered(power_channel) else has_power = powered(power_channel) - + if(has_power) stat &= ~NOPOWER else @@ -271,14 +271,17 @@ //No animations will be performed by this proc. /proc/electrocute_mob(mob/living/carbon/M as mob, var/power_source, var/obj/source, var/siemens_coeff = 1.0) if(istype(M.loc,/obj/mecha)) return 0 //feckin mechs are dumb - - //This is for performance optimization only. + + //This is for performance optimization only. //DO NOT modify siemens_coeff here. That is checked in human/electrocute_act() if(istype(M,/mob/living/carbon/human)) var/mob/living/carbon/human/H = M - if(H.gloves) + if(H.species.insulated) + return 0 + else if(H.gloves) var/obj/item/clothing/gloves/G = H.gloves - if(G.siemens_coefficient == 0) return 0 //to avoid spamming with insulated glvoes on + if(G.siemens_coefficient == 0) + return 0 //to avoid spamming with insulated glvoes on var/area/source_area if(istype(power_source,/area)) diff --git a/code/modules/projectiles/projectile/change.dm b/code/modules/projectiles/projectile/change.dm index fc88f6b519..72250fbf1a 100644 --- a/code/modules/projectiles/projectile/change.dm +++ b/code/modules/projectiles/projectile/change.dm @@ -53,11 +53,7 @@ new_mob.universal_speak = 1 if("xeno") var/alien_caste = pick("Hunter","Sentinel","Drone","Larva") - switch(alien_caste) - if("Hunter") new_mob = new /mob/living/carbon/alien/humanoid/hunter(M.loc) - if("Sentinel") new_mob = new /mob/living/carbon/alien/humanoid/sentinel(M.loc) - if("Drone") new_mob = new /mob/living/carbon/alien/humanoid/drone(M.loc) - else new_mob = new /mob/living/carbon/alien/larva(M.loc) + new_mob = create_new_xenomorph(alien_caste,M.loc) new_mob.universal_speak = 1 if("human") new_mob = new /mob/living/carbon/human(M.loc, pick(all_species)) diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm index 6501283f3c..a19c1d6a9c 100644 --- a/code/modules/reagents/Chemistry-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents.dm @@ -1,7 +1,6 @@ #define SOLID 1 #define LIQUID 2 #define GAS 3 -#define FOOD_METABOLISM 0.4 #define REAGENTS_OVERDOSE 30 #define REM REAGENTS_EFFECT_MULTIPLIER @@ -95,7 +94,7 @@ datum blood - data = new/list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null, "antibodies" = null) + data = new/list("donor"=null,"viruses"=null,"species"="Human","blood_DNA"=null,"blood_type"=null,"blood_colour"= "#A10808","resistances"=null,"trace_chem"=null, "antibodies" = null) name = "Blood" id = "blood" reagent_state = LIQUID @@ -128,49 +127,30 @@ datum var/mob/living/carbon/C = M C.antibodies |= self.data["antibodies"] + on_merge(var/data) + if(data["blood_colour"]) + color = data["blood_colour"] + return ..() - + on_update(var/atom/A) + if(data["blood_colour"]) + color = data["blood_colour"] + return ..() reaction_turf(var/turf/simulated/T, var/volume)//splash the blood all over the place if(!istype(T)) return var/datum/reagent/blood/self = src src = null if(!(volume >= 3)) return - //var/datum/disease/D = self.data["virus"] + if(!self.data["donor"] || istype(self.data["donor"], /mob/living/carbon/human)) - var/obj/effect/decal/cleanable/blood/blood_prop = locate() in T //find some blood here - if(!blood_prop) //first blood! - blood_prop = new(T) - blood_prop.blood_DNA[self.data["blood_DNA"]] = self.data["blood_type"] - - for(var/datum/disease/D in self.data["viruses"]) - var/datum/disease/newVirus = D.Copy(1) - blood_prop.viruses += newVirus - newVirus.holder = blood_prop - - if(self.data["virus2"]) - blood_prop.virus2 = virus_copylist(self.data["virus2"]) - - + blood_splatter(T,self,1) else if(istype(self.data["donor"], /mob/living/carbon/monkey)) - var/obj/effect/decal/cleanable/blood/blood_prop = locate() in T - if(!blood_prop) - blood_prop = new(T) - blood_prop.blood_DNA["Non-Human DNA"] = "A+" - for(var/datum/disease/D in self.data["viruses"]) - var/datum/disease/newVirus = D.Copy(1) - blood_prop.viruses += newVirus - newVirus.holder = blood_prop - + var/obj/effect/decal/cleanable/blood/B = blood_splatter(T,self,1) + if(B) B.blood_DNA["Non-Human DNA"] = "A+" else if(istype(self.data["donor"], /mob/living/carbon/alien)) - var/obj/effect/decal/cleanable/blood/xeno/blood_prop = locate() in T - if(!blood_prop) - blood_prop = new(T) - blood_prop.blood_DNA["UNKNOWN DNA STRUCTURE"] = "X*" - for(var/datum/disease/D in self.data["viruses"]) - var/datum/disease/newVirus = D.Copy(1) - blood_prop.viruses += newVirus - newVirus.holder = blood_prop + var/obj/effect/decal/cleanable/blood/B = blood_splatter(T,self,1) + if(B) B.blood_DNA["UNKNOWN DNA STRUCTURE"] = "X*" return /* Must check the transfering of reagents and their data first. They all can point to one disease datum. @@ -672,13 +652,17 @@ datum for (var/ID in C.virus2) var/datum/disease2/disease/V = C.virus2[ID] if(prob(5)) + M:antibodies |= V.antigen if(prob(50)) M.radiation += 50 // curing it that way may kill you instead - var/mob/living/carbon/human/H - if(istype(C,/mob/living/carbon/human)) - H = C - if(!H || (H.species && !(H.species.flags & RAD_ABSORB))) M.adjustToxLoss(100) - M:antibodies |= V.antigen + var/absorbed + if(istype(C,/mob/living/carbon)) + var/mob/living/carbon/H = C + var/datum/organ/internal/diona/nutrients/rad_organ = locate() in H.internal_organs + if(rad_organ && !rad_organ.is_broken()) + absorbed = 1 + if(!absorbed) + M.adjustToxLoss(100) ..() return @@ -1276,7 +1260,7 @@ datum if(ishuman(M)) var/mob/living/carbon/human/H = M var/datum/organ/internal/eyes/E = H.internal_organs_by_name["eyes"] - if(istype(E)) + if(E && istype(E)) if(E.damage > 0) E.damage = max(E.damage - 1, 0) ..() @@ -1512,11 +1496,11 @@ datum var/toxpwr = 0.7 // Toxins are really weak, but without being treated, last very long. custom_metabolism = 0.1 - on_mob_life(var/mob/living/M as mob) + on_mob_life(var/mob/living/M as mob,var/alien) if(!M) M = holder.my_atom if(toxpwr) M.adjustToxLoss(toxpwr*REM) - ..() + if(alien) ..() //Kind of a catch-all for aliens without kidneys. return toxin/amatoxin @@ -2991,7 +2975,7 @@ datum on_mob_life(var/mob/living/M as mob, var/alien) M:nutrition += nutriment_factor - holder.remove_reagent(src.id, FOOD_METABOLISM) + holder.remove_reagent(src.id, (alien ? FOOD_METABOLISM : ALCOHOL_METABOLISM)) // Catch-all for creatures without livers. if (adj_drowsy) M.drowsyness = max(0,M.drowsyness + adj_drowsy) if (adj_sleepy) M.sleeping = max(0,M.sleeping + adj_sleepy) @@ -3024,7 +3008,9 @@ datum if(ishuman(M)) var/mob/living/carbon/human/H = M var/datum/organ/internal/liver/L = H.internal_organs_by_name["liver"] - if (istype(L)) + if (!L) + H.adjustToxLoss(5) + else if(istype(L)) L.take_damage(0.1, 1) H.adjustToxLoss(0.1) ..() @@ -3264,13 +3250,13 @@ datum if(prob(5)) if(ishuman(M)) var/mob/living/carbon/human/H = M var/datum/organ/internal/heart/L = H.internal_organs_by_name["heart"] - if (istype(L)) + if (L && istype(L)) L.take_damage(5, 0) if (300 to INFINITY) if(ishuman(M)) var/mob/living/carbon/human/H = M var/datum/organ/internal/heart/L = H.internal_organs_by_name["heart"] - if (istype(L)) + if (L && istype(L)) L.take_damage(100, 0) holder.remove_reagent(src.id, FOOD_METABOLISM) diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm index 29001d9723..28e369f531 100644 --- a/code/modules/reagents/reagent_containers/food/snacks.dm +++ b/code/modules/reagents/reagent_containers/food/snacks.dm @@ -590,25 +590,20 @@ ..() reagents.add_reagent("nutriment", 1) -/obj/item/weapon/reagent_containers/food/snacks/appendix -//yes, this is the same as meat. I might do something different in future - name = "appendix" - desc = "An appendix which looks perfectly healthy." +/obj/item/weapon/reagent_containers/food/snacks/organ + + name = "organ" + desc = "It's good for you." icon = 'icons/obj/surgery.dmi' icon_state = "appendix" filling_color = "#E00D34" New() ..() - reagents.add_reagent("nutriment", 3) + reagents.add_reagent("nutriment", rand(3,5)) + reagents.add_reagent("toxin", rand(1,3)) src.bitesize = 3 -/obj/item/weapon/reagent_containers/food/snacks/appendix/inflamed - name = "inflamed appendix" - desc = "An appendix which appears to be inflamed." - icon_state = "appendixinflamed" - filling_color = "#E00D7A" - /obj/item/weapon/reagent_containers/food/snacks/tofu name = "Tofu" icon_state = "tofu" @@ -1559,7 +1554,6 @@ On_Consume(var/mob/M) M << "Something inside of you suddently expands!" - if (istype(M, /mob/living/carbon/human)) //Do not try to understand. var/obj/item/weapon/surprise = new/obj/item/weapon(M) diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 5e6277c8e7..5617a3802e 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -128,7 +128,7 @@ if(SYRINGE_INJECT) if(!reagents.total_volume) - user << "\red The Syringe is empty." + user << "\red The syringe is empty." return if(istype(target, /obj/item/weapon/implantcase/chem)) return diff --git a/code/modules/surgery/appendix.dm b/code/modules/surgery/appendix.dm deleted file mode 100644 index 91332eab06..0000000000 --- a/code/modules/surgery/appendix.dm +++ /dev/null @@ -1,89 +0,0 @@ -//Procedures in this file: Appendectomy -////////////////////////////////////////////////////////////////// -// APPENDECTOMY // -////////////////////////////////////////////////////////////////// - -/datum/surgery_step/appendectomy/ - priority = 2 - can_infect = 1 - blood_level = 1 - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - if (!hasorgans(target)) - return 0 - if (target_zone != "groin") - return 0 - var/datum/organ/external/groin = target.get_organ("groin") - if (!groin) - return 0 - if (groin.open < 2) - return 0 - return 1 - -/datum/surgery_step/appendectomy/cut_appendix - allowed_tools = list( - /obj/item/weapon/scalpel = 100, \ - /obj/item/weapon/kitchenknife = 75, \ - /obj/item/weapon/shard = 50, \ - ) - - min_duration = 70 - max_duration = 90 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.op_stage.appendix == 0 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] starts to separate [target]'s appendix from the abdominal wall with \the [tool].", \ - "You start to separate [target]'s appendix from the abdominal wall with \the [tool]." ) - target.custom_pain("The pain in your abdomen is living hell!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] has separated [target]'s appendix with \the [tool]." , \ - "\blue You have separated [target]'s appendix with \the [tool].") - target.op_stage.appendix = 1 - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/groin = target.get_organ("groin") - user.visible_message("\red [user]'s hand slips, slicing an artery inside [target]'s abdomen with \the [tool]!", \ - "\red Your hand slips, slicing an artery inside [target]'s abdomen with \the [tool]!") - groin.createwound(CUT, 50, 1) - -/datum/surgery_step/appendectomy/remove_appendix - allowed_tools = list( - /obj/item/weapon/hemostat = 100, \ - /obj/item/weapon/wirecutters = 75, \ - /obj/item/weapon/kitchen/utensil/fork = 20 - ) - - min_duration = 60 - max_duration = 80 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.op_stage.appendix == 1 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] starts removing [target]'s appendix with \the [tool].", \ - "You start removing [target]'s appendix with \the [tool].") - target.custom_pain("Someone's ripping out your bowels!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] has removed [target]'s appendix with \the [tool].", \ - "\blue You have removed [target]'s appendix with \the [tool].") - var/app = 0 - for(var/datum/disease/appendicitis/appendicitis in target.viruses) - app = 1 - appendicitis.cure() - target.resistances += appendicitis - if (app) - new /obj/item/weapon/reagent_containers/food/snacks/appendix/inflamed(get_turf(target)) - else - new /obj/item/weapon/reagent_containers/food/snacks/appendix(get_turf(target)) - target.op_stage.appendix = 2 - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/affected = target.get_organ(target_zone) - user.visible_message("\red [user]'s hand slips, nicking internal organs in [target]'s abdomen with \the [tool]!", \ - "\red Your hand slips, nicking internal organs in [target]'s abdomen with \the [tool]!") - affected.createwound(BRUISE, 20) diff --git a/code/modules/surgery/bones.dm b/code/modules/surgery/bones.dm index 0bc1407567..605b1503d5 100644 --- a/code/modules/surgery/bones.dm +++ b/code/modules/surgery/bones.dm @@ -18,7 +18,7 @@ if (!hasorgans(target)) return 0 var/datum/organ/external/affected = target.get_organ(target_zone) - return affected.open == 2 && affected.stage == 0 + return affected.open >= 2 && affected.stage == 0 begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) @@ -52,7 +52,7 @@ if (!hasorgans(target)) return 0 var/datum/organ/external/affected = target.get_organ(target_zone) - return affected.name != "head" && affected.open == 2 && affected.stage == 1 + return affected.name != "head" && affected.open >= 2 && affected.stage == 1 begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) @@ -91,7 +91,7 @@ if (!hasorgans(target)) return 0 var/datum/organ/external/affected = target.get_organ(target_zone) - return affected.name == "head" && affected.open == 2 && affected.stage == 1 + return affected.name == "head" && affected.open >= 2 && affected.stage == 1 begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) user.visible_message("[user] is beginning to piece together [target]'s skull with \the [tool]." , \ @@ -127,7 +127,7 @@ if (!hasorgans(target)) return 0 var/datum/organ/external/affected = target.get_organ(target_zone) - return affected.open == 2 && affected.stage == 2 + return affected.open >= 2 && affected.stage == 2 begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) diff --git a/code/modules/surgery/braincore.dm b/code/modules/surgery/braincore.dm deleted file mode 100644 index 4bc804eab5..0000000000 --- a/code/modules/surgery/braincore.dm +++ /dev/null @@ -1,279 +0,0 @@ -//Procedures in this file: Brain extraction. Brain fixing. Slime Core extraction. -////////////////////////////////////////////////////////////////// -// BRAIN SURGERY // -////////////////////////////////////////////////////////////////// - -/datum/surgery_step/brain/ - priority = 2 - blood_level = 1 - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return target_zone == "head" && hasorgans(target) - -/datum/surgery_step/brain/saw_skull - allowed_tools = list( - /obj/item/weapon/circular_saw = 100, \ - /obj/item/weapon/hatchet = 75 - ) - - min_duration = 50 - max_duration = 70 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target_zone == "head" && target.brain_op_stage == 1 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] begins to cut through [target]'s skull with \the [tool].", \ - "You begin to cut through [target]'s skull with \the [tool].") - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] has cut [target]'s skull open with \the [tool].", \ - "\blue You have cut [target]'s skull open with \the [tool].") - target.brain_op_stage = 2 - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, cracking [target]'s skull with \the [tool]!" , \ - "\red Your hand slips, cracking [target]'s skull with \the [tool]!" ) - target.apply_damage(max(10, tool.force), BRUTE, "head") - -/datum/surgery_step/brain/cut_brain - allowed_tools = list( - /obj/item/weapon/scalpel = 100, \ - /obj/item/weapon/kitchenknife = 75, \ - /obj/item/weapon/shard = 50, \ - ) - - min_duration = 80 - max_duration = 100 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.brain_op_stage == 2 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] starts separating connections to [target]'s brain with \the [tool].", \ - "You start separating connections to [target]'s brain with \the [tool].") - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] separates connections to [target]'s brain with \the [tool].", \ - "\blue You separate connections to [target]'s brain with \the [tool].") - target.brain_op_stage = 3 - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, cutting a vein in [target]'s brain with \the [tool]!", \ - "\red Your hand slips, cutting a vein in [target]'s brain with \the [tool]!") - target.apply_damage(50, BRUTE, "head", 1, sharp=1) - -/datum/surgery_step/brain/saw_spine - allowed_tools = list( - /obj/item/weapon/circular_saw = 100, \ - /obj/item/weapon/hatchet = 75 - ) - - min_duration = 50 - max_duration = 70 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.brain_op_stage == 3 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] starts separating [target]'s brain from \his spine with \the [tool].", \ - "You start separating [target]'s brain from spine with \the [tool].") - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] separates [target]'s brain from \his spine with \the [tool].", \ - "\blue You separate [target]'s brain from spine with \the [tool].") - - var/mob/living/simple_animal/borer/borer = target.has_brain_worms() - - if(borer) - borer.detatch() //Should remove borer if the brain is removed - RR - - user.attack_log += "\[[time_stamp()]\] Debrained [target.name] ([target.ckey]) with [tool.name] (INTENT: [uppertext(user.a_intent)])" - target.attack_log += "\[[time_stamp()]\] Debrained by [user.name] ([user.ckey]) with [tool.name] (INTENT: [uppertext(user.a_intent)])" - msg_admin_attack("[user.name] ([user.ckey]) debrained [target.name] ([target.ckey]) with [tool.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") - - var/mob/living/carbon/human/H - if(istype(target,/mob/living/carbon/human)) - H = target - - var/obj/item/brain/B - if(H && H.species && H.species.flags & IS_SYNTHETIC) - var/obj/item/device/mmi/posibrain/P = new(target.loc) - P.transfer_identity(target) - else - B = new(target.loc) - B.transfer_identity(target) - - target.internal_organs -= B - target.internal_organs_by_name -= "brain" - - target:brain_op_stage = 4.0 - target.death()//You want them to die after the brain was transferred, so not to trigger client death() twice. - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, cutting a vein in [target]'s brain with \the [tool]!", \ - "\red Your hand slips, cutting a vein in [target]'s brain with \the [tool]!") - target.apply_damage(30, BRUTE, "head", 1, sharp=1) - if (ishuman(user)) - user:bloody_body(target) - user:bloody_hands(target, 0) - - -////////////////////////////////////////////////////////////////// -// BRAIN DAMAGE FIXING // -////////////////////////////////////////////////////////////////// - -/datum/surgery_step/brain/bone_chips - allowed_tools = list( - /obj/item/weapon/hemostat = 100, \ - /obj/item/weapon/wirecutters = 75, \ - /obj/item/weapon/kitchen/utensil/fork = 20 - ) - - min_duration = 80 - max_duration = 100 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.brain_op_stage == 2 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] starts taking bone chips out of [target]'s brain with \the [tool].", \ - "You start taking bone chips out of [target]'s brain with \the [tool].") - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] takes out all the bone chips in [target]'s brain with \the [tool].", \ - "\blue You take out all the bone chips in [target]'s brain with \the [tool].") - target.brain_op_stage = 3 - - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, jabbing \the [tool] in [target]'s brain!", \ - "\red Your hand slips, jabbing \the [tool] in [target]'s brain!") - target.apply_damage(30, BRUTE, "head", 1, sharp=1) - -/datum/surgery_step/brain/hematoma - allowed_tools = list( - /obj/item/weapon/FixOVein = 100, \ - /obj/item/stack/cable_coil = 75 - ) - - min_duration = 90 - max_duration = 110 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.brain_op_stage == 3 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] starts mending hematoma in [target]'s brain with \the [tool].", \ - "You start mending hematoma in [target]'s brain with \the [tool].") - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] mends hematoma in [target]'s brain with \the [tool].", \ - "\blue You mend hematoma in [target]'s brain with \the [tool].") - var/datum/organ/internal/brain/sponge = target.internal_organs_by_name["brain"] - if (sponge) - sponge.damage = 0 - - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, bruising [target]'s brain with \the [tool]!", \ - "\red Your hand slips, bruising [target]'s brain with \the [tool]!") - target.apply_damage(20, BRUTE, "head", 1, sharp=1) - -////////////////////////////////////////////////////////////////// -// SLIME CORE EXTRACTION // -////////////////////////////////////////////////////////////////// - -/datum/surgery_step/slime - is_valid_target(mob/living/carbon/slime/target) - return istype(target, /mob/living/carbon/slime/) - - can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - return target.stat == 2 - -/datum/surgery_step/slime/cut_flesh - allowed_tools = list( - /obj/item/weapon/scalpel = 100, \ - /obj/item/weapon/kitchenknife = 75, \ - /obj/item/weapon/shard = 50, \ - ) - - min_duration = 30 - max_duration = 50 - - can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - return ..() && target.brain_op_stage == 0 - - begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message("[user] starts cutting through [target]'s flesh with \the [tool].", \ - "You start cutting through [target]'s flesh with \the [tool].") - - end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] cuts through [target]'s flesh with \the [tool].", \ - "\blue You cut through [target]'s flesh with \the [tool], revealing its silky innards.") - target.brain_op_stage = 1 - - fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, tearing [target]'s flesh with \the [tool]!", \ - "\red Your hand slips, tearing [target]'s flesh with \the [tool]!") - -/datum/surgery_step/slime/cut_innards - allowed_tools = list( - /obj/item/weapon/scalpel = 100, \ - /obj/item/weapon/kitchenknife = 75, \ - /obj/item/weapon/shard = 50, \ - ) - - min_duration = 30 - max_duration = 50 - - can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - return ..() && target.brain_op_stage == 1 - - begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message("[user] starts cutting [target]'s silky innards apart with \the [tool].", \ - "You start cutting [target]'s silky innards apart with \the [tool].") - - end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] cuts [target]'s innards apart with \the [tool], exposing the cores.", \ - "\blue You cut [target]'s innards apart with \the [tool], exposing the cores.") - target.brain_op_stage = 2 - - fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, tearing [target]'s innards with \the [tool]!", \ - "\red Your hand slips, tearing [target]'s innards with \the [tool]!") - -/datum/surgery_step/slime/saw_core - allowed_tools = list( - /obj/item/weapon/circular_saw = 100, \ - /obj/item/weapon/hatchet = 75 - ) - - min_duration = 50 - max_duration = 70 - - can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - return ..() && target.brain_op_stage == 2 && target.cores > 0 - - begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message("[user] starts cutting out one of [target]'s cores with \the [tool].", \ - "You start cutting out one of [target]'s cores with \the [tool].") - - end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - target.cores-- - user.visible_message("\blue [user] cuts out one of [target]'s cores with \the [tool].",, \ - "\blue You cut out one of [target]'s cores with \the [tool]. [target.cores] cores left.") - - if(target.cores >= 0) - new target.coretype(target.loc) - if(target.cores <= 0) - target.icon_state = "[target.colour] baby slime dead-nocore" - - - fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, causing \him to miss the core!", \ - "\red Your hand slips, causing you to miss the core!") \ No newline at end of file diff --git a/code/modules/surgery/brainrepair.dm b/code/modules/surgery/brainrepair.dm new file mode 100644 index 0000000000..85b5dd8dd3 --- /dev/null +++ b/code/modules/surgery/brainrepair.dm @@ -0,0 +1,68 @@ +////////////////////////////////////////////////////////////////// +// BRAIN DAMAGE FIXING // +////////////////////////////////////////////////////////////////// + +/datum/surgery_step/brain/bone_chips + allowed_tools = list( + /obj/item/weapon/hemostat = 100, \ + /obj/item/weapon/wirecutters = 75, \ + /obj/item/weapon/kitchen/utensil/fork = 20 + ) + + priority = 3 + min_duration = 80 + max_duration = 100 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/internal/brain/sponge = target.internal_organs_by_name["brain"] + return (sponge && sponge.damage > 0 && sponge.damage <= 20) && affected.open == 3 + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("[user] starts taking bone chips out of [target]'s brain with \the [tool].", \ + "You start taking bone chips out of [target]'s brain with \the [tool].") + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\blue [user] takes out all the bone chips in [target]'s brain with \the [tool].", \ + "\blue You take out all the bone chips in [target]'s brain with \the [tool].") + var/datum/organ/internal/brain/sponge = target.internal_organs_by_name["brain"] + if (sponge) + sponge.damage = 0 + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\red [user]'s hand slips, jabbing \the [tool] in [target]'s brain!", \ + "\red Your hand slips, jabbing \the [tool] in [target]'s brain!") + target.apply_damage(30, BRUTE, "head", 1, sharp=1) + +/datum/surgery_step/brain/hematoma + allowed_tools = list( + /obj/item/weapon/FixOVein = 100, \ + /obj/item/stack/cable_coil = 75 + ) + + priority = 3 + min_duration = 90 + max_duration = 110 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/internal/brain/sponge = target.internal_organs_by_name["brain"] + return (sponge && sponge.damage > 20) && affected.open == 3 + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("[user] starts mending hematoma in [target]'s brain with \the [tool].", \ + "You start mending hematoma in [target]'s brain with \the [tool].") + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\blue [user] mends hematoma in [target]'s brain with \the [tool].", \ + "\blue You mend hematoma in [target]'s brain with \the [tool].") + var/datum/organ/internal/brain/sponge = target.internal_organs_by_name["brain"] + if (sponge) + sponge.damage = 20 + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\red [user]'s hand slips, bruising [target]'s brain with \the [tool]!", \ + "\red Your hand slips, bruising [target]'s brain with \the [tool]!") + target.apply_damage(20, BRUTE, "head", 1, sharp=1) \ No newline at end of file diff --git a/code/modules/surgery/encased.dm b/code/modules/surgery/encased.dm new file mode 100644 index 0000000000..dcd6cc4b31 --- /dev/null +++ b/code/modules/surgery/encased.dm @@ -0,0 +1,220 @@ +//Procedures in this file: Generic ribcage opening steps, Removing alien embryo, Fixing internal organs. +////////////////////////////////////////////////////////////////// +// GENERIC RIBCAGE SURGERY // +////////////////////////////////////////////////////////////////// +/datum/surgery_step/open_encased + priority = 2 + can_infect = 1 + blood_level = 1 + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return 0 + + var/datum/organ/external/affected = target.get_organ(target_zone) + return affected.encased && affected.open >= 2 + + +/datum/surgery_step/open_encased/saw + allowed_tools = list( + /obj/item/weapon/circular_saw = 100, \ + /obj/item/weapon/hatchet = 75 + ) + + min_duration = 50 + max_duration = 70 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + return ..() && affected.open == 2 + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + user.visible_message("[user] begins to cut through [target]'s [affected.encased] with \the [tool].", \ + "You begin to cut through [target]'s [affected.encased] with \the [tool].") + target.custom_pain("Something hurts horribly in your [affected.display_name]!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + user.visible_message("\blue [user] has cut [target]'s [affected.encased] open with \the [tool].", \ + "\blue You have cut [target]'s [affected.encased] open with \the [tool].") + affected.open = 2.5 + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + user.visible_message("\red [user]'s hand slips, cracking [target]'s [affected.encased] with \the [tool]!" , \ + "\red Your hand slips, cracking [target]'s [affected.encased] with \the [tool]!" ) + + affected.createwound(CUT, 20) + affected.fracture() + + +/datum/surgery_step/open_encased/retract + allowed_tools = list( + /obj/item/weapon/retractor = 100, \ + /obj/item/weapon/crowbar = 75, \ + /obj/item/weapon/kitchen/utensil/fork = 20 + ) + + min_duration = 30 + max_duration = 40 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + return ..() && affected.open == 2.5 + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/msg = "[user] starts to force open the [affected.encased] in [target]'s [affected.display_name] with \the [tool]." + var/self_msg = "You start to force open the [affected.encased] in [target]'s [affected.display_name] with \the [tool]." + user.visible_message(msg, self_msg) + target.custom_pain("Something hurts horribly in your [affected.display_name]!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/msg = "\blue [user] forces open [target]'s [affected.encased] with \the [tool]." + var/self_msg = "\blue You force open [target]'s [affected.encased] with \the [tool]." + user.visible_message(msg, self_msg) + + affected.open = 3 + + // Whoops! + if(prob(10)) + affected.fracture() + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/msg = "\red [user]'s hand slips, cracking [target]'s [affected.encased]!" + var/self_msg = "\red Your hand slips, cracking [target]'s [affected.encased]!" + user.visible_message(msg, self_msg) + + affected.createwound(BRUISE, 20) + affected.fracture() + +/datum/surgery_step/open_encased/close + allowed_tools = list( + /obj/item/weapon/retractor = 100, \ + /obj/item/weapon/crowbar = 75, \ + /obj/item/weapon/kitchen/utensil/fork = 20 + ) + + min_duration = 20 + max_duration = 40 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + return ..() && affected.open == 3 + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/msg = "[user] starts bending [target]'s [affected.encased] back into place with \the [tool]." + var/self_msg = "You start bending [target]'s [affected.encased] back into place with \the [tool]." + user.visible_message(msg, self_msg) + target.custom_pain("Something hurts horribly in your [affected.display_name]!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/msg = "\blue [user] bends [target]'s [affected.encased] back into place with \the [tool]." + var/self_msg = "\blue You bend [target]'s [affected.encased] back into place with \the [tool]." + user.visible_message(msg, self_msg) + + affected.open = 2.5 + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/msg = "\red [user]'s hand slips, bending [target]'s [affected.encased] the wrong way!" + var/self_msg = "\red Your hand slips, bending [target]'s [affected.encased] the wrong way!" + user.visible_message(msg, self_msg) + + affected.createwound(BRUISE, 20) + affected.fracture() + + /*if (prob(40)) //TODO: ORGAN REMOVAL UPDATE. + user.visible_message("\red A rib pierces the lung!") + target.rupture_lung()*/ + +/datum/surgery_step/open_encased/mend + allowed_tools = list( + /obj/item/weapon/bonegel = 100, \ + /obj/item/weapon/screwdriver = 75 + ) + + min_duration = 20 + max_duration = 40 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + return ..() && affected.open == 2.5 + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/msg = "[user] starts applying \the [tool] to [target]'s [affected.encased]." + var/self_msg = "You start applying \the [tool] to [target]'s [affected.encased]." + user.visible_message(msg, self_msg) + target.custom_pain("Something hurts horribly in your [affected.display_name]!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/msg = "\blue [user] applied \the [tool] to [target]'s [affected.encased]." + var/self_msg = "\blue You applied \the [tool] to [target]'s [affected.encased]." + user.visible_message(msg, self_msg) + + affected.open = 2 \ No newline at end of file diff --git a/code/modules/surgery/eye.dm b/code/modules/surgery/eye.dm index d142b8ef67..0fa9f4863a 100644 --- a/code/modules/surgery/eye.dm +++ b/code/modules/surgery/eye.dm @@ -12,7 +12,10 @@ var/datum/organ/external/affected = target.get_organ(target_zone) if (!affected) return 0 - return target_zone == "eyes" + + var/datum/organ/internal/eyes = target.internal_organs_by_name["eyes"] + + return target_zone == "eyes" && eyes /datum/surgery_step/eye/cut_open allowed_tools = list( diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm index 94c7b2b861..a05c6f120b 100644 --- a/code/modules/surgery/generic.dm +++ b/code/modules/surgery/generic.dm @@ -56,8 +56,6 @@ affected.createwound(CUT, 1) affected.clamp() spread_germs_to_organ(affected, user) - if (target_zone == "head") - target.brain_op_stage = 1 fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) @@ -95,8 +93,6 @@ affected.createwound(CUT, 1) affected.clamp() affected.open = 2 - if (target_zone == "head") - target.brain_op_stage = 1 fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) @@ -134,8 +130,6 @@ affected.open = 1 affected.status |= ORGAN_BLEEDING affected.createwound(CUT, 1) - if (target_zone == "head") - target.brain_op_stage = 1 fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) @@ -191,7 +185,7 @@ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if(..()) var/datum/organ/external/affected = target.get_organ(target_zone) - return affected.open == 1 && !(affected.status & ORGAN_BLEEDING) + return affected.open == 1 //&& !(affected.status & ORGAN_BLEEDING) begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) diff --git a/code/modules/surgery/implant.dm b/code/modules/surgery/implant.dm index 57df6a398c..7e2fbc776e 100644 --- a/code/modules/surgery/implant.dm +++ b/code/modules/surgery/implant.dm @@ -10,7 +10,7 @@ if(!hasorgans(target)) return 0 var/datum/organ/external/affected = target.get_organ(target_zone) - return affected.open == 2 && !(affected.status & ORGAN_BLEEDING) && (target_zone != "chest" || target.op_stage.ribcage == 2) + return affected.open == (affected.encased ? 3 : 2) && !(affected.status & ORGAN_BLEEDING) proc/get_max_wclass(datum/organ/external/affected) switch (affected.name) @@ -156,6 +156,10 @@ min_duration = 80 max_duration = 100 + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/internal/brain/sponge = target.internal_organs_by_name["brain"] + return ..() && (!sponge || !sponge.damage) + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user] starts poking around inside the incision on [target]'s [affected.display_name] with \the [tool].", \ diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm new file mode 100644 index 0000000000..1d8fa06e53 --- /dev/null +++ b/code/modules/surgery/organs_internal.dm @@ -0,0 +1,500 @@ +// Internal surgeries. +/datum/surgery_step/internal + priority = 2 + can_infect = 1 + blood_level = 1 + +/datum/surgery_step/internal/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return 0 + + var/datum/organ/external/affected = target.get_organ(target_zone) + return affected.open == (affected.encased ? 3 : 2) + +////////////////////////////////////////////////////////////////// +// ALIEN EMBRYO SURGERY // +////////////////////////////////////////////////////////////////// +/datum/surgery_step/internal/remove_embryo + allowed_tools = list( + /obj/item/weapon/hemostat = 100, \ + /obj/item/weapon/wirecutters = 75, \ + /obj/item/weapon/kitchen/utensil/fork = 20 + ) + blood_level = 2 + + min_duration = 80 + max_duration = 100 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/embryo = 0 + for(var/obj/item/alien_embryo/A in target) + embryo = 1 + break + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + return ..() && embryo && affected.open == 3 && target_zone == "chest" + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/msg = "[user] starts to pull something out from [target]'s ribcage with \the [tool]." + var/self_msg = "You start to pull something out from [target]'s ribcage with \the [tool]." + user.visible_message(msg, self_msg) + target.custom_pain("Something hurts horribly in your chest!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\red [user] rips the larva out of [target]'s ribcage!", + "You rip the larva out of [target]'s ribcage!") + + for(var/obj/item/alien_embryo/A in target) + A.loc = A.loc.loc + + +////////////////////////////////////////////////////////////////// +// CHEST INTERNAL ORGAN SURGERY // +////////////////////////////////////////////////////////////////// +/datum/surgery_step/internal/fix_organ + allowed_tools = list( + /obj/item/stack/medical/advanced/bruise_pack= 100, \ + /obj/item/stack/medical/bruise_pack = 20, \ + /obj/item/stack/medical/bruise_pack/tajaran = 70, \ + ) + + min_duration = 70 + max_duration = 90 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/is_organ_damaged = 0 + for(var/datum/organ/internal/I in affected.internal_organs) + if(I.damage > 0) + is_organ_damaged = 1 + break + return ..() && is_organ_damaged + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/tool_name = "\the [tool]" + if (istype(tool, /obj/item/stack/medical/advanced/bruise_pack)) + tool_name = "regenerative membrane" + if (istype(tool, /obj/item/stack/medical/bruise_pack)) + if (istype(tool, /obj/item/stack/medical/bruise_pack/tajaran)) + tool_name = "the poultice" + else + tool_name = "the bandaid" + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + for(var/datum/organ/internal/I in affected.internal_organs) + if(I && I.damage > 0) + if(I.robotic < 2) + user.visible_message("[user] starts treating damage to [target]'s [I.name] with [tool_name].", \ + "You start treating damage to [target]'s [I.name] with [tool_name]." ) + + target.custom_pain("The pain in your [affected.display_name] is living hell!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/tool_name = "\the [tool]" + if (istype(tool, /obj/item/stack/medical/advanced/bruise_pack)) + tool_name = "regenerative membrane" + if (istype(tool, /obj/item/stack/medical/bruise_pack)) + if (istype(tool, /obj/item/stack/medical/bruise_pack/tajaran)) + tool_name = "the poultice" + else + tool_name = "the bandaid" + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + for(var/datum/organ/internal/I in affected.internal_organs) + if(I && I.damage > 0) + if(I.robotic < 2) + user.visible_message("\blue [user] treats damage to [target]'s [I.name] with [tool_name].", \ + "\blue You treat damage to [target]'s [I.name] with [tool_name]." ) + I.damage = 0 + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + user.visible_message("\red [user]'s hand slips, getting mess and tearing the inside of [target]'s [affected.display_name] with \the [tool]!", \ + "\red Your hand slips, getting mess and tearing the inside of [target]'s [affected.display_name] with \the [tool]!") + var/dam_amt = 2 + + if (istype(tool, /obj/item/stack/medical/advanced/bruise_pack)) + target.adjustToxLoss(5) + + else if (istype(tool, /obj/item/stack/medical/bruise_pack)) + if (istype(tool, /obj/item/stack/medical/bruise_pack/tajaran)) + target.adjustToxLoss(7) + else + dam_amt = 5 + target.adjustToxLoss(10) + affected.createwound(CUT, 5) + + for(var/datum/organ/internal/I in affected.internal_organs) + if(I && I.damage > 0) + I.take_damage(dam_amt,0) + +/datum/surgery_step/internal/fix_organ_robotic //For artificial organs + allowed_tools = list( + /obj/item/stack/nanopaste = 100, \ + /obj/item/weapon/bonegel = 30, \ + /obj/item/weapon/screwdriver = 70, \ + ) + + min_duration = 70 + max_duration = 90 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/is_organ_damaged = 0 + for(var/datum/organ/internal/I in affected.internal_organs) + if(I.damage > 0 && I.robotic >= 2) + is_organ_damaged = 1 + break + return ..() && is_organ_damaged + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + for(var/datum/organ/internal/I in affected.internal_organs) + if(I && I.damage > 0) + if(I.robotic >= 2) + user.visible_message("[user] starts mending the damage to [target]'s [I.name]'s mechanisms.", \ + "You start mending the damage to [target]'s [I.name]'s mechanisms." ) + + target.custom_pain("The pain in your [affected.display_name] is living hell!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + for(var/datum/organ/internal/I in affected.internal_organs) + + if(I && I.damage > 0) + if(I.robotic >= 2) + user.visible_message("\blue [user] repairs [target]'s [I.name] with [tool].", \ + "\blue You repair [target]'s [I.name] with [tool]." ) + I.damage = 0 + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!hasorgans(target)) + return + var/datum/organ/external/affected = target.get_organ(target_zone) + + user.visible_message("\red [user]'s hand slips, gumming up the mechanisms inside of [target]'s [affected.display_name] with \the [tool]!", \ + "\red Your hand slips, gumming up the mechanisms inside of [target]'s [affected.display_name] with \the [tool]!") + + target.adjustToxLoss(5) + affected.createwound(CUT, 5) + + for(var/datum/organ/internal/I in affected.internal_organs) + if(I) + I.take_damage(rand(3,5),0) + + +/datum/surgery_step/internal/detatch_organ + + allowed_tools = list( + /obj/item/weapon/scalpel = 100, \ + /obj/item/weapon/kitchenknife = 75, \ + /obj/item/weapon/shard = 50, \ + ) + + min_duration = 90 + max_duration = 110 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!..()) + return 0 + + target.op_stage.current_organ = null + + var/list/attached_organs = list() + for(var/organ in target.internal_organs_by_name) + var/datum/organ/internal/I = target.internal_organs_by_name[organ] + if(!I.status && I.parent_organ == target_zone) + attached_organs |= organ + + var/organ_to_remove = input(user, "Which organ do you want to prepare for removal?") as null|anything in attached_organs + if(!organ_to_remove) + return 0 + + target.op_stage.current_organ = organ_to_remove + + return ..() && organ_to_remove + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + var/datum/organ/external/affected = target.get_organ(target_zone) + + user.visible_message("[user] starts to separate [target]'s [target.op_stage.current_organ] with \the [tool].", \ + "You start to separate [target]'s [target.op_stage.current_organ] with \the [tool]." ) + target.custom_pain("The pain in your [affected.display_name] is living hell!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\blue [user] has separated [target]'s [target.op_stage.current_organ] with \the [tool]." , \ + "\blue You have separated [target]'s [target.op_stage.current_organ] with \the [tool].") + + var/datum/organ/internal/I = target.internal_organs_by_name[target.op_stage.current_organ] + if(I && istype(I)) + I.status |= ORGAN_CUT_AWAY + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + user.visible_message("\red [user]'s hand slips, slicing an artery inside [target]'s [affected.display_name] with \the [tool]!", \ + "\red Your hand slips, slicing an artery inside [target]'s [affected.display_name] with \the [tool]!") + affected.createwound(CUT, rand(30,50), 1) + +/datum/surgery_step/internal/remove_organ + + allowed_tools = list( + /obj/item/weapon/hemostat = 100, \ + /obj/item/weapon/wirecutters = 75, \ + /obj/item/weapon/kitchen/utensil/fork = 20 + ) + + min_duration = 60 + max_duration = 80 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!..()) + return 0 + + target.op_stage.current_organ = null + + var/list/removable_organs = list() + for(var/organ in target.internal_organs_by_name) + var/datum/organ/internal/I = target.internal_organs_by_name[organ] + if(I.status & ORGAN_CUT_AWAY && I.parent_organ == target_zone) + removable_organs |= organ + + var/organ_to_remove = input(user, "Which organ do you want to remove?") as null|anything in removable_organs + if(!organ_to_remove) + return 0 + + target.op_stage.current_organ = organ_to_remove + return ..() + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("[user] starts removing [target]'s [target.op_stage.current_organ] with \the [tool].", \ + "You start removing [target]'s [target.op_stage.current_organ] with \the [tool].") + target.custom_pain("Someone's ripping out your [target.op_stage.current_organ]!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\blue [user] has removed [target]'s [target.op_stage.current_organ] with \the [tool].", \ + "\blue You have removed [target]'s [target.op_stage.current_organ] with \the [tool].") + + // Extract the organ! + if(target.op_stage.current_organ) + + var/datum/organ/external/affected = target.get_organ(target_zone) + var/datum/organ/internal/I = target.internal_organs_by_name[target.op_stage.current_organ] + + var/obj/item/organ/O + if(I && istype(I)) + O = I.remove(user) + if(O && istype(O)) + + // Stop the organ from continuing to reject. + O.organ_data.rejecting = null + + // Transfer over some blood data, if the organ doesn't have data. + var/datum/reagent/blood/organ_blood = O.reagents.reagent_list["blood"] + if(!organ_blood || !organ_blood.data["blood_DNA"]) + target.vessel.trans_to(O, 5, 1, 1) + + // Kinda redundant, but I'm getting some buggy behavior. + target.internal_organs_by_name[target.op_stage.current_organ] = null + target.internal_organs_by_name -= target.op_stage.current_organ + target.internal_organs -= O.organ_data + affected.internal_organs -= O.organ_data + O.removed(target,user) + + target.op_stage.current_organ = null + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + user.visible_message("\red [user]'s hand slips, damaging the flesh in [target]'s [affected.display_name] with \the [tool]!", \ + "\red Your hand slips, damaging the flesh in [target]'s [affected.display_name] with \the [tool]!") + affected.createwound(BRUISE, 20) + +/datum/surgery_step/internal/replace_organ + allowed_tools = list( + /obj/item/organ = 100 + ) + + min_duration = 60 + max_duration = 80 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + var/obj/item/organ/O = tool + var/datum/organ/external/affected = target.get_organ(target_zone) + + var/organ_compatible + var/organ_missing + + if(!istype(O)) + return 0 + + if(target.species && target.species.has_organ[O.organ_tag]) + + if(!O.health) + user << "\red \The [O.organ_tag] is dead." + return 0 + + if(!target.internal_organs_by_name[O.organ_tag]) + organ_missing = 1 + else + user << "\red \The [target] already has a [O.organ_tag]." //TODO: grammar. + return 0 + + if(O.organ_data && affected.name == O.organ_data.parent_organ) + organ_compatible = 1 + else + user << "\red \The [O.organ_tag] doesn't normally go in \the [affected.display_name]." + return 0 + else + user << "\red \A [target.species.name] doesn't normally have a [O.organ_tag]." //TODO: grammar. + return 0 + + return ..() && organ_missing && organ_compatible + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + user.visible_message("[user] starts transplanting \the [tool] into [target]'s [affected.display_name].", \ + "You start transplanting \the [tool] into [target]'s [affected.display_name].") + target.custom_pain("Someone's rooting around in your [affected.display_name]!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + user.visible_message("\blue [user] has transplanted \the [tool] into [target]'s [affected.display_name].", \ + "\blue You have transplanted \the [tool] into [target]'s [affected.display_name].") + user.drop_item(tool) + var/obj/item/organ/O = tool + + if(istype(O)) + + var/datum/reagent/blood/transplant_blood = O.reagents.reagent_list["blood"] + if(!transplant_blood) + O.organ_data.transplant_data = list() + O.organ_data.transplant_data["species"] = target.species.name + O.organ_data.transplant_data["blood_type"] = target.dna.b_type + O.organ_data.transplant_data["blood_DNA"] = target.dna.unique_enzymes + else + O.organ_data.transplant_data = list() + O.organ_data.transplant_data["species"] = transplant_blood.data["species"] + O.organ_data.transplant_data["blood_type"] = transplant_blood.data["blood_type"] + O.organ_data.transplant_data["blood_DNA"] = transplant_blood.data["blood_DNA"] + + O.organ_data.organ_holder = null + O.organ_data.owner = target + target.internal_organs |= O.organ_data + affected.internal_organs |= O.organ_data + target.internal_organs_by_name[O.organ_tag] = O.organ_data + O.organ_data.status |= ORGAN_CUT_AWAY + O.replaced(target) + + del(O) + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\red [user]'s hand slips, damaging \the [tool]!", \ + "\red Your hand slips, damaging \the [tool]!") + var/obj/item/organ/I = tool + if(istype(I)) + I.organ_data.take_damage(rand(3,5),0) + +/datum/surgery_step/internal/attach_organ + allowed_tools = list( + /obj/item/weapon/FixOVein = 100, \ + /obj/item/stack/cable_coil = 75 + ) + + min_duration = 100 + max_duration = 120 + + can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + + if (!..()) + return 0 + + target.op_stage.current_organ = null + + var/list/removable_organs = list() + for(var/organ in target.internal_organs_by_name) + var/datum/organ/internal/I = target.internal_organs_by_name[organ] + if(I.status & ORGAN_CUT_AWAY && I.parent_organ == target_zone) + removable_organs |= organ + + var/organ_to_replace = input(user, "Which organ do you want to reattach?") as null|anything in removable_organs + if(!organ_to_replace) + return 0 + + target.op_stage.current_organ = organ_to_replace + return ..() + + begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("[user] begins reattaching [target]'s [target.op_stage.current_organ] with \the [tool].", \ + "You start reattaching [target]'s [target.op_stage.current_organ] with \the [tool].") + target.custom_pain("Someone's digging needles into your [target.op_stage.current_organ]!",1) + ..() + + end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + user.visible_message("\blue [user] has reattached [target]'s [target.op_stage.current_organ] with \the [tool]." , \ + "\blue You have reattached [target]'s [target.op_stage.current_organ] with \the [tool].") + + var/datum/organ/internal/I = target.internal_organs_by_name[target.op_stage.current_organ] + if(I && istype(I)) + I.status &= ~ORGAN_CUT_AWAY + + fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) + var/datum/organ/external/affected = target.get_organ(target_zone) + user.visible_message("\red [user]'s hand slips, damaging the flesh in [target]'s [affected.display_name] with \the [tool]!", \ + "\red Your hand slips, damaging the flesh in [target]'s [affected.display_name] with \the [tool]!") + affected.createwound(BRUISE, 20) + +////////////////////////////////////////////////////////////////// +// HEART SURGERY // +////////////////////////////////////////////////////////////////// +// To be finished after some tests. +// /datum/surgery_step/ribcage/heart/cut +// allowed_tools = list( +// /obj/item/weapon/scalpel = 100, \ +// /obj/item/weapon/kitchenknife = 75, \ +// /obj/item/weapon/shard = 50, \ +// ) + +// min_duration = 30 +// max_duration = 40 + +// can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) +// return ..() && target.op_stage.ribcage == 2 \ No newline at end of file diff --git a/code/modules/surgery/other.dm b/code/modules/surgery/other.dm index 67f3cb82de..ccd9d388e2 100644 --- a/code/modules/surgery/other.dm +++ b/code/modules/surgery/other.dm @@ -27,7 +27,7 @@ internal_bleeding = 1 break - return affected.open == 2 && internal_bleeding + return affected.open >= 2 && internal_bleeding begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) @@ -59,7 +59,7 @@ /obj/item/weapon/kitchenknife = 75, \ /obj/item/weapon/shard = 50, \ ) - + can_infect = 1 blood_level = 1 @@ -72,10 +72,10 @@ if (target_zone == "mouth" || target_zone == "eyes") return 0 - + var/datum/organ/external/affected = target.get_organ(target_zone) - return affected.open == 2 && (affected.status & ORGAN_DEAD) + return affected.open >= 2 && (affected.status & ORGAN_DEAD) begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) @@ -105,7 +105,7 @@ /obj/item/weapon/reagent_containers/spray = 50, /obj/item/weapon/reagent_containers/glass/bucket = 50, ) - + can_infect = 0 blood_level = 0 @@ -115,7 +115,7 @@ can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) if (!istype(tool, /obj/item/weapon/reagent_containers)) return 0 - + var/obj/item/weapon/reagent_containers/container = tool if(!container.reagents.has_reagent("peridaxon")) return 0 @@ -125,7 +125,7 @@ if (target_zone == "mouth" || target_zone == "eyes") return 0 - + var/datum/organ/external/affected = target.get_organ(target_zone) return affected.open == 3 && (affected.status & ORGAN_DEAD) @@ -138,34 +138,34 @@ end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) - + if (!istype(tool, /obj/item/weapon/reagent_containers)) return - + var/obj/item/weapon/reagent_containers/container = tool - + var/trans = container.reagents.trans_to(target, container.amount_per_transfer_from_this) if (trans > 0) container.reagents.reaction(target, INGEST) //technically it's contact, but the reagents are being applied to internal tissue - + if(container.reagents.has_reagent("peridaxon")) affected.status &= ~ORGAN_DEAD - + user.visible_message("\blue [user] applies [trans] units of the solution to affected tissue in [target]'s [affected.display_name]", \ "\blue You apply [trans] units of the solution to affected tissue in [target]'s [affected.display_name] with \the [tool].") fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/datum/organ/external/affected = target.get_organ(target_zone) - + if (!istype(tool, /obj/item/weapon/reagent_containers)) return - + var/obj/item/weapon/reagent_containers/container = tool - + var/trans = container.reagents.trans_to(target, container.amount_per_transfer_from_this) container.reagents.reaction(target, INGEST) //technically it's contact, but the reagents are being applied to internal tissue - + user.visible_message("\red [user]'s hand slips, applying [trans] units of the solution to the wrong place in [target]'s [affected.display_name] with the [tool]!" , \ "\red Your hand slips, applying [trans] units of the solution to the wrong place in [target]'s [affected.display_name] with the [tool]!") - + //no damage or anything, just wastes medicine diff --git a/code/modules/surgery/ribcage.dm b/code/modules/surgery/ribcage.dm deleted file mode 100644 index c14d065cd9..0000000000 --- a/code/modules/surgery/ribcage.dm +++ /dev/null @@ -1,335 +0,0 @@ -//Procedures in this file: Generic ribcage opening steps, Removing alien embryo, Fixing internal organs. -////////////////////////////////////////////////////////////////// -// GENERIC RIBCAGE SURGERY // -////////////////////////////////////////////////////////////////// -/datum/surgery_step/ribcage - priority = 2 - can_infect = 1 - blood_level = 1 - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return target_zone == "chest" - -/datum/surgery_step/ribcage/saw_ribcage - allowed_tools = list( - /obj/item/weapon/circular_saw = 100, \ - /obj/item/weapon/hatchet = 75 - ) - - min_duration = 50 - max_duration = 70 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - if (!hasorgans(target)) - return - var/datum/organ/external/affected = target.get_organ(target_zone) - return ..() && target.op_stage.ribcage == 0 && affected.open >= 2 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("[user] begins to cut through [target]'s ribcage with \the [tool].", \ - "You begin to cut through [target]'s ribcage with \the [tool].") - target.custom_pain("Something hurts horribly in your chest!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\blue [user] has cut [target]'s ribcage open with \the [tool].", \ - "\blue You have cut [target]'s ribcage open with \the [tool].") - target.op_stage.ribcage = 1 - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\red [user]'s hand slips, cracking [target]'s ribcage with \the [tool]!" , \ - "\red Your hand slips, cracking [target]'s ribcage with \the [tool]!" ) - var/datum/organ/external/affected = target.get_organ(target_zone) - affected.createwound(CUT, 20) - affected.fracture() - - -/datum/surgery_step/ribcage/retract_ribcage - allowed_tools = list( - /obj/item/weapon/retractor = 100, \ - /obj/item/weapon/crowbar = 75, \ - /obj/item/weapon/kitchen/utensil/fork = 20 - ) - - min_duration = 30 - max_duration = 40 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.op_stage.ribcage == 1 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "[user] starts to force open the ribcage in [target]'s torso with \the [tool]." - var/self_msg = "You start to force open the ribcage in [target]'s torso with \the [tool]." - user.visible_message(msg, self_msg) - target.custom_pain("Something hurts horribly in your chest!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "\blue [user] forces open [target]'s ribcage with \the [tool]." - var/self_msg = "\blue You force open [target]'s ribcage with \the [tool]." - user.visible_message(msg, self_msg) - target.op_stage.ribcage = 2 - - // Whoops! - if(prob(10)) - var/datum/organ/external/affected = target.get_organ(target_zone) - affected.fracture() - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "\red [user]'s hand slips, breaking [target]'s ribcage!" - var/self_msg = "\red Your hand slips, breaking [target]'s ribcage!" - user.visible_message(msg, self_msg) - var/datum/organ/external/affected = target.get_organ(target_zone) - affected.createwound(BRUISE, 20) - affected.fracture() - -/datum/surgery_step/ribcage/close_ribcage - allowed_tools = list( - /obj/item/weapon/retractor = 100, \ - /obj/item/weapon/crowbar = 75, \ - /obj/item/weapon/kitchen/utensil/fork = 20 - ) - - - min_duration = 20 - max_duration = 40 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.op_stage.ribcage == 2 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "[user] starts bending [target]'s ribcage back into place with \the [tool]." - var/self_msg = "You start bending [target]'s ribcage back into place with \the [tool]." - user.visible_message(msg, self_msg) - target.custom_pain("Something hurts horribly in your chest!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "\blue [user] bends [target]'s ribcage back into place with \the [tool]." - var/self_msg = "\blue You bend [target]'s ribcage back into place with \the [tool]." - user.visible_message(msg, self_msg) - - target.op_stage.ribcage = 1 - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "\red [user]'s hand slips, bending [target]'s ribs the wrong way!" - var/self_msg = "\red Your hand slips, bending [target]'s ribs the wrong way!" - user.visible_message(msg, self_msg) - var/datum/organ/external/chest/affected = target.get_organ("chest") - affected.createwound(BRUISE, 20) - affected.fracture() - if (prob(40)) - user.visible_message("\red A rib pierces the lung!") - target.rupture_lung() - -/datum/surgery_step/ribcage/mend_ribcage - allowed_tools = list( - /obj/item/weapon/bonegel = 100, \ - /obj/item/weapon/screwdriver = 75 - ) - - min_duration = 20 - max_duration = 40 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - return ..() && target.op_stage.ribcage == 1 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "[user] starts applying \the [tool] to [target]'s ribcage." - var/self_msg = "You start applying \the [tool] to [target]'s ribcage." - user.visible_message(msg, self_msg) - target.custom_pain("Something hurts horribly in your chest!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "\blue [user] applied \the [tool] to [target]'s ribcage." - var/self_msg = "\blue You applied \the [tool] to [target]'s ribcage." - user.visible_message(msg, self_msg) - - target.op_stage.ribcage = 0 - -////////////////////////////////////////////////////////////////// -// ALIEN EMBRYO SURGERY // -////////////////////////////////////////////////////////////////// -/datum/surgery_step/ribcage/remove_embryo - allowed_tools = list( - /obj/item/weapon/hemostat = 100, \ - /obj/item/weapon/wirecutters = 75, \ - /obj/item/weapon/kitchen/utensil/fork = 20 - ) - blood_level = 2 - - min_duration = 80 - max_duration = 100 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/embryo = 0 - for(var/obj/item/alien_embryo/A in target) - embryo = 1 - break - return ..() && embryo && target.op_stage.ribcage == 2 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/msg = "[user] starts to pull something out from [target]'s ribcage with \the [tool]." - var/self_msg = "You start to pull something out from [target]'s ribcage with \the [tool]." - user.visible_message(msg, self_msg) - target.custom_pain("Something hurts horribly in your chest!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - user.visible_message("\red [user] rips the larva out of [target]'s ribcage!", - "You rip the larva out of [target]'s ribcage!") - - for(var/obj/item/alien_embryo/A in target) - A.loc = A.loc.loc - - -////////////////////////////////////////////////////////////////// -// CHEST INTERNAL ORGAN SURGERY // -////////////////////////////////////////////////////////////////// -/datum/surgery_step/ribcage/fix_chest_internal - allowed_tools = list( - /obj/item/stack/medical/advanced/bruise_pack= 100, \ - /obj/item/stack/medical/bruise_pack = 20, \ - /obj/item/stack/medical/bruise_pack/tajaran = 70, \ - ) - - min_duration = 70 - max_duration = 90 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - if(!hasorgans(target)) - return 0 - - var/is_chest_organ_damaged = 0 - var/datum/organ/external/chest/chest = target.get_organ("chest") - for(var/datum/organ/internal/I in chest.internal_organs) - if(I.damage > 0) - is_chest_organ_damaged = 1 - break - return ..() && is_chest_organ_damaged && target.op_stage.ribcage == 2 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/tool_name = "\the [tool]" - if (istype(tool, /obj/item/stack/medical/advanced/bruise_pack)) - tool_name = "regenerative membrane" - if (istype(tool, /obj/item/stack/medical/bruise_pack)) - if (istype(tool, /obj/item/stack/medical/bruise_pack/tajaran)) - tool_name = "the poultice" - else - tool_name = "the bandaid" - var/datum/organ/external/chest/chest = target.get_organ("chest") - for(var/datum/organ/internal/I in chest.internal_organs) - if(I && I.damage > 0) - if(I.robotic < 2) - user.visible_message("[user] starts treating damage to [target]'s [I.name] with [tool_name].", \ - "You start treating damage to [target]'s [I.name] with [tool_name]." ) - else - user.visible_message("[user] attempts to repair [target]'s mechanical [I.name] with [tool_name]...", \ - "\blue You attempt to repair [target]'s mechanical [I.name] with [tool_name]...") - - target.custom_pain("The pain in your chest is living hell!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/tool_name = "\the [tool]" - if (istype(tool, /obj/item/stack/medical/advanced/bruise_pack)) - tool_name = "regenerative membrane" - if (istype(tool, /obj/item/stack/medical/bruise_pack)) - if (istype(tool, /obj/item/stack/medical/bruise_pack/tajaran)) - tool_name = "the poultice" - else - tool_name = "the bandaid" - var/datum/organ/external/chest/chest = target.get_organ("chest") - for(var/datum/organ/internal/I in chest.internal_organs) - if(I && I.damage > 0) - if(I.robotic < 2) - user.visible_message("\blue [user] treats damage to [target]'s [I.name] with [tool_name].", \ - "\blue You treat damage to [target]'s [I.name] with [tool_name]." ) - else - user.visible_message("\blue [user] pokes [target]'s mechanical [I.name] with [tool_name]...", \ - "\blue You poke [target]'s mechanical [I.name] with [tool_name]... \red For no effect, since it's robotic.") - I.damage = 0 - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/external/chest/affected = target.get_organ("chest") - user.visible_message("\red [user]'s hand slips, getting mess and tearing the inside of [target]'s chest with \the [tool]!", \ - "\red Your hand slips, getting mess and tearing the inside of [target]'s chest with \the [tool]!") - var/dam_amt = 2 - - if (istype(tool, /obj/item/stack/medical/advanced/bruise_pack)) - target.adjustToxLoss(5) - - else if (istype(tool, /obj/item/stack/medical/bruise_pack)) - if (istype(tool, /obj/item/stack/medical/bruise_pack/tajaran)) - target.adjustToxLoss(7) - else - dam_amt = 5 - target.adjustToxLoss(10) - affected.createwound(CUT, 5) - - for(var/datum/organ/internal/I in affected.internal_organs) - if(I && I.damage > 0) - I.take_damage(dam_amt,0) - -/datum/surgery_step/ribcage/fix_chest_internal_robot //For artificial organs - allowed_tools = list( - /obj/item/stack/nanopaste = 100, \ - /obj/item/weapon/bonegel = 30, \ - /obj/item/weapon/screwdriver = 70, \ - ) - - min_duration = 70 - max_duration = 90 - - can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - if(!hasorgans(target)) - return 0 - - var/is_chest_organ_damaged = 0 - var/datum/organ/internal/heart/heart = target.internal_organs_by_name["heart"] - var/datum/organ/external/chest/chest = target.get_organ("chest") - for(var/datum/organ/internal/I in chest.internal_organs) if(I.damage > 0) - is_chest_organ_damaged = 1 - break - return ..() && is_chest_organ_damaged && heart.robotic == 2 && target.op_stage.ribcage == 2 - - begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/internal/heart/heart = target.internal_organs_by_name["heart"] - - if(heart.damage > 0) - user.visible_message("[user] starts mending the mechanisms on [target]'s heart with \the [tool].", \ - "You start mending the mechanisms on [target]'s heart with \the [tool]." ) - target.custom_pain("The pain in your chest is living hell!",1) - ..() - - end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/internal/heart/heart = target.internal_organs_by_name["heart"] - if(heart.damage > 0) - user.visible_message("\blue [user] repairs [target]'s heart with \the [tool].", \ - "\blue You repair [target]'s heart with \the [tool]." ) - heart.damage = 0 - - fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - var/datum/organ/internal/heart/heart = target.internal_organs_by_name["heart"] - user.visible_message("\red [user]'s hand slips, smearing [tool] in the incision in [target]'s heart, gumming it up!!" , \ - "\red Your hand slips, smearing [tool] in the incision in [target]'s heart, gumming it up!") - heart.take_damage(5, 0) - target.adjustToxLoss(5) - -////////////////////////////////////////////////////////////////// -// HEART SURGERY // -////////////////////////////////////////////////////////////////// -// To be finished after some tests. -// /datum/surgery_step/ribcage/heart/cut -// allowed_tools = list( -// /obj/item/weapon/scalpel = 100, \ -// /obj/item/weapon/kitchenknife = 75, \ -// /obj/item/weapon/shard = 50, \ -// ) - -// min_duration = 30 -// max_duration = 40 - -// can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) -// return ..() && target.op_stage.ribcage == 2 - diff --git a/code/modules/surgery/slimes.dm b/code/modules/surgery/slimes.dm new file mode 100644 index 0000000000..048c6d3e3c --- /dev/null +++ b/code/modules/surgery/slimes.dm @@ -0,0 +1,93 @@ +////////////////////////////////////////////////////////////////// +// SLIME CORE EXTRACTION // +////////////////////////////////////////////////////////////////// + +/datum/surgery_step/slime + is_valid_target(mob/living/carbon/slime/target) + return istype(target, /mob/living/carbon/slime/) + + can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + return target.stat == 2 + +/datum/surgery_step/slime/cut_flesh + allowed_tools = list( + /obj/item/weapon/scalpel = 100, \ + /obj/item/weapon/kitchenknife = 75, \ + /obj/item/weapon/shard = 50, \ + ) + + min_duration = 30 + max_duration = 50 + + can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + return ..() && istype(target) && target.core_removal_stage == 0 + + begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + user.visible_message("[user] starts cutting through [target]'s flesh with \the [tool].", \ + "You start cutting through [target]'s flesh with \the [tool].") + + end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + user.visible_message("\blue [user] cuts through [target]'s flesh with \the [tool].", \ + "\blue You cut through [target]'s flesh with \the [tool], revealing its silky innards.") + target.core_removal_stage = 1 + + fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + user.visible_message("\red [user]'s hand slips, tearing [target]'s flesh with \the [tool]!", \ + "\red Your hand slips, tearing [target]'s flesh with \the [tool]!") + +/datum/surgery_step/slime/cut_innards + allowed_tools = list( + /obj/item/weapon/scalpel = 100, \ + /obj/item/weapon/kitchenknife = 75, \ + /obj/item/weapon/shard = 50, \ + ) + + min_duration = 30 + max_duration = 50 + + can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + return ..() && istype(target) && target.core_removal_stage == 1 + + begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + user.visible_message("[user] starts cutting [target]'s silky innards apart with \the [tool].", \ + "You start cutting [target]'s silky innards apart with \the [tool].") + + end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + user.visible_message("\blue [user] cuts [target]'s innards apart with \the [tool], exposing the cores.", \ + "\blue You cut [target]'s innards apart with \the [tool], exposing the cores.") + target.core_removal_stage = 2 + + fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + user.visible_message("\red [user]'s hand slips, tearing [target]'s innards with \the [tool]!", \ + "\red Your hand slips, tearing [target]'s innards with \the [tool]!") + +/datum/surgery_step/slime/saw_core + allowed_tools = list( + /obj/item/weapon/circular_saw = 100, \ + /obj/item/weapon/hatchet = 75 + ) + + min_duration = 50 + max_duration = 70 + + can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + return ..() && (istype(target) && target.core_removal_stage == 2 && target.cores > 0) //This is being passed a human as target, unsure why. + + begin_step(mob/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + user.visible_message("[user] starts cutting out one of [target]'s cores with \the [tool].", \ + "You start cutting out one of [target]'s cores with \the [tool].") + + end_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + target.cores-- + user.visible_message("\blue [user] cuts out one of [target]'s cores with \the [tool].",, \ + "\blue You cut out one of [target]'s cores with \the [tool]. [target.cores] cores left.") + + if(target.cores >= 0) + new target.coretype(target.loc) + if(target.cores <= 0) + target.icon_state = "[target.colour] baby slime dead-nocore" + + + fail_step(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) + user.visible_message("\red [user]'s hand slips, causing \him to miss the core!", \ + "\red Your hand slips, causing you to miss the core!") \ No newline at end of file diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index b0116585ab..9ce44d1260 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -86,12 +86,15 @@ proc/do_surgery(mob/living/M, mob/living/user, obj/item/tool) //check if tool is right or close enough and if this step is possible if( S.tool_quality(tool) && S.can_use(user, M, user.zone_sel.selecting, tool) && S.is_valid_target(M)) S.begin_step(user, M, user.zone_sel.selecting, tool) //start on it - //We had proper tools! (or RNG smiled.) and User did not move or change hands. + //We had proper tools! (or RNG smiled.) and user did not move or change hands. if( prob(S.tool_quality(tool)) && do_mob(user, M, rand(S.min_duration, S.max_duration))) S.end_step(user, M, user.zone_sel.selecting, tool) //finish successfully else if (tool in user.contents && user.Adjacent(M)) //or S.fail_step(user, M, user.zone_sel.selecting, tool) //malpractice~ return 1 //don't want to do weapony things after surgery + if (user.a_intent == "help") + user << "\red You can't see any useful way to use [tool] on [M]." + return 1 return 0 proc/sort_surgeries() @@ -114,5 +117,5 @@ proc/sort_surgeries() var/eyes = 0 var/face = 0 var/appendix = 0 - var/ribcage = 0 var/head_reattach = 0 + var/current_organ diff --git a/code/modules/virus2/effect.dm b/code/modules/virus2/effect.dm index 41fda7a150..3ebeefeba8 100644 --- a/code/modules/virus2/effect.dm +++ b/code/modules/virus2/effect.dm @@ -203,7 +203,7 @@ if(istype(mob, /mob/living/carbon/human)) var/mob/living/carbon/human/H = mob var/datum/organ/internal/brain/B = H.internal_organs_by_name["brain"] - if (B.damage < B.min_broken_damage) + if (B && B.damage < B.min_broken_damage) B.take_damage(5) else mob.setBrainLoss(50) diff --git a/code/setup.dm b/code/setup.dm index cd455dda5b..f053065352 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -741,27 +741,25 @@ var/list/RESTRICTED_CAMERA_NETWORKS = list( //Those networks can only be accesse #define NO_BREATHE 2 #define NO_SCAN 4 #define NO_PAIN 8 +#define NO_SLIP 16 +#define NO_POISON 32 -#define HAS_SKIN_TONE 16 -#define HAS_SKIN_COLOR 32 -#define HAS_LIPS 64 -#define HAS_UNDERWEAR 128 -#define HAS_TAIL 256 +#define HAS_SKIN_TONE 64 +#define HAS_SKIN_COLOR 128 +#define HAS_LIPS 256 +#define HAS_UNDERWEAR 512 +#define HAS_TAIL 1024 -#define IS_SLOW 512 -#define IS_PLANT 1024 -#define IS_WHITELISTED 2048 - -#define RAD_ABSORB 4096 -#define REQUIRE_LIGHT 8192 - -#define IS_SYNTHETIC 16384 +#define IS_PLANT 2048 +#define IS_WHITELISTED 4096 +#define IS_SYNTHETIC 8192 //Language flags. #define WHITELISTED 1 // Language is available if the speaker is whitelisted. #define RESTRICTED 2 // Language can only be accquired by spawning or an admin. #define NONVERBAL 4 // Language has a significant non-verbal component. Speech is garbled without line-of-sight #define SIGNLANG 8 // Language is completely non-verbal. Speech is displayed through emotes for those who can understand. +#define HIVEMIND 16 // Broadcast to all mobs with this language. //Flags for zone sleeping #define ZONE_ACTIVE 1 @@ -826,6 +824,7 @@ var/list/RESTRICTED_CAMERA_NETWORKS = list( //Those networks can only be accesse #define IS_VOX 2 #define IS_SKRELL 3 #define IS_UNATHI 4 +#define IS_XENOS 5 #define MAX_GEAR_COST 5 //Used in chargen for loadout limit. @@ -852,3 +851,7 @@ var/list/RESTRICTED_CAMERA_NETWORKS = list( //Those networks can only be accesse #define ATMOS_DEFAULT_VOLUME_PIPE 70 //L var/list/hit_appends = list("-OOF", "-ACK", "-UGH", "-HRNK", "-HURGH", "-GLORF") + +// Reagent metabolism defines. +#define FOOD_METABOLISM 0.4 +#define ALCOHOL_METABOLISM 0.1 diff --git a/code/stylesheet.dm b/code/stylesheet.dm index 4d93845d98..2647e5a0d3 100644 --- a/code/stylesheet.dm +++ b/code/stylesheet.dm @@ -65,6 +65,7 @@ h1.alert, h2.alert {color: #000000;} .tajaran_signlang {color: #941C1C;} .skrell {color: #00CED1;} .soghun {color: #228B22;} +.changeling {color: #800080;} .vox {color: #AA00AA;} .rough {font-family: "Trebuchet MS", cursive, sans-serif;} .say_quote {font-family: Georgia, Verdana, sans-serif;} diff --git a/html/changelog.html b/html/changelog.html index 344101d7a0..fecd3052c1 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -56,7 +56,49 @@ should be listed in the changelog upon commit though. Thanks. --> -+
+
+

1 October 2014

+

Zuhayr updated:

+
    +
  • Added species organ checks to several areas (phoron burn, welder burn, appendicitis, vox cortical stacks, flashes).
  • +
  • Added VV option to add or remove organs.
  • +
  • Added simple bioprinter (adminspawn).
  • +
  • Added smashing/slashing behavior from xenos to some unarmed attacks.
  • +
  • Added some new state icons for diona nymphs.
  • +
  • Added borer husk functionality (cortical borers can turn dead humans into zombies).
  • +
  • Added tackle verb.
  • +
  • Added NO_SLIP.
  • +
  • Added species-specific orans to Dionaea, new Xenomorphs and vox.
  • +
  • Added colour and species to blood data.
  • +
  • Added lethal consequences to missing your heart.
  • +
  • Removed robot_talk_understand and alien_talk_understand.
  • +
  • Removed attack_alien() and several flavours of is_alien() procs.
  • +
  • Removed /mob/living/carbon/alien/humanoid.
  • +
  • Removed alien_hud().
  • +
  • Removed IS_SLOW, NEEDS_LIGHT and RAD_ABSORB.
  • +
  • Renamed is_larva() to is_alien().
  • +
  • Refactored a ton of files, either condensing or expanding them, or moving them to new directories.
  • +
  • Refactored some attack vars from simple_animal to mob/living level.
  • +
  • Refactored internal organs to /mob/living/carbon level.
  • +
  • Refactored rad and light absorbtion to organ level.
  • +
  • Refactored brains to /obj/item/organ/brain.
  • +
  • Refactored a lot of blood splattering to use blood_splatter() proc.
  • +
  • Refactored broadcast languages (changeling and alien hiveminds, drone and binary chat) to actual languages.
  • +
  • Refactored xenomorph abilities to work for humans.
  • +
  • Refactored xenomorphs into human species.
  • +
  • Rewrote larva_hud() and human_hud(). The latter now takes data from the species datum.
  • +
  • Rewrote diona nymphs as descendents of /mob/living/carbon/alien.
  • +
  • Rewrote xenolarva as descendents of /mob/living/carbon/alien.
  • +
  • Rewrote /mob/living/carbon/alien.
  • +
  • Moved alcohol and toxin processing to the liver.
  • +
  • Moved drone light proc to robot level, added integrated_light_power and local_transmit vars to robots.
  • +
  • Moved human brainloss onto the brain organ.
  • +
  • Shuffled around and collapsed several redundant procs down to carbon level (hide, ventcrawl, Bump).
  • +
  • Fixed species swaps from NO_BLOOD to those with blood killing the subject instantly.
  • +
+
+ +

28 September 2014

Gamerofthegame updated:

    @@ -65,6 +107,18 @@ should be listed in the changelog upon commit though. Thanks. -->
+
+

28 September 2014

+

Zuhayr updated:

+
    +
  • Organs can now be removed and transplanted.
  • +
  • Brain surgery is now the same as chest surgery regarding the steps leading up to it.
  • +
  • Appendix and kidney now share the groin and removing the first will prevent appendicitis.
  • +
  • Lots of backend surgery/organ stuff, see the PR if you need to know.
  • +
+
+ +

20 September 2014

HarpyEagle updated:

diff --git a/icons/effects/species.dmi b/icons/effects/species.dmi index d5405066ab..4c1516b858 100644 Binary files a/icons/effects/species.dmi and b/icons/effects/species.dmi differ diff --git a/icons/mob/alien.dmi b/icons/mob/alien.dmi index 36a6aa3368..2f31429878 100644 Binary files a/icons/mob/alien.dmi and b/icons/mob/alien.dmi differ diff --git a/icons/mob/human_races/xenos/r_xenos_drone.dmi b/icons/mob/human_races/xenos/r_xenos_drone.dmi new file mode 100644 index 0000000000..19094d66ed Binary files /dev/null and b/icons/mob/human_races/xenos/r_xenos_drone.dmi differ diff --git a/icons/mob/human_races/xenos/r_xenos_hunter.dmi b/icons/mob/human_races/xenos/r_xenos_hunter.dmi new file mode 100644 index 0000000000..ef1b3a6f4d Binary files /dev/null and b/icons/mob/human_races/xenos/r_xenos_hunter.dmi differ diff --git a/icons/mob/human_races/xenos/r_xenos_queen.dmi b/icons/mob/human_races/xenos/r_xenos_queen.dmi new file mode 100644 index 0000000000..efb5558ac1 Binary files /dev/null and b/icons/mob/human_races/xenos/r_xenos_queen.dmi differ diff --git a/icons/mob/human_races/xenos/r_xenos_sentinel.dmi b/icons/mob/human_races/xenos/r_xenos_sentinel.dmi new file mode 100644 index 0000000000..5b250c7445 Binary files /dev/null and b/icons/mob/human_races/xenos/r_xenos_sentinel.dmi differ diff --git a/icons/mob/monkey.dmi b/icons/mob/monkey.dmi index b00b4a08fa..b9c1299ec2 100644 Binary files a/icons/mob/monkey.dmi and b/icons/mob/monkey.dmi differ diff --git a/icons/mob/screen1_alien.dmi b/icons/mob/screen1_alien.dmi index d42c521068..b21cd203dd 100644 Binary files a/icons/mob/screen1_alien.dmi and b/icons/mob/screen1_alien.dmi differ diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index a5c7e0c7cd..58a7aaf25c 100644 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ diff --git a/maps/tgstation2.dmm b/maps/tgstation2.dmm index e647875dfa..780a091ca2 100644 --- a/maps/tgstation2.dmm +++ b/maps/tgstation2.dmm @@ -3743,7 +3743,7 @@ "btY" = (/obj/machinery/portable_atmospherics/powered/pump,/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor{icon_state = "white"},/area/rnd/misc_lab) "btZ" = (/obj/structure/table,/obj/machinery/computer/med_data/laptop,/obj/machinery/atmospherics/unary/vent_pump/on{dir = 4},/turf/simulated/floor{dir = 9; icon_state = "whitered"},/area/medical/patient_c) "bua" = (/obj/structure/cable/green{d1 = 1; d2 = 4; icon_state = "1-4"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9; pixel_y = 0},/turf/simulated/floor{dir = 1; icon_state = "whitered"},/area/medical/patient_c) -"bub" = (/obj/structure/table,/obj/item/weapon/circular_saw,/obj/item/weapon/scalpel{pixel_y = 12},/turf/simulated/floor{dir = 2; icon_state = "whitecorner"},/area/assembly/robotics) +"bub" = (/obj/structure/table,/obj/item/weapon/circular_saw,/obj/item/weapon/scalpel{pixel_y = 12},/obj/item/weapon/hemostat,/obj/item/weapon/retractor,/turf/simulated/floor{dir = 2; icon_state = "whitecorner"},/area/assembly/robotics) "buc" = (/obj/structure/table,/obj/item/device/flash/synthetic,/obj/item/device/flash/synthetic,/obj/item/device/flash/synthetic,/obj/item/device/flash/synthetic,/obj/item/device/flash/synthetic,/obj/item/device/flash/synthetic,/obj/structure/window/reinforced/tinted{dir = 4; icon_state = "twindow"},/obj/item/device/mmi/posibrain,/obj/item/device/robotanalyzer,/turf/simulated/floor{dir = 8; icon_state = "whitecorner"},/area/assembly/robotics) "bud" = (/turf/simulated/wall/r_wall,/area/rnd/xenobiology) "bue" = (/obj/structure/table,/obj/item/weapon/crowbar,/obj/item/device/radio/headset/headset_sci{pixel_x = -3},/obj/item/device/multitool{pixel_x = 3},/obj/item/device/multitool{pixel_x = 3},/obj/item/clothing/glasses/welding,/obj/item/clothing/glasses/welding,/turf/simulated/floor{icon_state = "white"},/area/assembly/robotics) @@ -4043,6 +4043,7 @@ "bzM" = (/obj/machinery/teleport/hub,/turf/simulated/floor/plating,/area/teleporter) "bzN" = (/obj/structure/rack,/obj/item/weapon/tank/oxygen,/obj/item/clothing/mask/gas,/turf/simulated/floor/plating,/area/teleporter) "bzO" = (/obj/structure/disposalpipe/segment,/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 4},/turf/simulated/floor{dir = 4; icon_state = "whiteblue"; tag = "icon-whitehall (WEST)"},/area/medical/medbay2) +"bzP" = (/obj/machinery/light/small{dir = 4},/obj/structure/closet/crate/freezer,/turf/simulated/floor{icon_state = "freezerfloor"},/area/medical/surgery2) "bzQ" = (/obj/machinery/vending/hydronutrients,/turf/simulated/floor{icon_state = "hydrofloor"},/area/rnd/xenobiology/xenoflora) "bzR" = (/obj/machinery/airlock_sensor{frequency = 1379; id_tag = "eng_eva_sensor"; pixel_x = 0; pixel_y = 25},/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 4; frequency = 1379; id_tag = "eng_eva_pump"},/turf/simulated/floor{dir = 8; icon_state = "floorgrimecaution"},/area/engine/engine_eva_maintenance) "bzS" = (/obj/structure/closet/crate,/obj/item/device/multitool,/obj/item/device/multitool,/obj/item/device/assembly/prox_sensor,/obj/item/device/flashlight,/obj/item/weapon/storage/backpack,/turf/simulated/floor/plating,/area/maintenance/research_shuttle) @@ -8630,7 +8631,7 @@ "djY" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/door/poddoor{id = "skipjack"; name = "Skipjack Blast Shielding"},/turf/simulated/shuttle/plating/vox,/area/shuttle/vox/station) "djZ" = (/obj/machinery/embedded_controller/radio/airlock/airlock_controller{tag_airpump = "vox_east_vent"; tag_exterior_door = "vox_northeast_lock"; frequency = 1331; id_tag = "vox_east_control"; tag_interior_door = "vox_southeast_lock"; pixel_x = -24; req_access_txt = "150"; tag_chamber_sensor = "vox_east_sensor"},/obj/machinery/atmospherics/unary/vent_pump/high_volume{dir = 4; frequency = 1331; id_tag = "vox_east_vent"},/turf/simulated/shuttle/plating/vox,/area/shuttle/vox/station) "dka" = (/obj/machinery/atmospherics/pipe/manifold/visible{dir = 4},/turf/simulated/shuttle/plating/vox,/area/shuttle/vox/station) -"dkb" = (/obj/machinery/body_scanconsole{known_implants = list(/obj/item/weapon/implant/cortical)},/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station) +"dkb" = (/obj/machinery/light/small{dir = 8},/obj/structure/closet/crate/freezer,/turf/simulated/floor{icon_state = "freezerfloor"},/area/medical/surgery) "dkc" = (/obj/machinery/atmospherics/pipe/tank/nitrogen{dir = 1; initialize_directions = 1; start_pressure = 493.6},/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station) "dkd" = (/obj/machinery/sleep_console,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station) "dke" = (/obj/machinery/bodyscanner,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station) @@ -8651,7 +8652,7 @@ "dkt" = (/obj/machinery/power/terminal{dir = 4},/obj/machinery/light/small{dir = 1},/obj/structure/cable/yellow{d2 = 2; icon_state = "0-2"},/turf/simulated/floor/plating,/area/maintenance/portsolar) "dku" = (/obj/structure/table/reinforced,/obj/item/weapon/circular_saw,/obj/structure/window/basic{dir = 1},/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station) "dkv" = (/obj/structure/table/reinforced,/obj/item/weapon/pickaxe,/obj/item/weapon/storage/firstaid/toxin,/obj/structure/window/basic{dir = 1},/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station) -"dkw" = (/obj/machinery/optable,/obj/item/brain,/obj/structure/window/basic{dir = 1},/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station) +"dkw" = (/obj/machinery/body_scanconsole,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station) "dkx" = (/obj/structure/window/basic{dir = 1},/obj/structure/table,/obj/machinery/bot/floorbot,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station) "dky" = (/obj/structure/window/basic{dir = 1},/obj/structure/table,/obj/item/broken_device,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station) "dkz" = (/obj/item/weapon/organ/r_arm,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station) @@ -10685,14 +10686,13 @@ "dXz" = (/obj/machinery/door/firedoor/border_only{dir = 4; name = "Firelock"},/obj/machinery/door/airlock{id_tag = "rdorm2"; name = "Dorm 2"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor{dir = 2; icon_state = "carpet"},/area/research_outpost/hallway) "dXA" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 9; pixel_y = 0},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor/carpet,/area/research_outpost/hallway) "dXB" = (/turf/simulated/wall,/area/medical/surgery2) -"dXC" = (/obj/machinery/light/small{dir = 4},/turf/simulated/floor{icon_state = "freezerfloor"},/area/medical/surgery2) +"dXC" = (/obj/machinery/optable,/obj/item/organ/brain,/obj/structure/window/basic{dir = 1},/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station) "dXD" = (/turf/unsimulated/wall{icon_state = "phoron13"},/area/alien) "dXE" = (/turf/unsimulated/wall{icon_state = "phoron5"},/area/alien) "dXF" = (/turf/simulated/wall/r_wall,/area/medical/virologyaccess) "dXG" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1},/obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers,/turf/simulated/floor,/area/research_outpost/hallway) "dXH" = (/obj/machinery/atmospherics/pipe/simple/hidden{dir = 10; icon_state = "intact"; tag = "icon-intact-f (SOUTHWEST)"},/turf/simulated/floor{icon_state = "cafeteria"; dir = 5},/area/djstation) "dXI" = (/obj/structure/window/shuttle,/obj/structure/grille,/turf/simulated/shuttle/plating,/area/shuttle/escape/centcom) -"dXJ" = (/obj/machinery/light/small{dir = 8},/turf/simulated/floor{icon_state = "freezerfloor"},/area/medical/surgery) "dXK" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor,/area/research_outpost/hallway) "dXL" = (/obj/structure/closet/secure_closet/miner,/obj/machinery/atmospherics/unary/vent_pump/on,/turf/simulated/floor,/area/mine/living_quarters) "dXM" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor,/area/mine/west_outpost) @@ -11169,7 +11169,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabCVaaeaaeaaeaaaaaecHGaaecHGaaecsaaaecrZaaecsaaaecrZaaeaaeaaabskdfZdgacttdfXdfJddFdfNdfMdaGdfPdfUdaGdaGdfVdaGdaGdfWcBsdaGdfGdfldfodfzdfGdaGcaOcaOcaOcGqdfIcaOcjXcjXcjXcjXcjXcjXbkMbEaebRdibcVRdgJebObEaeaFcmCebMdXBebKdgIcVQdiaebGdXBcmIcqzdXFdgCdgxdgtdXFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaabudcnbcmXcmYdgrdgscfIdgpcfcdgqdgldgbdgmctqaaaaaaaaeaaeaaaaaaaaaaaaaaaaaaaaaaaecebdgLcebaaeaaaaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaaedeCcghdeEcghdeEdeIcgicghcgjdeIcgicghcgjdeKccVbQGddFdeMddFddFddFddFddFddEddCddLcrTddIdQTcFAdQVdQUchBddMdZEcrYchBcaTddVddUcaOcsdcsecsbcsccaPddWcaOdRMdRMcsfclLclLcjXboJbEabEaebxdeUbEabEabEaebvcmCebwdXBdXBdXBdeQebCdXBdXBcmIcmMdXFdYddeYdYddXFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaeaaebudccCcoLccCdRNcmEckUdePcfccfcdeOcfcbudbudaaaaaaaaaaaeaaeaaaaafaaaaaaaaaaaaaaeaaadeZaaaaaeaaeaaeaaeaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeceebSZcuqcgrcgqcnqcuschrcgFcnscurcgBcgCcnqbSZcgycgzcnmcnncnjcnlcnQcnLcnWcnVcnKcuucuwckyclWcnFcnIcnHcnucntcnAcnvcaTclucoacaOcaPcaPcaPcaPcaPcnZcaOcoVcoVcoVclLclLcjXboJcmsbEadXWcmAcmvdXVbEadXZcmCdXYdXBdYacmFcmHdYbdXBcmJcmIcmMdXFcmLcmKcmNdXFaaaaaaaaaaaaaaaaaabVuckZbYRceXbVuaaeaaaaaaaaaaaabudccCccCccCcmRcmScmZcmVcndcnacngcnecnhbudaaaaaaaaaaaaaaeaaeaaaaaaaaaaaaaaaaaeaaackvaaaaaeaaeaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaaaaaeclmcfpcfmcbDcfmcbDcfmcbDcuecbDcfmcbDcudclgclgclgcllclbbSZcfkclccmrcmqcmocmicuvcibcmgckyckxcmecmaclPclNclCclyclvcaTclucltcaOclscaPcaPclqcaPclpcaOckgcfgclocfgcfrcjXboJckFbEadXJckHckIckJckKckLckMckNckOckPckQckTdXCdXBckAckzceLbZJbVuckEbVubZJaaaaaaaaeaaaaaaaaabVuckYccOccYbVuaaeaaeaaaaaaaaabudcfccfccfccfcckfckUcbWcbWcbWckXcbWckVbudaaaaaaaaaaaaaaaciHciHciHbCVaaeaaeaaeaaeckwaaeaaeaaeaaeaaeaaAciHciHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaaaaaeclmcfpcfmcbDcfmcbDcfmcbDcuecbDcfmcbDcudclgclgclgcllclbbSZcfkclccmrcmqcmocmicuvcibcmgckyckxcmecmaclPclNclCclyclvcaTclucltcaOclscaPcaPclqcaPclpcaOckgcfgclocfgcfrcjXboJckFbEadkbckHckIckJckKckLckMckNckOckPckQckTbzPdXBckAckzceLbZJbVuckEbVubZJaaaaaaaaeaaaaaaaaabVuckYccOccYbVuaaeaaeaaaaaaaaabudcfccfccfccfcckfckUcbWcbWcbWckXcbWckVbudaaaaaaaaaaaaaaaciHciHciHbCVaaeaaeaaeaaeckwaaeaaeaaeaaeaaeaaAciHciHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaeaaeaaeceeciccibbSZcibciYchYcvSciabSZcibbSZbSZbSZbSZbSZcqjcqqcpOcqkcpRcpOcipcpRcpPcpTcpScpWcpVcpDcpAcpFchBcpIcpGcpLchBcqdcqfcoHciRcqgciSciTcqicaPcpXcaOcqccfgchscfgcnTcjXboJcplbEacpjcpkcuLdYnbEadYtcnodYtdXBdYrcuZcpmcptdXBcooceLceLbVucprcpqcpzbVubVubVucnJbVubVubVubVucpecpfcfvbVubVubVubZJaaaaaabudcnbcmXcmYcphcpicmZcbWcbWcbWckXcbWcnkbudaaaaaaaaaaaaaaaciHaaaaaeaaaaaeaaaaaaaaaciPaaaaaeaaeaaaaaaaaaaaaciHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaeaaeaaaaaaceeciccibbSZcidcuIchXchHchGchHchYcuJciachLchHchHcuFcpdcuGcuHchHcpccpcchHcpbchYcfTbWldeBdcxcoWbQGchBcoZchBchBchBcoIcoQcoHchucoSchAchxcoRcaPcoGcaOcoFcfgchscfgcfgcjXcovcowbEabEacosbEabEabEacoAcoBcoCdXBdXBdXBcozdXBdXBcooceLaaabVuconcexcorcaZdbdcmzcmwcilcmycmxbVuceycexcevbVucomcfCbVuaaeaaebudccCccCccCcmDcmEcokcogcofcoccobcbWcmcbudbudbudbudaaaaaaciHaaachWchWchWchWchWaaeciPaaechWchWchWchWchWaaaciHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactvctvctvctvctvctvctvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaaaaaaaaceeciccidchHchHchHchHchHchGchHchHchHchGchYcxrcxdcxeclbcxcckhckicrHcrHckickGbSZbSZbWlcgAbSZcrPcrScrRcrKcrIcrOcrNcrIcshcsicsjcrUcrXcrXcsgcrXcsmcsncsocskcslclHclHcjXcrkcrhcricrlcrlcrlcrmcrfcrecrecrecrecrecrecrecrecrnckzceLaaacaZcrocfPdZpcaZdeNdZnbXKbXKdZmbXKdZkcrqcrtdWPdZjcjPbXKbVuaaaaaabudccCccCccCcphcrpcrucqKcrAcrvcrBcbWcbWcrEcoqcopbudaaeaaeciHaaeceucepcepcepcepcelciPcekcefcefcefcefceqaaeciHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -11502,9 +11502,9 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacUscUvdSrdSWdSVdStcUvdS aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacUscUvdSrdSXcUWdStcUvdSsdSsdSsdSsdSsdSsdSYdTadSZcUsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacVgdOPdjWcVgdODdjYdjSdjkdjjdjkdjjdjkdjSdjYdODcVgdjZdkacVgaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacUscUvcUvcUvcUvcUvcUvdSsdSsdSsdSsdSsdSsdSsdSsdSscUsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacVgdjMcWhcVgcVgcVgcVgcVgcVgdjKcVgcVgcVgcVgcVgcVgcWjdjLcVgaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacUscVlcVmcVmdSTcVmcVmcVmdSTcVmcVmcVmdSTcVmcVmdSUcUsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadODdjPdjOdjNdjNdjNdjNdjNdjNcVgdjNcVgdjNdjNdjNdjNdjNdjNdjOdjPdODaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacUsdTbdTcdTccVzdTfdTgdThcVzdTddTddTecVzdTjdTicVycUsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadODdkqdkpdksdkrdkxdkycVgdjKcVgdjKcVgdjKcVgdkvdpydkudkwdkpdkqdODaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacUsdTbdTcdTccVzdTfdTgdThcVzdTddTddTecVzdTjdTicVycUsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadODdkqdkpdksdkrdkxdkycVgdjKcVgdjKcVgdjKcVgdkvdpydkudXCdkpdkqdODaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacUsdTcdTkdTbcVXdTodTndTgcVXdTmdTldTdcVXdTpcVydTqcUsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadODdjYdkpdjkdjkdjkdjkcVgdjkdjkdjkdjkdjkcVgdjkdjkdkzdjkdkpdjYdODaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacUscUscUscUscUscUscUscUscUscUscUscUscUscUscUscUscUsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacVbcVgdkcdkldkkdkidkjcVgdkhdjkdjkdjkdkgcVgdkfdkddkedkbdkccVgcVdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacUscUscUscUscUscUscUscUscUscUscUscUscUscUscUscUscUsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacVbcVgdkcdkldkkdkidkjcVgdkhdjkdjkdjkdkgcVgdkfdkddkedkwdkccVgcVdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacWJcVgdkmdkmcVgcVgcVgcVgdkodjkdjkdjkdEFcVgcVgcVgcVgdkmdkmcVgcWNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacWJcWOcWOcWNaaaaaacVgdjzdjkdjkdjkdEzcVgaaaaaacWJcWOcWOcWNaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacVgdjBdjkdjkdjkdEzcVgaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa