diff --git a/baystation12.dme b/baystation12.dme index 1c200c9afc..037531f6fd 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" @@ -897,7 +896,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 +923,33 @@ #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\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 +963,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 +996,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 +1047,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 +1056,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,6 +1108,7 @@ #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" 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/_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/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 d36fc7a7c7..001372b4e3 100644 --- a/code/controllers/hooks-defs.dm +++ b/code/controllers/hooks-defs.dm @@ -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..4777f061d6 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -495,7 +495,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 +777,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 +830,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 +848,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 +857,7 @@ client return else H.verbs += verb - + else if(href_list["remverb"]) if(!check_rights(R_DEBUG)) return @@ -872,7 +875,7 @@ client else H.verbs -= verb - + else if(href_list["fix_nano"]) if(!check_rights(R_DEBUG)) return @@ -881,11 +884,11 @@ 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" 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/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 590df9cd07..83ca646d89 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -690,21 +690,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/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/objective.dm b/code/game/gamemodes/objective.dm index 9ff5608e2d..d01e0e3506 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -649,17 +649,6 @@ datum/objective/capture 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[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/secbot.dm b/code/game/machinery/bots/secbot.dm index 094f3ff700..8868914872 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 04f5efa518..8f1eff7d63 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -77,9 +77,10 @@ if ((M.stat != 2) || (!M.client)) continue //They need a brain! - if ((istype(M, /mob/living/carbon/human)) && (!M.has_brain())) - 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 47eb7ca558..3897ee1d08 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -338,7 +338,12 @@ scantemp = "Error: Unable to locate valid genetic data." return if (!subject.has_brain()) - scantemp = "Error: No signs of intelligence detected." + 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/turrets.dm b/code/game/machinery/turrets.dm index 5ad0ecae56..d3e9b81e15 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 [] has slashed at []!", user, 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 b4155d6fca..c7f8fadfcb 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -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) 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 3080c05f09..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/organ/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/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 a45e2436b8..76ac4b18ac 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 @@ -30,15 +30,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 2bda55b93f..d6e461b4c1 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 @@ -247,49 +238,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 @@ -576,29 +524,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 @@ -629,32 +557,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/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..46b1beef78 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -141,10 +141,6 @@ 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 \[ slime: Baby, 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..d0cc41da62 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -284,10 +284,6 @@ 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 ) @@ -2205,11 +2201,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/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/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..b0ffe74fe6 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,105 @@ 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) + + world << "Got through checks, transmitting." + + 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 214c091c3e..0cb28d1086 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -1,210 +1,90 @@ -#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 + + var/adult_form + var/dead_icon + var/amount_grown = 0 + var/max_grown = 10 + var/time_of_birth + var/co2overloadtime = null + var/temperature_resistance = T0C+75 + var/language + +/mob/living/carbon/alien/New() + + 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 +//This is fine, works the same as a human +/mob/living/carbon/alien/Bump(atom/movable/AM as mob|obj, yes) -/mob/living/carbon/alien/setDNA() + 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 -/*---------------------------------------- -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/Stat() + ..() + stat(null, "Progress: [amount_grown]/[max_grown]") - -/*---------------------------------------- -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 - -/mob/living/carbon/alien/has_eyes() +/mob/living/carbon/alien/restrained() return 0 -#undef HEAT_DAMAGE_LEVEL_1 -#undef HEAT_DAMAGE_LEVEL_2 -#undef HEAT_DAMAGE_LEVEL_3 +/mob/living/carbon/alien/show_inv(mob/user as mob) + return //Consider adding cuffs and hats to this, for the sake of fun. + +/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..26d236bcaa --- /dev/null +++ b/code/modules/mob/living/carbon/alien/diona/life.dm @@ -0,0 +1,20 @@ +/* TODO + 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) +*/ \ 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/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 6b7752f813..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.has_brain()) - 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 f1910fcfe3..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 || !has_brain()) - 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 deleted file mode 100644 index 97abbdec38..0000000000 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ /dev/null @@ -1,369 +0,0 @@ -//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 || !has_brain()) - 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 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..5c0ea8ed1f --- /dev/null +++ b/code/modules/mob/living/carbon/alien/life.dm @@ -0,0 +1,63 @@ +// Alien larva are quite simple. +/mob/living/carbon/alien/Life() + + set invisibility = 0 + set background = 1 + + if (monkeyizing) + return + + ..() + + if (stat != DEAD) //still breathing + + // GROW! + update_progression() + + // Radiation. + handle_mutations_and_radiation() + + // Chemicals in the body + handle_chemicals_in_body() + + blinded = null + + handle_environment() + + //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_environment(enviroment) + //TODO: Work out if larvae breathe/suffer from pressure/suffer from heat. + if(!enviroment) + return + +/mob/living/carbon/alien/proc/handle_regular_status_updates() + // TODO: sleep, blind, stunned, paralyzed? + return + +/mob/living/carbon/alien/proc/handle_regular_hud_updates() + return //TODO: Not sure what to do with this yet. \ No newline at end of file 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..794078a3b3 --- /dev/null +++ b/code/modules/mob/living/carbon/alien/update_icons.dm @@ -0,0 +1,22 @@ +/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 (handcuffed || legcuffed) + icon_state = "[initial(icon_state)][state]_cuff" + 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/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm index 5ee424bd8d..f17bfa5d73 100644 --- a/code/modules/mob/living/carbon/brain/posibrain.dm +++ b/code/modules/mob/living/carbon/brain/posibrain.dm @@ -132,7 +132,6 @@ 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 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..1687016f85 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) @@ -427,7 +431,7 @@ //Brain slug proc for voluntary removal of control. /mob/living/carbon/proc/release_control() - set category = "Alien" + set category = "Abilities" set name = "Release Control" set desc = "Release control of your host's body." @@ -447,7 +451,7 @@ //Brain slug proc for tormenting the host. /mob/living/carbon/proc/punish_host() - set category = "Alien" + set category = "Abilities" set name = "Torment host" set desc = "Punish your host with agony." @@ -470,7 +474,7 @@ return 0 /mob/living/carbon/proc/spawn_larvae() - set category = "Alien" + set category = "Abilities" set name = "Reproduce" set desc = "Spawn several young." @@ -491,4 +495,4 @@ else src << "You do not have enough chemicals stored to reproduce." - return + return \ No newline at end of file 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..c477d26031 --- /dev/null +++ b/code/modules/mob/living/carbon/carbon_powers.dm @@ -0,0 +1,39 @@ +//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.") 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..185a3b60c7 --- /dev/null +++ b/code/modules/mob/living/carbon/human/alien/alien_species.dm @@ -0,0 +1,251 @@ +//TODO: Generalize some kind of power pool so that other races can use it. +//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 + 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 | RAD_ABSORB | 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 + ) + + 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) + + if(!H.loc) + return + + if(locate(/obj/effect/alien/weeds) in H.loc) + 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" + + 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 + ) + + 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 + ) + + 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 + ) + + 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" + + 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 + ) + + 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 c672950a18..6196e71159 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -240,7 +240,7 @@ if(getBrainLoss() >= 60) msg += "[t_He] [t_has] a stupid expression on [t_his] face.\n" - if(has_brain() && stat != DEAD) + 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) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 3f7faeac8e..ba433afb17 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) @@ -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,7 @@ spawn(0) update_icons() + vessel.add_reagent("blood",560-vessel.total_volume) fixblood() if(species) @@ -1381,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 @@ -1569,6 +1404,16 @@ 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"] @@ -1581,4 +1426,4 @@ var/datum/organ/internal/eyes = internal_organs_by_name["eyes"] if(eyes && istype(eyes) && !eyes.status & ORGAN_CUT_AWAY) return 1 - return 0 + return 0 \ No newline at end of file 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 8b4e010d4b..602c00edf6 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,9 +10,15 @@ 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 RAD_ABSORB or 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 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 dd02d3c17d..c4dec0abe8 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -638,9 +638,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) @@ -1084,7 +1088,7 @@ handle_organs() //Optimized. handle_blood() - if(health <= config.health_threshold_dead || !has_brain()) + if(health <= config.health_threshold_dead || (species.has_organ["brain"] && !has_brain())) death() blinded = 1 silent = 0 @@ -1660,8 +1664,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..2b9878e345 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 @@ -38,6 +41,12 @@ 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 + 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/species.dm b/code/modules/mob/living/carbon/human/species.dm similarity index 52% rename from code/modules/mob/living/carbon/species.dm rename to code/modules/mob/living/carbon/human/species.dm index d5e8a16761..d2727d94d3 100644 --- a/code/modules/mob/living/carbon/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -3,24 +3,43 @@ */ /datum/species - var/name // Species name. - + 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/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/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. + + // 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. @@ -54,6 +73,8 @@ 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, @@ -63,12 +84,30 @@ "appendix" = /datum/organ/internal/appendix, "eyes" = /datum/organ/internal/eyes ) + /datum/species/New() - unarmed = new unarmed_type() + 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. - //This is a basic humanoid limb setup. + + //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"]) @@ -81,7 +120,6 @@ 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() for(var/organ in has_organ) var/organ_type = has_organ[organ] H.internal_organs_by_name[organ] = new organ_type(H) @@ -99,19 +137,60 @@ 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. +/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.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 +// 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" @@ -130,8 +209,10 @@ 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 @@ -191,7 +272,10 @@ 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. + unarmed_type = /datum/unarmed_attack/claws/strong + secondary_unarmed_type = /datum/unarmed_attack/bite/strong + + speech_sounds = list('sound/voice/shriek1.ogg') warning_low_pressure = 50 hazard_low_pressure = 0 @@ -204,6 +288,7 @@ breath_type = "nitrogen" poison_type = "oxygen" + insulated = 1 flags = NO_SCAN @@ -212,23 +297,24 @@ reagent_tag = IS_VOX -/datum/species/vox/handle_post_spawn(var/mob/living/carbon/human/H) + inherent_verbs = list( + /mob/living/carbon/human/proc/leap + ) - 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 - ..() + 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 + ) /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 @@ -258,13 +344,29 @@ 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/monkey/diona + primitive = /mob/living/carbon/alien/diona + slowdown = 7 + + 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 @@ -279,7 +381,7 @@ 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 + flags = IS_WHITELISTED | NO_BREATHE | REQUIRE_LIGHT | NO_SCAN | IS_PLANT | RAD_ABSORB | NO_BLOOD | NO_PAIN | NO_SLIP blood_color = "#004400" flesh_color = "#907E4A" @@ -288,17 +390,16 @@ /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)) + var/mob/living/carbon/alien/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) + for(var/mob/living/carbon/alien/diona/D in H.contents) if(D.client) D.loc = H.loc else @@ -335,18 +436,65 @@ blood_color = "#1F181F" flesh_color = "#575757" -//Species unarmed attacks + 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") @@ -360,6 +508,47 @@ 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... +/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..ad609cad73 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -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 85fdb33a8d..df9d22c5dc 100644 --- a/code/modules/mob/living/carbon/metroid/metroid.dm +++ b/code/modules/mob/living/carbon/metroid/metroid.dm @@ -54,6 +54,9 @@ 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) @@ -274,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 @@ -447,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 @@ -615,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\"." 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 44a7e7a259..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-- diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index 7bb9af2a15..2d9abfa246 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) @@ -301,78 +291,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/living.dm b/code/modules/mob/living/living.dm index a4e5e0586f..8fc440c921 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,7 @@ 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. + if(HULK in usr.mutations) //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 +647,7 @@ 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. + if(HULK in usr.mutations) //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 +698,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,6 +788,9 @@ 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 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_defines.dm b/code/modules/mob/mob_defines.dm index 86f3724fb5..ca3a2b8551 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/drowsyness = 0.0//Carbon var/dizziness = 0//Carbon @@ -210,8 +208,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/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 2307d00bcb..77ec2c1305 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -197,14 +197,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/organ_alien.dm b/code/modules/organs/organ_alien.dm new file mode 100644 index 0000000000..5d1d487423 --- /dev/null +++ b/code/modules/organs/organ_alien.dm @@ -0,0 +1,164 @@ +//DIONA ORGANS. +/datum/organ/internal/diona + removed_type = /obj/item/organ/diona + +/datum/organ/internal/diona/process() + return + +/datum/organ/internal/diona/nutrients + name = "nutrient vessel" + parent_organ = "chest" + +/datum/organ/internal/diona/strata + name = "neural strata" + parent_organ = "chest" + +/datum/organ/internal/diona/node + name = "receptor node" + parent_organ = "head" + +/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" + +/obj/item/organ/diona + name = "diona nymph" + icon = 'icons/obj/objects.dmi' + icon_state = "nymph" + +/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) + +//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" \ No newline at end of file diff --git a/code/modules/organs/organ_internal.dm b/code/modules/organs/organ_internal.dm index e8c7acbfbf..9c26f814e9 100644 --- a/code/modules/organs/organ_internal.dm +++ b/code/modules/organs/organ_internal.dm @@ -2,7 +2,7 @@ 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 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/surgery/slimes.dm b/code/modules/surgery/slimes.dm index d962cfd3f4..048c6d3e3c 100644 --- a/code/modules/surgery/slimes.dm +++ b/code/modules/surgery/slimes.dm @@ -20,7 +20,7 @@ max_duration = 50 can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - return ..() && target.core_removal_stage == 0 + 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].", \ @@ -46,7 +46,7 @@ max_duration = 50 can_use(mob/living/user, mob/living/carbon/slime/target, target_zone, obj/item/tool) - return ..() && target.core_removal_stage == 1 + 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].", \ diff --git a/code/setup.dm b/code/setup.dm index cd455dda5b..fd44b399ca 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -741,27 +741,28 @@ 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 IS_PLANT 2048 +#define IS_WHITELISTED 4096 +#define IS_SYNTHETIC 8192 -#define RAD_ABSORB 4096 -#define REQUIRE_LIGHT 8192 - -#define IS_SYNTHETIC 16384 +#define RAD_ABSORB 16384 +#define REQUIRE_LIGHT 32768 //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 +827,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. 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/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..24b09492de 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