diff --git a/code/defines/mob/dead/observer.dm b/code/defines/mob/dead/observer.dm
index 2cecfcf184..f5f395f1f8 100644
--- a/code/defines/mob/dead/observer.dm
+++ b/code/defines/mob/dead/observer.dm
@@ -5,7 +5,6 @@
icon_state = "ghost"
layer = 4
density = 0
- stat = 2
canmove = 0
blinded = 0
anchored = 1 // don't get pushed around
diff --git a/code/defines/mob/living/carbon/alien_humanoid.dm b/code/defines/mob/living/carbon/alien_humanoid.dm
index 3dafed16b0..2dee5fb2ac 100644
--- a/code/defines/mob/living/carbon/alien_humanoid.dm
+++ b/code/defines/mob/living/carbon/alien_humanoid.dm
@@ -14,6 +14,7 @@
/mob/living/carbon/alien/humanoid/hunter
name = "alien hunter"
caste = "h"
+ maxHealth = 150
health = 150
storedPlasma = 100
max_plasma = 150
@@ -22,6 +23,7 @@
/mob/living/carbon/alien/humanoid/sentinel
name = "alien sentinel"
caste = "s"
+ maxHealth = 125
health = 125
storedPlasma = 100
max_plasma = 250
@@ -30,12 +32,14 @@
/mob/living/carbon/alien/humanoid/drone
name = "alien drone"
caste = "d"
+ maxHealth = 100
health = 100
icon_state = "aliend_s"
/mob/living/carbon/alien/humanoid/queen
name = "alien queen"
caste = "q"
+ maxHealth = 250
health = 250
icon_state = "alienq_s"
nopush = 1
diff --git a/code/defines/mob/living/carbon/alien_larva.dm b/code/defines/mob/living/carbon/alien_larva.dm
index 4c62e4a40b..6e11728031 100644
--- a/code/defines/mob/living/carbon/alien_larva.dm
+++ b/code/defines/mob/living/carbon/alien_larva.dm
@@ -3,6 +3,7 @@
icon_state = "larva"
pass_flags = PASSTABLE
+ maxHealth = 25
health = 25
var/amount_grown = 0
\ No newline at end of file
diff --git a/code/defines/mob/living/carbon/metroid.dm b/code/defines/mob/living/carbon/metroid.dm
index ca3d34b1de..ac6ddf9300 100644
--- a/code/defines/mob/living/carbon/metroid.dm
+++ b/code/defines/mob/living/carbon/metroid.dm
@@ -11,6 +11,7 @@
layer = 5
+ maxHealth = 150
health = 150
gender = NEUTER
diff --git a/code/defines/mob/living/silicon/robot.dm b/code/defines/mob/living/silicon/robot.dm
index da5910a022..d7031bcfae 100644
--- a/code/defines/mob/living/silicon/robot.dm
+++ b/code/defines/mob/living/silicon/robot.dm
@@ -2,6 +2,7 @@
name = "Cyborg"
icon = 'robots.dmi'//
icon_state = "robot"
+ maxHealth = 300
health = 300
#define BORGMESON 1
diff --git a/code/game/dna.dm b/code/game/dna.dm
index 8056712421..ad03448564 100644
--- a/code/game/dna.dm
+++ b/code/game/dna.dm
@@ -840,7 +840,7 @@
dat = text("[]
Main Menu", src.temphtml, src)
else
if (src.connected) //Is something connected?
- var/mob/occupant = src.connected.occupant
+ var/mob/living/occupant = src.connected.occupant
dat = "Occupant Statistics:
" //Blah obvious
if(occupant && occupant.dna) //is there REALLY someone in there?
if(NOCLONE in occupant.mutations)
diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm
index f2168e8a3b..cd86642da0 100644
--- a/code/game/gamemodes/changeling/changeling_powers.dm
+++ b/code/game/gamemodes/changeling/changeling_powers.dm
@@ -632,7 +632,7 @@ Tarjan shit, not recoding this -Sieve{R}*/
var/list/victims = list()
for(var/mob/living/carbon/C in oview(usr.changeling.sting_range))
victims += C
- var/mob/T = input(usr, "Who do you wish to sting?") as null | anything in victims
+ var/mob/living/carbon/T = input(usr, "Who do you wish to sting?") as null | anything in victims
if(T && T in view(usr.changeling.sting_range))
if(usr.stat)
@@ -650,10 +650,7 @@ Tarjan shit, not recoding this -Sieve{R}*/
feedback_add_details("changeling_powers","SS")
if(!T.changeling)
- // T << "You feel a small prick and a burning sensation in your throat."
T.silent += 30
- //else
- // T << "You feel a small prick."
usr.verbs -= /client/proc/changeling_silence_sting
@@ -984,7 +981,7 @@ Tarjan shit, not recoding this -Sieve{R}*/
var/list/victims = list()
for(var/mob/living/carbon/C in oview(usr.changeling.sting_range))
victims += C
- var/mob/T = input(usr, "Who do you wish to sting?") as null | anything in victims
+ var/mob/living/carbon/T = input(usr, "Who do you wish to sting?") as null | anything in victims
if(T && T in view(usr.changeling.sting_range))
diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm
index 64fb906ef3..968ff6e6ea 100644
--- a/code/game/gamemodes/gameticker.dm
+++ b/code/game/gamemodes/gameticker.dm
@@ -162,15 +162,17 @@ var/global/datum/controller/gameticker/ticker
M.buckled = temp_buckle
if(M.client)
M.client.screen += cinematic
+
+ var/mob/living/L = M
switch(M.z)
if(0) //inside a crate or something
- var/turf/T = get_turf(M)
+ var/turf/T = get_turf(L)
if(T && T.z==1) //we don't use M.death(0) because it calls a for(/mob) loop and
- M.health = 0
- M.stat = DEAD
+ L.health = 0
+ L.stat = DEAD
if(1) //on a z-level 1 turf.
- M.health = 0
- M.stat = DEAD
+ L.health = 0
+ L.stat = DEAD
//Now animate the cinematic
switch(station_missed)
diff --git a/code/game/gamemodes/wizard/spells.dm b/code/game/gamemodes/wizard/spells.dm
index 7a303c31c4..df62971314 100644
--- a/code/game/gamemodes/wizard/spells.dm
+++ b/code/game/gamemodes/wizard/spells.dm
@@ -17,7 +17,6 @@
usr.verbs += /client/proc/blind
usr.whisper("STI KALY")
- // usr.spellvoice()
var/obj/effect/overlay/B = new /obj/effect/overlay( M.loc )
B.icon_state = "blspell"
@@ -50,7 +49,6 @@
if(!usr.casting()) return
usr.say("FORTI GY AMA")
- usr.spellvoice()
for (var/mob/living/M as mob in oview())
spawn(0)
@@ -162,7 +160,6 @@
var/forcefield
usr.whisper("TARCOL MINTI ZHERI")
-// usr.spellvoice()
forcefield = new /obj/effect/forcefield(locate(usr.x,usr.y,usr.z))
spawn (300)
@@ -185,7 +182,6 @@
usr.verbs += /client/proc/fireball
usr.say("ONI SOMA")
- // usr.spellvoice()
var/obj/effect/overlay/A = new /obj/effect/overlay( usr.loc )
A.icon_state = "fireball"
@@ -220,7 +216,6 @@
usr.verbs += /client/proc/knock
usr.whisper("AULIE OXIN FIERA")
-// usr.spellvoice()
for(var/obj/machinery/door/G in oview(3))
spawn(1)
@@ -242,7 +237,6 @@
usr.verbs += /mob/proc/kill
usr.say("EI NATH")
- usr.spellvoice()
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(4, 1, M)
@@ -265,7 +259,6 @@
usr.verbs += /mob/proc/tech
usr.say("NEC CANTIO")
- usr.spellvoice()
empulse(src, 6, 10)
return
@@ -328,7 +321,6 @@
var/area/thearea = teleportlocs[A]
usr.say("SCYAR NILA [uppertext(A)]")
- usr.spellvoice()
var/datum/effect/effect/system/harmless_smoke_spread/smoke = new /datum/effect/effect/system/harmless_smoke_spread()
smoke.set_up(5, 0, usr.loc)
@@ -486,7 +478,6 @@
usr.verbs += /client/proc/mutate
usr.say("BIRUZ BENNAR")
- usr.spellvoice()
usr << text("\blue You feel strong! You feel pressure building behind your eyes!")
if (!(HULK in usr.mutations))
diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm
index b7c986e0ec..9a86726fe0 100644
--- a/code/game/gamemodes/wizard/wizard.dm
+++ b/code/game/gamemodes/wizard/wizard.dm
@@ -290,13 +290,3 @@ Made a proc so this is not repeated 14 (or more) times.*/
return 0
else
return 1
-
-/*Checks if the wizard is a mime and male/female.
-Outputs the appropriate voice if the user is not a mime.
-Made a proc here so it's not repeated several times.*/
-/mob/proc/spellvoice()
-// if(!usr.miming)No longer necessary.
-// if(usr.gender=="male")
-// playsound(usr.loc, pick('null.ogg','null.ogg'), 100, 1)
-// else
-// playsound(usr.loc, pick('null.ogg','null.ogg'), 100, 1)
diff --git a/code/game/jobs/jobprocs.dm b/code/game/jobs/jobprocs.dm
index 813d3353d9..62b2b7c4ae 100644
--- a/code/game/jobs/jobprocs.dm
+++ b/code/game/jobs/jobprocs.dm
@@ -8,15 +8,20 @@
if(usr.stat)
usr << "Not when you're incapicated."
return
- if(!usr.miming)
+ if(!ishuman(usr))
+ return
+
+ var/mob/living/carbon/human/H = usr
+
+ if(!H.miming)
usr << "You still haven't atoned for your speaking transgression. Wait."
return
- usr.verbs -= /client/proc/mimewall
+ H.verbs -= /client/proc/mimewall
spawn(300)
- usr.verbs += /client/proc/mimewall
- for (var/mob/V in viewers(usr))
+ H.verbs += /client/proc/mimewall
+ for (var/mob/V in viewers(H))
if(V!=usr)
- V.show_message("[usr] looks as if a wall is in front of them.", 3, "", 2)
+ V.show_message("[H] looks as if a wall is in front of them.", 3, "", 2)
usr << "You form a wall in front of yourself."
var/obj/effect/forcefield/F = new /obj/effect/forcefield(locate(usr.x,usr.y,usr.z))
F.icon_state = "empty"
@@ -30,10 +35,15 @@
set category = "Mime"
set name = "Speech"
set desc = "Toggle your speech."
- if(usr.miming)
- usr.miming = 0
+ if(!ishuman(usr))
+ return
+
+ var/mob/living/carbon/human/H = usr
+
+ if(H.miming)
+ H.miming = 0
else
- usr << "You'll have to wait if you want to atone for your sins."
+ H << "You'll have to wait if you want to atone for your sins."
spawn(3000)
- usr.miming = 1
+ H.miming = 1
return
diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm
index ff40d49adc..b45966a9ab 100644
--- a/code/game/machinery/turrets.dm
+++ b/code/game/machinery/turrets.dm
@@ -3,11 +3,12 @@
var/list/turretTargets = list()
/area/turret_protected/proc/subjectDied(target)
- if( ismob(target) )
+ if( isliving(target) )
if( !issilicon(target) )
- if( target:stat )
- if( target in turretTargets )
- src.Exited(target)
+ var/mob/living/L = target
+ if( L.stat )
+ if( L in turretTargets )
+ src.Exited(L)
/area/turret_protected/Entered(O)
diff --git a/code/game/objects/devices/PDA/uplink.dm b/code/game/objects/devices/PDA/uplink.dm
deleted file mode 100644
index 1954e9b1be..0000000000
--- a/code/game/objects/devices/PDA/uplink.dm
+++ /dev/null
@@ -1,250 +0,0 @@
-/obj/item/weapon/integrated_uplink
- name = "uplink module"
- desc = "An electronic uplink system of unknown origin."
- icon = 'module.dmi'
- icon_state = "power_mod"
- var/uses = 10
- var/obj/item/device/pda/hostpda = null
- var/orignote = null //Restore original notes when locked.
- var/active = 0 //Are we currently active??
- var/menu_message = ""
- var/lock_code = "password" //What's the password?
-
-//Communicate with traitor through the PDA's note function.
-/obj/item/weapon/integrated_uplink/proc/print_to_host(var/text)
- if (isnull(hostpda))
- return
- hostpda.note = text
-
- for (var/mob/M in viewers(1, hostpda.loc))
- if (M.client && M.machine == hostpda)
- hostpda.attack_self(M)
-
- return
-
-//Let's build a menu!
-/obj/item/weapon/integrated_uplink/proc/generate_menu()
- menu_message = "Syndicate Uplink Console:
"
- menu_message += "Tele-Crystals left: [uses]
"
- menu_message += "
"
+ if(inventory_head)
+ dat += "
Head: [inventory_head] (Remove)"
+ else
+ dat += "
Head: Nothing"
+ if(inventory_back)
+ dat += "
Back: [inventory_back] (Remove)"
+ else
+ dat += "
Back: Nothing"
+
+ user << browse(dat, text("window=mob[];size=325x500", name))
+ onclose(user, "mob[real_name]")
+ return
+
+/mob/living/simple_animal/corgi/attackby(var/obj/item/O as obj, var/mob/user as mob)
+ if(inventory_head && inventory_back)
+ //helmet and armor = 100% protection
+ if( istype(inventory_head,/obj/item/clothing/head/helmet) && istype(inventory_back,/obj/item/clothing/suit/armor) )
+ if( O.force )
+ usr << "\red This animal is wearing too much armor. You can't cause /him any damage."
+ for (var/mob/M in viewers(src, null))
+ M.show_message("\red \b [user] hits [src] with the [O], however [src] is too armored.")
+ else
+ usr << "\red This animal is wearing too much armor. You can't reach its skin."
+ for (var/mob/M in viewers(src, null))
+ M.show_message("\red [user] gently taps [src] with the [O]. ")
+ if(prob(15))
+ emote("looks at [user] with [pick("an amused","an annoyed","a confused","a resentful", "a happy", "an excited")] expression on \his face")
+ return
+ ..()
+
+/mob/living/simple_animal/corgi/Topic(href, href_list)
+ if(usr.stat) return
+
+ //Removing from inventory
+ if(href_list["remove_inv"])
+ if(get_dist(src,usr) > 1 || !(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr)))
+ return
+ var/remove_from = href_list["remove_inv"]
+ switch(remove_from)
+ if("head")
+ if(inventory_head)
+ name = real_name
+ desc = initial(desc)
+ speak = list("YAP", "Woof!", "Bark!", "AUUUUUU")
+ speak_emote = list("barks", "woofs")
+ emote_hear = list("barks", "woofs", "yaps","pants")
+ emote_see = list("shakes its head", "shivers")
+ desc = "It's a corgi."
+ src.sd_SetLuminosity(0)
+ inventory_head.loc = src.loc
+ inventory_head = null
+ else
+ usr << "\red There is nothing to remove from its [remove_from]."
+ return
+ if("back")
+ if(inventory_back)
+ inventory_back.loc = src.loc
+ inventory_back = null
+ else
+ usr << "\red There is nothing to remove from its [remove_from]."
+ return
+
+ //show_inv(usr) //Commented out because changing Ian's name and then calling up his inventory opens a new inventory...which is annoying.
+
+ //Adding things to inventory
+ else if(href_list["add_inv"])
+ if(get_dist(src,usr) > 1 || !(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr)))
+ return
+ var/add_to = href_list["add_inv"]
+ if(!usr.get_active_hand())
+ usr << "\red You have nothing in your hand to put on its [add_to]."
+ return
+ switch(add_to)
+ if("head")
+ if(inventory_head)
+ usr << "\red It's is already wearing something."
+ return
+ else
+ var/obj/item/item_to_add = usr.get_active_hand()
+ if(!item_to_add)
+ return
+
+ //Corgis are supposed to be simpler, so only a select few objects can actually be put
+ //to be compatible with them. The objects are below.
+ //Many hats added, Some will probably be removed, just want to see which ones are popular.
+
+ var/list/allowed_types = list(
+ /obj/item/clothing/head/helmet,
+ /obj/item/clothing/glasses/sunglasses,
+ /obj/item/clothing/head/caphat,
+ /obj/item/clothing/head/collectable/captain,
+ /obj/item/clothing/head/that,
+ /obj/item/clothing/head/that,
+ /obj/item/clothing/head/kitty,
+ /obj/item/clothing/head/collectable/kitty,
+ /obj/item/clothing/head/rabbitears,
+ /obj/item/clothing/head/collectable/rabbitears,
+ /obj/item/clothing/head/beret,
+ /obj/item/clothing/head/collectable/beret,
+ /obj/item/clothing/head/det_hat,
+ /obj/item/clothing/head/nursehat,
+ /obj/item/clothing/head/pirate,
+ /obj/item/clothing/head/collectable/pirate,
+ /obj/item/clothing/head/ushanka,
+ /obj/item/clothing/head/chefhat,
+ /obj/item/clothing/head/collectable/chef,
+ /obj/item/clothing/head/collectable/police,
+ /obj/item/clothing/head/wizard/fake,
+ /obj/item/clothing/head/wizard,
+ /obj/item/clothing/head/collectable/wizard,
+ /obj/item/clothing/head/hardhat,
+ /obj/item/clothing/head/collectable/hardhat,
+ /obj/item/clothing/head/hardhat/white,
+ /obj/item/weapon/bedsheet,
+ /obj/item/clothing/head/helmet/space/santahat,
+ /obj/item/clothing/head/collectable/paper,
+ /obj/item/clothing/head/soft
+ )
+
+ if( ! ( item_to_add.type in allowed_types ) )
+ usr << "\red It doesn't seem too keen on wearing that item."
+ return
+
+ usr.drop_item()
+ item_to_add.loc = src
+ src.inventory_head = item_to_add
+ regenerate_icons()
+
+ //Various hats and items (worn on his head) change Ian's behaviour. His attributes are reset when a HAT is removed.
+
+
+ switch(inventory_head && inventory_head.type)
+ if(/obj/item/clothing/head/caphat, /obj/item/clothing/head/collectable/captain)
+ name = "Captain [real_name]"
+ desc = "Probably better than the last captain."
+ if(/obj/item/clothing/head/kitty, /obj/item/clothing/head/collectable/kitty)
+ name = "Runtime"
+ emote_see = list("coughs up a furball", "stretches")
+ emote_hear = list("purrs")
+ speak = list("Purrr", "Meow!", "MAOOOOOW!", "HISSSSS", "MEEEEEEW")
+ desc = "It's a cute little kitty-cat! ... wait ... what the hell?"
+ if(/obj/item/clothing/head/rabbitears, /obj/item/clothing/head/collectable/rabbitears)
+ name = "Hoppy"
+ emote_see = list("twitches its nose", "hops around a bit")
+ desc = "This is hoppy. It's a corgi-...urmm... bunny rabbit"
+ if(/obj/item/clothing/head/beret, /obj/item/clothing/head/collectable/beret)
+ name = "Yann"
+ desc = "Mon dieu! C'est un chien!"
+ speak = list("le woof!", "le bark!", "JAPPE!!")
+ emote_see = list("cowers in fear", "surrenders", "plays dead","looks as though there is a wall in front of /him")
+ if(/obj/item/clothing/head/det_hat)
+ name = "Detective [real_name]"
+ desc = "[name] sees through your lies..."
+ emote_see = list("investigates the area","sniffs around for clues","searches for scooby snacks")
+ if(/obj/item/clothing/head/nursehat)
+ name = "Nurse [real_name]"
+ desc = "[name] needs 100cc of beef jerky...STAT!"
+ if(/obj/item/clothing/head/pirate, /obj/item/clothing/head/collectable/pirate)
+ name = "'[pick("Ol'","Scurvy","Black","Rum","Gammy","Bloody","Gangrene","Death","Long-John")] [pick("kibble","leg","beard","tooth","poop-deck","Threepwood","Le Chuck","corsair","Silver","Crusoe")]'"
+ desc = "Yaarghh!! Thar' be a scurvy dog!"
+ emote_see = list("hunts for treasure","stares coldly...","gnashes his tiny corgi teeth")
+ emote_hear = list("growls ferociously", "snarls")
+ speak = list("Arrrrgh!!","Grrrrrr!")
+ if(/obj/item/clothing/head/ushanka)
+ name = "[pick("Comrade","Commissar","Glorious Leader")] [real_name]"
+ desc = "A follower of Karl Barx."
+ emote_see = list("contemplates the failings of the capitalist economic model", "ponders the pros and cons of vangaurdism")
+ if(/obj/item/clothing/head/collectable/police)
+ name = "Officer [real_name]"
+ emote_see = list("drools","looks for donuts")
+ desc = "Stop right there criminal scum!"
+ if(/obj/item/clothing/head/wizard/fake, /obj/item/clothing/head/wizard, /obj/item/clothing/head/collectable/wizard)
+ name = "Grandwizard [real_name]"
+ speak = list("YAP", "Woof!", "Bark!", "AUUUUUU", "EI NATH!")
+ if(/obj/item/weapon/bedsheet)
+ name = "\improper Ghost"
+ speak = list("WoooOOOooo~","AUUUUUUUUUUUUUUUUUU")
+ emote_see = list("stumbles around", "shivers")
+ emote_hear = list("howls","groans")
+ desc = "Spooky!"
+ if(/obj/item/clothing/head/helmet/space/santahat)
+ name = "Rudolph the Red-Nosed Corgi"
+ emote_hear = list("barks christmas songs", "yaps")
+ desc = "He has a very shiny nose."
+ src.sd_SetLuminosity(6)
+ if(/obj/item/clothing/head/soft)
+ name = "Corgi Tech [real_name]"
+ speak = list("Needs a stamp!", "Request DENIED!", "Fill these out in triplicate!")
+ desc = "The reason your yellow gloves have chew-marks."
+
+ if("back")
+ if(inventory_back)
+ usr << "\red It's already wearing something."
+ return
+ else
+ var/obj/item/item_to_add = usr.get_active_hand()
+ if(!item_to_add)
+ return
+
+ //Corgis are supposed to be simpler, so only a select few objects can actually be put
+ //to be compatible with them. The objects are below.
+
+ var/list/allowed_types = list(
+ /obj/item/clothing/suit/armor/vest,
+ /obj/item/device/radio
+ )
+
+ if( ! ( item_to_add.type in allowed_types ) )
+ usr << "\red This object won't fit."
+ return
+
+ usr.drop_item()
+ item_to_add.loc = src
+ src.inventory_back = item_to_add
+ regenerate_icons()
+
+ //show_inv(usr) //Commented out because changing Ian's name and then calling up his inventory opens a new inventory...which is annoying.
+ else
+ ..()
+
+//IAN! SQUEEEEEEEEE~
+/mob/living/simple_animal/corgi/Ian
+ name = "Ian"
+ real_name = "Ian" //Intended to hold the name without altering it.
+ gender = "male"
+ desc = "It's a corgi."
+ var/turns_since_scan = 0
+ var/obj/movement_target
+ response_help = "pets"
+ response_disarm = "gently pushes aside"
+ response_harm = "kicks"
+
+/mob/living/simple_animal/corgi/Ian/Life()
+ ..()
+
+ //Feeding, chasing food, FOOOOODDDD
+ if(alive && !resting && !buckled)
+ turns_since_scan++
+ if(turns_since_scan > 5)
+ turns_since_scan = 0
+ if((movement_target) && !(isturf(movement_target.loc) || ishuman(movement_target.loc) ))
+ movement_target = null
+ stop_automated_movement = 0
+ if( !movement_target || !(movement_target.loc in oview(src, 3)) )
+ movement_target = null
+ stop_automated_movement = 0
+ for(var/obj/item/weapon/reagent_containers/food/snacks/S in oview(src,3))
+ if(isturf(S.loc) || ishuman(S.loc))
+ movement_target = S
+ break
+ if(movement_target)
+ stop_automated_movement = 1
+ step_to(src,movement_target,1)
+ sleep(3)
+ step_to(src,movement_target,1)
+ sleep(3)
+ step_to(src,movement_target,1)
+
+ if(movement_target) //Not redundant due to sleeps, Item can be gone in 6 decisecomds
+ if (movement_target.loc.x < src.x)
+ dir = WEST
+ else if (movement_target.loc.x > src.x)
+ dir = EAST
+ else if (movement_target.loc.y < src.y)
+ dir = SOUTH
+ else if (movement_target.loc.y > src.y)
+ dir = NORTH
+ else
+ dir = SOUTH
+
+ if(isturf(movement_target.loc) )
+ movement_target.attack_animal(src)
+ else if(ishuman(movement_target.loc) )
+ if(prob(20))
+ emote("stares at the [movement_target] that [movement_target.loc] has with a sad puppy-face")
+
+ if(prob(1))
+ emote(pick("dances around","chases its tail"))
+ spawn(0)
+ for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
+ dir = i
+ sleep(1)
+
+/obj/item/weapon/reagent_containers/food/snacks/meat/corgi
+ name = "Corgi meat"
+ desc = "Tastes like... well you know..."
+
+/mob/living/simple_animal/corgi/Ian/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.nopush)
+ now_pushing = 0
+ return
+
+ tmob.LAssailant = src
+ now_pushing = 0
+ ..()
+ if (!( istype(AM, /atom/movable) ))
+ return
+ if (!( now_pushing ))
+ now_pushing = 1
+ if (!( AM.anchored ))
+ var/t = get_dir(src, AM)
+ if (istype(AM, /obj/structure/window))
+ if(AM:ini_dir == NORTHWEST || AM:ini_dir == NORTHEAST || AM:ini_dir == SOUTHWEST || AM:ini_dir == SOUTHEAST)
+ for(var/obj/structure/window/win in get_step(AM,t))
+ now_pushing = 0
+ return
+ step(AM, t)
+ now_pushing = null
+ return
+ return
+//PC stuff-Sieve
+
+/mob/living/simple_animal/corgi/proc/mind_initialize(mob/G)
+ mind = new
+ mind.current = src
+ mind.assigned_role = "Corgi"
+ mind.key = G.key
+
+
+/mob/living/simple_animal/corgi/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri
+ if(istype(O, /obj/item/weapon/newspaper))
+ if(alive)
+ for(var/mob/M in viewers(user, null))
+ if ((M.client && !( M.blinded )))
+ M.show_message("\blue [user] baps [name] on the nose with the rolled up [O]")
+ spawn(0)
+ for(var/i in list(1,2,4,8,4,2,1,2))
+ dir = i
+ sleep(1)
+ else
+ ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/crab.dm b/code/modules/mob/living/simple_animal/crab.dm
new file mode 100644
index 0000000000..53e899c501
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/crab.dm
@@ -0,0 +1,69 @@
+//Look Sir, free crabs!
+/mob/living/simple_animal/crab
+ name = "crab"
+ desc = "Free crabs!"
+ icon = 'mob.dmi'
+ icon_state = "crab"
+ icon_living = "crab"
+ icon_dead = "crab_dead"
+ speak_emote = list("clicks")
+ emote_hear = list("clicks")
+ emote_see = list("clacks")
+ speak_chance = 1
+ turns_per_move = 5
+ meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
+ response_help = "pets the"
+ response_disarm = "gently pushes aside the"
+ response_harm = "stomps the"
+ stop_automated_movement = 1
+ friendly = "pinches"
+
+/mob/living/simple_animal/crab/Life()
+ ..()
+ //CRAB movement
+ if(!ckey && alive)
+ if(isturf(src.loc) && !resting && !buckled) //This is so it only moves if it's not inside a closet, gentics machine, etc.
+ turns_since_move++
+ if(turns_since_move >= turns_per_move)
+ Move(get_step(src,pick(4,8)))
+ turns_since_move = 0
+
+//COFFEE! SQUEEEEEEEEE!
+/mob/living/simple_animal/crab/Coffee
+ name = "Coffee"
+ desc = "It's Coffee, the other pet!"
+ response_help = "pets"
+ response_disarm = "gently pushes aside"
+ response_harm = "stomps"
+
+//LOOK AT THIS - ..()??
+/mob/living/simple_animal/crab/attackby(var/obj/item/O as obj, var/mob/user as mob)
+ if(istype(O, /obj/item/weapon/wirecutters))
+ user << "\red \b This kills the crab."
+ health -= 20
+ Die()
+ if(istype(O, /obj/item/stack/medical))
+ if(alive)
+ var/obj/item/stack/medical/MED = O
+ if(health < maxHealth)
+ if(MED.amount >= 1)
+ health = min(maxHealth, health + MED.heal_brute)
+ MED.amount -= 1
+ if(MED.amount <= 0)
+ del(MED)
+ for(var/mob/M in viewers(src, null))
+ if ((M.client && !( M.blinded )))
+ M.show_message("\blue [user] applies the [MED] on [src]")
+ else
+ user << "\blue this [src] is dead, medical items won't bring it back to life."
+ else
+ if(O.force)
+ health -= O.force
+ for(var/mob/M in viewers(src, null))
+ if ((M.client && !( M.blinded )))
+ M.show_message("\red \b [src] has been attacked with the [O] by [user]. ")
+ else
+ usr << "\red This weapon is ineffective, it does no damage."
+ for(var/mob/M in viewers(src, null))
+ if ((M.client && !( M.blinded )))
+ M.show_message("\red [user] gently taps [src] with the [O]. ")
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/life.dm b/code/modules/mob/living/simple_animal/life.dm
new file mode 100644
index 0000000000..9f7de01ec1
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/life.dm
@@ -0,0 +1,366 @@
+/mob/living/simple_animal
+ name = "animal"
+ var/icon_living = ""
+ var/icon_dead = ""
+ maxHealth = 20
+ var/alive = 1
+ var/list/speak = list()
+ var/list/speak_emote = list()// Emotes while speaking IE: Ian [emote], [text] -- Ian barks, "WOOF!". Spoken text is generated from the speak variable.
+ var/speak_chance = 0
+ var/list/emote_hear = list() //EHearable emotes
+ var/list/emote_see = list() //Unlike speak_emote, the list of things in this variable only show by themselves with no spoken text. IE: Ian barks, Ian yaps
+ health = 20
+ var/turns_per_move = 1
+ var/turns_since_move = 0
+ universal_speak = 1
+ var/meat_amount = 0
+ var/meat_type
+ var/stop_automated_movement = 0 //Use this to temporarely stop random movement or to if you write special movement code for animals.
+
+ //Interaction
+ var/response_help = "You try to help"
+ var/response_disarm = "You try to disarm"
+ var/response_harm = "You try to hurt"
+ var/harm_intent_damage = 3
+
+ //Temperature effect
+ var/minbodytemp = 270
+ var/maxbodytemp = 370
+ var/heat_damage_per_tick = 3 //amount of damage applied if animal's body temperature is higher than maxbodytemp
+ var/cold_damage_per_tick = 2 //same as heat_damage_per_tick, only if the bodytemperature it's lower than minbodytemp
+
+ //Atmos effect - Yes, you can make creatures that require plasma or co2 to survive. N2O is a trace gas and handled separately, hence why it isn't here. It'd be hard to add it. Hard and me don't mix (Yes, yes make all the dick jokes you want with that.) - Errorage
+ var/min_oxy = 5
+ var/max_oxy = 0 //Leaving something at 0 means it's off - has no maximum
+ var/min_tox = 0
+ var/max_tox = 1
+ var/min_co2 = 0
+ var/max_co2 = 5
+ 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
+
+
+ //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
+
+ var/obj/item/device/radio/headset/ears = null
+/mob/living/simple_animal/New()
+ ..()
+ verbs -= /mob/verb/observe
+
+/mob/living/simple_animal/Login()
+ if(src && src.client)
+ src.client.screen = null
+ ..()
+
+/mob/living/simple_animal/Life()
+
+ //Health
+ if(!alive)
+ if(health > 0)
+ icon_state = icon_living
+ alive = 1
+ stat = CONSCIOUS
+ density = 1
+ return
+
+
+ if(health < 1)
+ Die()
+
+ if(health > maxHealth)
+ health = maxHealth
+
+/*
+ // Stun/Weaken
+
+ if (paralysis || stunned || weakened) //Stunned etc.
+ if (stunned > 0)
+ AdjustStunned(-1)
+ stat = 0
+ if (weakened > 0)
+ AdjustWeakened(-1)
+ lying = 1
+ stat = 0
+ if (paralysis > 0)
+ AdjustParalysis(-1)
+ blinded = 1
+ lying = 1
+ stat = 1
+ var/h = hand
+ hand = 0
+ drop_item()
+ hand = 1
+ drop_item()
+ hand = h
+
+ else //Not stunned.
+ lying = 0
+ stat = 0
+
+ if(paralysis || stunned || weakened || buckled)
+ canmove = 0
+ else
+ canmove = 1
+*/
+ //Movement
+ if(!ckey && !stop_automated_movement)
+ if(isturf(src.loc) && !resting && !buckled && canmove) //This is so it only moves if it's not inside a closet, gentics machine, etc.
+ turns_since_move++
+ if(turns_since_move >= turns_per_move)
+ Move(get_step(src,pick(cardinal)))
+ turns_since_move = 0
+
+
+
+
+
+
+
+ //Speaking
+ if(speak_chance)
+ if(prob(speak_chance))
+ if(speak && speak.len)
+ if((emote_hear && emote_hear.len) || (emote_see && emote_see.len))
+ var/length = speak.len
+ if(emote_hear && emote_hear.len)
+ length += emote_hear.len
+ if(emote_see && emote_see.len)
+ length += emote_see.len
+ var/randomValue = rand(1,length)
+ if(randomValue <= speak.len)
+ say(pick(speak))
+ else
+ randomValue -= speak.len
+ if(emote_see && randomValue <= emote_see.len)
+ emote(pick(emote_see),1)
+ else
+ emote(pick(emote_hear),2)
+ else
+ say(pick(speak))
+ else
+ if(!(emote_hear && emote_hear.len) && (emote_see && emote_see.len))
+ emote(pick(emote_see),1)
+ if((emote_hear && emote_hear.len) && !(emote_see && emote_see.len))
+ emote(pick(emote_hear),2)
+ if((emote_hear && emote_hear.len) && (emote_see && emote_see.len))
+ var/length = emote_hear.len + emote_see.len
+ var/pick = rand(1,length)
+ if(pick <= emote_see.len)
+ emote(pick(emote_see),1)
+ else
+ emote(pick(emote_hear),2)
+
+
+ //Atmos
+ var/atmos_suitable = 1
+
+ var/atom/A = src.loc
+ if(isturf(A))
+ var/turf/T = A
+ var/areatemp = T.temperature
+ if( abs(areatemp - bodytemperature) > 50 )
+ var/diff = areatemp - bodytemperature
+ diff = diff / 5
+ //world << "changed from [bodytemperature] by [diff] to [bodytemperature + diff]"
+ bodytemperature += diff
+
+ if(istype(T,/turf/simulated))
+ var/turf/simulated/ST = T
+ if(ST.air)
+ var/tox = ST.air.toxins
+ var/oxy = ST.air.oxygen
+ var/n2 = ST.air.nitrogen
+ var/co2 = ST.air.carbon_dioxide
+
+ if(min_oxy)
+ if(oxy < min_oxy)
+ atmos_suitable = 0
+ if(max_oxy)
+ if(oxy > max_oxy)
+ atmos_suitable = 0
+ if(min_tox)
+ if(tox < min_tox)
+ atmos_suitable = 0
+ if(max_tox)
+ if(tox > max_tox)
+ atmos_suitable = 0
+ if(min_n2)
+ if(n2 < min_n2)
+ atmos_suitable = 0
+ if(max_n2)
+ if(n2 > max_n2)
+ atmos_suitable = 0
+ if(min_co2)
+ if(co2 < min_co2)
+ atmos_suitable = 0
+ if(max_co2)
+ if(co2 > max_co2)
+ atmos_suitable = 0
+
+ //Atmos effect
+ if(bodytemperature < minbodytemp)
+ health -= cold_damage_per_tick
+ else if(bodytemperature > maxbodytemp)
+ health -= heat_damage_per_tick
+
+ if(!atmos_suitable)
+ health -= unsuitable_atoms_damage
+
+/mob/living/simple_animal/Bumped(AM as mob|obj)
+ if(!AM) return
+ if(isturf(src.loc) && !resting && !buckled)
+ if(ismob(AM))
+ var/newamloc = src.loc
+ src.loc = AM:loc
+ AM:loc = newamloc
+ else
+ ..()
+
+/mob/living/simple_animal/gib()
+ if(meat_amount && meat_type)
+ for(var/i = 0; i < meat_amount; i++)
+ new meat_type(src.loc)
+ ..()
+
+/mob/living/simple_animal/say_quote(var/text)
+ if(speak_emote && speak_emote.len)
+ var/emote = pick(speak_emote)
+ if(emote)
+ return "[emote], \"[text]\""
+ return "says, \"[text]\"";
+
+/mob/living/simple_animal/emote(var/act)
+ if(act)
+ if(act == "scream") act = "makes a loud and pained whimper" //ugly hack to stop animals screaming when crushed :P
+ for (var/mob/O in viewers(src, null))
+ O.show_message("[src] [act].")
+
+
+/mob/living/simple_animal/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)
+ health -= damage
+
+/mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj)
+ if(!Proj) return
+ src.health -= Proj.damage
+ return 0
+
+/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M as mob)
+ ..()
+
+ switch(M.a_intent)
+
+ if ("help")
+ if (health > 0)
+ for(var/mob/O in viewers(src, null))
+ if ((O.client && !( O.blinded )))
+ O.show_message("\blue [M] [response_help] [src]")
+
+ if ("grab")
+ if (M == src)
+ return
+ if (nopush)
+ return
+ var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M )
+ G.assailant = M
+ G.affecting = src
+ M.put_in_active_hand(G)
+
+ grabbed_by += G
+ G.synch()
+
+ LAssailant = M
+
+ 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")
+ health -= harm_intent_damage
+ for(var/mob/O in viewers(src, null))
+ if ((O.client && !( O.blinded )))
+ O.show_message("\red [M] [response_harm] [src]")
+
+ if ("disarm")
+ for(var/mob/O in viewers(src, null))
+ if ((O.client && !( O.blinded )))
+ O.show_message("\blue [M] [response_disarm] [src]")
+
+ return
+
+/mob/living/simple_animal/attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri
+ if(istype(O, /obj/item/stack/medical))
+ if(alive)
+ var/obj/item/stack/medical/MED = O
+ if(health < maxHealth)
+ if(MED.amount >= 1)
+ health = min(maxHealth, health + MED.heal_brute)
+ MED.amount -= 1
+ if(MED.amount <= 0)
+ del(MED)
+ for(var/mob/M in viewers(src, null))
+ if ((M.client && !( M.blinded )))
+ M.show_message("\blue [user] applies the [MED] on [src]")
+ else
+ user << "\blue this [src] is dead, medical items won't bring it back to life."
+ else
+ if(O.force)
+ health -= O.force
+ for(var/mob/M in viewers(src, null))
+ if ((M.client && !( M.blinded )))
+ M.show_message("\red \b [src] has been attacked with the [O] by [user]. ")
+ else
+ usr << "\red This weapon is ineffective, it does no damage."
+ for(var/mob/M in viewers(src, null))
+ if ((M.client && !( M.blinded )))
+ M.show_message("\red [user] gently taps [src] with the [O]. ")
+
+
+/mob/living/simple_animal/movement_delay()
+ var/tally = 0 //Incase I need to add stuff other than "speed" later
+
+ tally = speed
+
+ return tally
+
+/mob/living/simple_animal/Stat()
+ ..()
+
+ statpanel("Status")
+ stat(null, "Health: [round((health / maxHealth) * 100)]%")
+
+/mob/living/simple_animal/proc/Die()
+ alive = 0
+ icon_state = icon_dead
+ stat = DEAD
+ density = 0
+ return
+
+/mob/living/simple_animal/ex_act(severity)
+ flick("flash", flash)
+ switch (severity)
+ if (1.0)
+ health -= 500
+ gib()
+ return
+
+ if (2.0)
+ health -= 60
+
+
+ if(3.0)
+ health -= 30
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm
new file mode 100644
index 0000000000..48faf0c9c7
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/parrot.dm
@@ -0,0 +1,91 @@
+/mob/living/simple_animal/parrot
+ name = "\improper Parrot"
+ desc = "It's a parrot! No dirty words!"
+ icon = 'mob.dmi'
+ icon_state = "cat"
+ icon_living = "cat"
+ icon_dead = "cat_dead"
+ speak = list("Hi","Hello!","Cracker?","BAWWWWK george mellons griffing me")
+ speak_emote = list("squawks","says","yells")
+ emote_hear = list("squawks","bawks")
+ emote_see = list("flutters its wings", "glares at you")
+ speak_chance = 1
+ turns_per_move = 5
+ meat_type = /obj/item/weapon/reagent_containers/food/snacks/cracker/
+ response_help = "pets the"
+ response_disarm = "gently moves aside the"
+ response_harm = "swats the"
+
+ ears = new /obj/item/device/radio/headset/heads/ce()
+
+/mob/living/simple_animal/parrot/DrProfessor
+ name = "Doctor Professor Parrot, PhD"
+ desc = "That's the Doctor Professor. He has more degrees than all of the engineering team put together, and has several published papers on quantum cracker theory."
+ speak = list(":e Check the singlo, you chucklefucks!",":e Wire the solars, you lazy bums!",":e WHO TOOK THE DAMN RIG SUIT?",":e OH GOD ITS FREE CALL THE SHUTTLE")
+ response_harm = "is attacked in the face by"
+
+/obj/item/weapon/reagent_containers/food/snacks/cracker/
+ name = "Cracker"
+ desc = "It's a salted cracker."
+
+/mob/living/simple_animal/parrot/show_inv(mob/user as mob)
+ user.machine = src
+ if(user.stat) return
+
+ var/dat = "
"
+ if(ears)
+ dat += "
Headset: [ears] (Remove)"
+ else
+ dat += "
Headset: Nothing"
+
+ user << browse(dat, text("window=mob[];size=325x500", name))
+ onclose(user, "mob[real_name]")
+ return
+
+
+
+/mob/living/simple_animal/parrot/Topic(href, href_list)
+ if(usr.stat) return
+
+ //Removing from inventory
+ if(href_list["remove_inv"])
+ if(get_dist(src,usr) > 1 || !(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr)))
+ return
+ var/remove_from = href_list["remove_inv"]
+ switch(remove_from)
+ if("ears")
+ if(ears)
+ src.say(":e BAWWWWWK LEAVE THE HEADSET BAWKKKKK!")
+ ears.loc = src.loc
+ ears = null
+ else
+ usr << "\red There is nothing to remove from its [remove_from]."
+ return
+
+ //Adding things to inventory
+ else if(href_list["add_inv"])
+ if(get_dist(src,usr) > 1 || !(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr)))
+ return
+ var/add_to = href_list["add_inv"]
+ if(!usr.get_active_hand())
+ usr << "\red You have nothing in your hand to put on its [add_to]."
+ return
+ switch(add_to)
+ if("ears")
+ if(ears)
+ usr << "\red It's already wearing something."
+ return
+ else
+ var/obj/item/item_to_add = usr.get_active_hand()
+ if(!item_to_add)
+ return
+
+ if( !istype(item_to_add, /obj/item/device/radio/headset) )
+ usr << "\red This object won't fit."
+ return
+
+ usr.drop_item()
+ item_to_add.loc = src
+ src.ears = item_to_add
+ else
+ ..()
diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm
new file mode 100644
index 0000000000..00b5e72f44
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/shade.dm
@@ -0,0 +1,59 @@
+/mob/living/simple_animal/shade
+ name = "Shade"
+ desc = "A bound spirit"
+ icon = 'mob.dmi'
+ icon_state = "shade"
+ icon_living = "shade"
+ icon_dead = "shade_dead"
+ maxHealth = 50
+ health = 50
+ speak_emote = list("hisses")
+ emote_hear = list("wails","screeches")
+ response_help = "puts their hand through"
+ response_disarm = "flails at"
+ response_harm = "punches the"
+ melee_damage_lower = 5
+ melee_damage_upper = 15
+ attacktext = "drains the life from"
+ minbodytemp = 0
+ maxbodytemp = 4000
+ min_oxy = 0
+ max_co2 = 0
+ max_tox = 0
+ speed = -1
+ stop_automated_movement = 1
+
+
+ Life()
+ ..()
+ if(stat == 2)
+ new /obj/item/weapon/ectoplasm (src.loc)
+ for(var/mob/M in viewers(src, null))
+ if((M.client && !( M.blinded )))
+ M.show_message("\red [src] lets out a contented sigh as their form unwinds. ")
+ ghostize(0)
+ del src
+ return
+
+
+ attackby(var/obj/item/O as obj, var/mob/user as mob) //Marker -Agouri
+ if(istype(O, /obj/item/device/soulstone))
+ O.transfer_soul("SHADE", src, user)
+ else
+ if(O.force)
+ health -= O.force
+ for(var/mob/M in viewers(src, null))
+ if ((M.client && !( M.blinded )))
+ M.show_message("\red \b [src] has been attacked with the [O] by [user]. ")
+ else
+ usr << "\red This weapon is ineffective, it does no damage."
+ for(var/mob/M in viewers(src, null))
+ if ((M.client && !( M.blinded )))
+ M.show_message("\red [user] gently taps [src] with the [O]. ")
+ return
+
+/mob/living/simple_animal/shade/proc/mind_initialize(mob/G)
+ mind = new
+ mind.current = src
+ mind.assigned_role = "Shade"
+ mind.key = G.key
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/update_icons.dm b/code/modules/mob/living/simple_animal/update_icons.dm
new file mode 100644
index 0000000000..1b010a23b2
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/update_icons.dm
@@ -0,0 +1,21 @@
+/mob/living/simple_animal/corgi/regenerate_icons()
+ overlays = list()
+
+ if(inventory_head)
+ var/head_icon_state = inventory_head.icon_state
+ if(health <= 0)
+ head_icon_state += "2"
+
+ var/icon/head_icon = icon('corgi_head.dmi',head_icon_state)
+ if(head_icon)
+ overlays += head_icon
+
+ if(inventory_back)
+ var/back_icon_state = inventory_back.icon_state
+ if(health <= 0)
+ back_icon_state += "2"
+
+ var/icon/back_icon = icon('corgi_back.dmi',back_icon_state)
+ if(back_icon)
+ overlays += back_icon
+ return
diff --git a/code/modules/mob/living/simple_animal/worm.dm b/code/modules/mob/living/simple_animal/worm.dm
new file mode 100644
index 0000000000..6bc082ad6e
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/worm.dm
@@ -0,0 +1,199 @@
+/mob/living/simple_animal/space_worm
+ name = "space worm segment"
+ desc = "A part of a space worm."
+ icon = 'critter.dmi'
+ icon_state = "spaceworm"
+ icon_living = "spaceworm"
+ icon_dead = "spacewormdead"
+
+ speak_emote = list("transmits") //not supposed to be used under AI control
+ emote_hear = list("transmits") //I'm just adding it so it doesn't runtime if controlled by player who speaks
+
+ response_help = "touches"
+ response_disarm = "flails at"
+ response_harm = "punches the"
+
+ harm_intent_damage = 2
+
+ maxHealth = 30
+ health = 30
+
+ stop_automated_movement = 1
+ animate_movement = SYNC_STEPS
+
+ minbodytemp = 0
+ maxbodytemp = 350
+ min_oxy = 0
+ max_co2 = 0
+ max_tox = 0
+
+ a_intent = "harm" //so they don't get pushed around
+
+ nopush = 1
+ wall_smash = 1
+
+ speed = -1
+
+ var/mob/living/simple_animal/space_worm/previous //next/previous segments, correspondingly
+ var/mob/living/simple_animal/space_worm/next //head is the nextest segment
+
+ var/stomachProcessProbability = 50
+ var/digestionProbability = 20
+ var/flatPlasmaValue = 5 //flat plasma amount given for non-items
+
+ var/atom/currentlyEating //what the worm is currently eating
+ var/eatingDuration = 0 //how long he's been eating it for
+
+ head
+ name = "space worm head"
+ icon_state = "spacewormhead"
+ icon_living = "spacewormhead"
+ icon_dead = "spacewormdead"
+
+ maxHealth = 20
+ health = 20
+
+ melee_damage_lower = 10
+ melee_damage_upper = 15
+ attacktext = "bites"
+
+ animate_movement = SLIDE_STEPS
+
+ New(var/location, var/segments = 6)
+ ..()
+
+ var/mob/living/simple_animal/space_worm/current = src
+
+ for(var/i = 1 to segments)
+ var/mob/living/simple_animal/space_worm/newSegment = new /mob/living/simple_animal/space_worm(loc)
+ current.Attach(newSegment)
+ current = newSegment
+
+ update_icon()
+ if(stat == CONSCIOUS || stat == UNCONSCIOUS)
+ icon_state = "spacewormhead[previous?1:0]"
+ if(previous)
+ dir = get_dir(previous,src)
+ else
+ icon_state = "spacewormheaddead"
+
+ Life()
+ ..()
+
+ if(next && !(next in view(src,1)))
+ Detach()
+
+ if(stat == DEAD) //dead chunks fall off and die immediately
+ if(previous)
+ previous.Detach()
+ if(next)
+ Detach(1)
+
+ if(prob(stomachProcessProbability))
+ ProcessStomach()
+
+ update_icon()
+
+ return
+
+ Del() //if a chunk a destroyed, make a new worm out of the split halves
+ if(previous)
+ previous.Detach()
+ ..()
+
+ Move()
+ var/attachementNextPosition = loc
+ if(..())
+ if(previous)
+ previous.Move(attachementNextPosition)
+ update_icon()
+
+ Bump(atom/obstacle)
+ if(currentlyEating != obstacle)
+ currentlyEating = obstacle
+ eatingDuration = 0
+
+ if(!AttemptToEat(obstacle))
+ eatingDuration++
+ else
+ currentlyEating = null
+ eatingDuration = 0
+
+ return
+
+ proc/update_icon() //only for the sake of consistency with the other update icon procs
+ if(stat == CONSCIOUS || stat == UNCONSCIOUS)
+ if(previous) //midsection
+ icon_state = "spaceworm[get_dir(src,previous) | get_dir(src,next)]" //see 3 lines below
+ else //tail
+ icon_state = "spacewormtail"
+ dir = get_dir(src,next) //next will always be present since it's not a head and if it's dead, it goes in the other if branch
+ else
+ icon_state = "spacewormdead"
+
+ return
+
+ proc/AttemptToEat(var/atom/target)
+ if(istype(target,/turf/simulated/wall))
+ if((!istype(target,/turf/simulated/wall/r_wall) && eatingDuration >= 100) || eatingDuration >= 200) //need 20 ticks to eat an rwall, 10 for a regular one
+ var/turf/simulated/wall/wall = target
+ wall.ReplaceWithFloor()
+ new /obj/item/stack/sheet/metal(src, flatPlasmaValue)
+ return 1
+ else if(istype(target,/atom/movable))
+ if(istype(target,/mob) || eatingDuration >= 50) //5 ticks to eat stuff like airlocks
+ var/atom/movable/objectOrMob = target
+ contents += objectOrMob
+ return 1
+
+ return 0
+
+ proc/Attach(var/mob/living/simple_animal/space_worm/attachement)
+ if(!attachement)
+ return
+
+ previous = attachement
+ attachement.next = src
+
+ return
+
+ proc/Detach(die = 0)
+ var/mob/living/simple_animal/space_worm/newHead = new /mob/living/simple_animal/space_worm/head(loc,0)
+ var/mob/living/simple_animal/space_worm/newHeadPrevious = previous
+
+ previous = null //so that no extra heads are spawned
+
+ newHead.Attach(newHeadPrevious)
+
+ if(die)
+ newHead.Die()
+
+ del(src)
+
+ proc/ProcessStomach()
+ for(var/atom/movable/stomachContent in contents)
+ if(prob(digestionProbability))
+ if(istype(stomachContent,/obj/item/stack)) //converts to plasma, keeping the stack value
+ if(!istype(stomachContent,/obj/item/stack/sheet/plasma))
+ var/obj/item/stack/oldStack = stomachContent
+ new /obj/item/stack/sheet/plasma(src, oldStack.amount)
+ del(oldStack)
+ continue
+ else if(istype(stomachContent,/obj/item)) //converts to plasma, keeping the w_class
+ var/obj/item/oldItem = stomachContent
+ new /obj/item/stack/sheet/plasma(src, oldItem.w_class)
+ del(oldItem)
+ continue
+ else
+ new /obj/item/stack/sheet/plasma(src, flatPlasmaValue) //just flat amount
+ del(stomachContent)
+ continue
+
+ if(previous)
+ for(var/atom/movable/stomachContent in contents) //transfer it along the digestive tract
+ previous.contents += stomachContent
+ else
+ for(var/atom/movable/stomachContent in contents) //or poop it out
+ loc.contents += stomachContent
+
+ return
\ No newline at end of file
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index b222e2876a..07733b109b 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -487,9 +487,6 @@
// ..()
return
-/mob/proc/get_damage()
- return health
-
/mob/proc/UpdateLuminosity()
if(src.total_luminosity == src.last_luminosity) return 0//nothing to do here
src.last_luminosity = src.total_luminosity
@@ -812,12 +809,6 @@ note dizziness decrements automatically in the mob's Life() proc.
resting = max(resting + amount,0)
return
-/mob/proc/getMaxHealth()
- return maxHealth
-
-/mob/proc/setMaxHealth(var/newMaxHealth)
- maxHealth = newMaxHealth
-
/*
* Sends resource files to client cache
*/
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index ece6c2b20a..757d1e8b51 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -5,12 +5,11 @@
flags = NOREACT
var/datum/mind/mind
+ var/stat = 0 //Whether a mob is alive or dead. TODO: Move this to living - Nodrak
+
//Not in use yet
var/obj/effect/organstructure/organStructure = null
- var/maxHealth = 100 //Maximum health that should be possible. Used by living, organ and simple_mobs
-
-
// var/uses_hud = 0
var/obj/screen/flash = null
var/obj/screen/blind = null
@@ -40,8 +39,6 @@
I'll make some notes on where certain variable defines should probably go.
Changing this around would probably require a good look-over the pre-existing code.
*/
- //var/midis = 1 //Check if midis should be played for someone - no, this is something that is tied to clients, not mobs.
- var/alien_egg_flag = 0//Have you been infected?
var/obj/screen/zone_sel/zone_sel = null
var/emote_allowed = 1
@@ -57,7 +54,6 @@
var/sdisabilities = 0 //Carbon
var/disabilities = 0 //Carbon
var/atom/movable/pulling = null
- var/stat = 0.0
var/next_move = null
var/prev_move = null
var/monkeyizing = null //Carbon
@@ -91,7 +87,7 @@
var/timeofdeath = 0.0//Living
var/cpr_time = 1.0//Carbon
- var/health = 100//Living
+
var/bodytemperature = 310.055 //98.7 F
var/drowsyness = 0.0//Carbon
@@ -122,15 +118,9 @@
var/obj/item/weapon/tank/internal = null//Human/Monkey
var/obj/item/weapon/storage/s_active = null//Carbon
var/obj/item/clothing/mask/wear_mask = null//Carbon
- var/r_epil = 0
- var/r_ch_cou = 0
- var/r_Tourette = 0//Carbon
var/seer = 0 //for cult//Carbon, probably Human
- var/miming = null //checks if the guy is a mime//Human
- var/silent = null //Can't talk. Value goes down every life proc.//Human
-
var/obj/hud/hud_used = null
//var/list/organs = list( ) //moved to human.
@@ -152,8 +142,6 @@
var/nodamage = 0
- var/underwear = 1//Human
- var/backbag = 2//Human
var/be_syndicate = 0//This really should be a client variable.
var/be_random_name = 0
var/const/blindness = 1//Carbon
@@ -206,35 +194,10 @@
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
-/*
-//Changeling mode stuff//Carbon
- var/changeling_level = 0
- var/list/absorbed_dna = list()
- var/changeling_fakedeath = 0
- var/chem_charges = 20.00
- var/sting_range = 1
-*/
- var/datum/changeling/changeling = null
-
- var/universal_speak = 0 // Set to 1 to enable the mob to speak to everyone -- TLE
- var/obj/control_object // Hacking in to control objects -- TLE
-
- var/robot_talk_understand = 0
- var/alien_talk_understand = 0
-
-/*For ninjas and others. This variable is checked when a mob moves and I guess it was supposed to allow the mob to move
-through dense areas, such as walls. Setting density to 0 does the same thing. The difference here is that
-the mob is also allowed to move without any sort of restriction. For instance, in space or out of holder objects.*/
-//0 is off, 1 is normal, 2 is for ninjas.
- var/incorporeal_move = 0
-
-
var/update_icon = 1 //Set to 1 to trigger update_icons() at the next life() call
var/UI = 'screen1_Midnight.dmi' // For changing the UI from preferences
-// var/obj/effect/organstructure/organStructure = null //for dem organs
-
var/canstun = 1 // determines if this mob can be stunned by things
var/canweaken = 1 // determines if this mob can be weakened/knocked down by things
var/nopush = 0 //Can they be shoved?
@@ -249,3 +212,13 @@ the mob is also allowed to move without any sort of restriction. For instance, i
var/list/radar_blips = list() // list of screen objects, radar blips
var/radar_open = 0 // nonzero is radar is open
+
+ //Datum holding changeling stuff
+ var/datum/changeling/changeling = null //TODO: Move this to living or carbon -Nodrak
+
+ var/obj/control_object //Used by admins to possess objects. All mobs should have this var
+
+ //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/robot_talk_understand = 0
+ var/alien_talk_understand = 0
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 7c63d6cbfa..02cf5a6a8d 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -278,9 +278,11 @@
if(mob.monkeyizing) return//This is sota the goto stop mobs from moving var
- if(mob.incorporeal_move)//Move though walls
- Process_Incorpmove(direct)
- return
+ if(isliving(mob))
+ var/mob/living/L = mob
+ if(L.incorporeal_move)//Move though walls
+ Process_Incorpmove(direct)
+ return
if(Process_Grab()) return
if(!mob.canmove) return
@@ -413,10 +415,13 @@
///Allows mobs to run though walls
/client/proc/Process_Incorpmove(direct)
var/turf/mobloc = get_turf(mob)
- switch(mob.incorporeal_move)
+ if(!isliving(mob))
+ return
+ var/mob/living/L = mob
+ switch(L.incorporeal_move)
if(1)
- mob.loc = get_step(mob, direct)
- mob.dir = direct
+ L.loc = get_step(L, direct)
+ L.dir = direct
if(2)
if(prob(50))
var/locx
@@ -444,19 +449,19 @@
return
else
return
- mob.loc = locate(locx,locy,mobloc.z)
+ L.loc = locate(locx,locy,mobloc.z)
spawn(0)
var/limit = 2//For only two trailing shadows.
- for(var/turf/T in getline(mobloc, mob.loc))
+ for(var/turf/T in getline(mobloc, L.loc))
spawn(0)
- anim(T,mob,'mob.dmi',,"shadow",,mob.dir)
+ anim(T,L,'mob.dmi',,"shadow",,L.dir)
limit--
if(limit<=0) break
else
spawn(0)
- anim(mobloc,mob,'mob.dmi',,"shadow",,mob.dir)
- mob.loc = get_step(mob, direct)
- mob.dir = direct
+ anim(mobloc,mob,'mob.dmi',,"shadow",,L.dir)
+ L.loc = get_step(L, direct)
+ L.dir = direct
return 1
diff --git a/tgstation.dme b/tgstation.dme
index 04594f0ed9..7e2dd1f6d5 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -125,6 +125,7 @@
#define FILE_DIR "code/modules/mob/living/silicon/decoy"
#define FILE_DIR "code/modules/mob/living/silicon/pai"
#define FILE_DIR "code/modules/mob/living/silicon/robot"
+#define FILE_DIR "code/modules/mob/living/simple_animal"
#define FILE_DIR "code/modules/mob/new_player"
#define FILE_DIR "code/modules/mob/organ"
#define FILE_DIR "code/modules/mob/simple_animal"
@@ -188,8 +189,8 @@
#define FILE_DIR "icons/vending_icons"
#define FILE_DIR "interface"
#define FILE_DIR "maps"
-#define FILE_DIR "maps/backup"
#define FILE_DIR "maps/RandomZLevels"
+#define FILE_DIR "Redirector"
#define FILE_DIR "sound"
#define FILE_DIR "sound/AI"
#define FILE_DIR "sound/ambience"
@@ -927,6 +928,7 @@
#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\alien\alien.dm"
#include "code\modules\mob\living\carbon\alien\death.dm"
#include "code\modules\mob\living\carbon\alien\say.dm"
@@ -968,6 +970,7 @@
#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\inventory.dm"
#include "code\modules\mob\living\carbon\human\life.dm"
@@ -1034,6 +1037,16 @@
#include "code\modules\mob\living\silicon\robot\robot_movement.dm"
#include "code\modules\mob\living\silicon\robot\say.dm"
#include "code\modules\mob\living\silicon\robot\wires.dm"
+#include "code\modules\mob\living\simple_animal\behemoth.dm"
+#include "code\modules\mob\living\simple_animal\cat.dm"
+#include "code\modules\mob\living\simple_animal\constructs.dm"
+#include "code\modules\mob\living\simple_animal\corgi.dm"
+#include "code\modules\mob\living\simple_animal\crab.dm"
+#include "code\modules\mob\living\simple_animal\life.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\update_icons.dm"
+#include "code\modules\mob\living\simple_animal\worm.dm"
#include "code\modules\mob\new_player\hud.dm"
#include "code\modules\mob\new_player\login.dm"
#include "code\modules\mob\new_player\new_player.dm"
@@ -1043,16 +1056,6 @@
#include "code\modules\mob\new_player\sprite_accessories.dm"
#include "code\modules\mob\organ\organ.dm"
#include "code\modules\mob\organ\organ_external.dm"
-#include "code\modules\mob\simple_animal\behemoth.dm"
-#include "code\modules\mob\simple_animal\cat.dm"
-#include "code\modules\mob\simple_animal\constructs.dm"
-#include "code\modules\mob\simple_animal\corgi.dm"
-#include "code\modules\mob\simple_animal\crab.dm"
-#include "code\modules\mob\simple_animal\life.dm"
-#include "code\modules\mob\simple_animal\parrot.dm"
-#include "code\modules\mob\simple_animal\shade.dm"
-#include "code\modules\mob\simple_animal\update_icons.dm"
-#include "code\modules\mob\simple_animal\worm.dm"
#include "code\modules\paperwork\clipboard.dm"
#include "code\modules\paperwork\filingcabinet.dm"
#include "code\modules\paperwork\folders.dm"