Tg patch branch to master (#192)

* code nitpicking

* Midnight oil

More like 6am oil.  Still having issues with actually eating anyone.

* Subsystem 12/21

Most Recent TG subsystem folder

* globalvars 12/21

Tossed out the flavor_misc and parallax files

* Onclick 12/21

as well as .dme updates

* _defines 12/21

ommited old _MC.dm

* _HELPERS 12/21

Preserved snowflake placement of furry sprites

* _defeines/genetics

reapplied narkism holdover for snowflake races.

* Oops forgot mutant colors

* modules porting 12/21 + Sounds/icons

Admin, Client and most of mob life files ommitted

* enviroment file

* Admin optimizations

ahelp log system kept

* Mob ports 12/21

Flavor text preserved

* datums ported 12/21

* Game ported 12/21

* batch of duplicate fixes/dogborg work

Dogborgs need to be modernized to refractored borg standards.

* moar fixes

* Maps and futher compile fixes

* missed commit

* Noms

* specific release doesn't work

* Tg modernization patch (#115)

* sync (#3)

* shuttle auto call

* Merge /vore into /master (#39)

* progress

* Compile errors fixed

No idea if it's test worthy tho as conflicts with race overhaul and
narky removal.

* Update admins.txt

* efforts continue

Fuck grab code, seriously

* grab code is cancer

* Execute the Narkism

Do not hesitate.

Show no mercy.

* holy shit grab code is awful

* have I bitched about grab code

My bitching, let me show you it

* código de agarre es una mierda

No really it is

* yeah I don't even know anymore.

* Lolnope. Fuck grab code

* I'm not even sure what to fix anymore

* Self eating is not an acceptable fate

* Taste the void, son.

* My code doesn't pass it's own sanity check.

Maybe it's a sign of things to come.

* uncommented and notes

* It Works and I Don't Know Why (#38)

* shuttle auto call

* it works and I don't know why

* Subsystem 12/21

Most Recent TG subsystem folder

* globalvars 12/21

Tossed out the flavor_misc and parallax files

* Onclick 12/21

as well as .dme updates

* _defines 12/21

ommited old _MC.dm

* _HELPERS 12/21

Preserved snowflake placement of furry sprites

* _defeines/genetics

reapplied narkism holdover for snowflake races.

* Oops forgot mutant colors

* modules porting 12/21 + Sounds/icons

Admin, Client and most of mob life files ommitted

* enviroment file

* Admin optimizations

ahelp log system kept

* Mob ports 12/21

Flavor text preserved

* datums ported 12/21

* Game ported 12/21

* batch of duplicate fixes/dogborg work

Dogborgs need to be modernized to refractored borg standards.

* moar fixes

* Maps and futher compile fixes

* port from cactus did

* fix format error

* Update preferences.dm

unfuck

* Revert "port from cactus did"

* unfuck

* more sprite work

* vore

* disabled roundstart xenos for now

* admin QOL

needs callback porting, TBD

* Mentor system initial port

I'm sure I've missed a fuckton of shit

* test merge

* Jesus tits did this finally fix compile issues?

* Tg modern (#149)

* sync (#3)

* shuttle auto call

* Merge /vore into /master (#39)

* progress

* Compile errors fixed

No idea if it's test worthy tho as conflicts with race overhaul and
narky removal.

* Update admins.txt

* efforts continue

Fuck grab code, seriously

* grab code is cancer

* Execute the Narkism

Do not hesitate.

Show no mercy.

* holy shit grab code is awful

* have I bitched about grab code

My bitching, let me show you it

* código de agarre es una mierda

No really it is

* yeah I don't even know anymore.

* Lolnope. Fuck grab code

* I'm not even sure what to fix anymore

* Self eating is not an acceptable fate

* Taste the void, son.

* My code doesn't pass it's own sanity check.

Maybe it's a sign of things to come.

* uncommented and notes

* It Works and I Don't Know Why (#38)

* shuttle auto call

* it works and I don't know why

* Subsystem 12/21

Most Recent TG subsystem folder

* globalvars 12/21

Tossed out the flavor_misc and parallax files

* Onclick 12/21

as well as .dme updates

* _defines 12/21

ommited old _MC.dm

* _HELPERS 12/21

Preserved snowflake placement of furry sprites

* _defeines/genetics

reapplied narkism holdover for snowflake races.

* Oops forgot mutant colors

* modules porting 12/21 + Sounds/icons

Admin, Client and most of mob life files ommitted

* enviroment file

* Admin optimizations

ahelp log system kept

* Mob ports 12/21

Flavor text preserved

* datums ported 12/21

* Game ported 12/21

* batch of duplicate fixes/dogborg work

Dogborgs need to be modernized to refractored borg standards.

* moar fixes

* Maps and futher compile fixes

* Tg modernization patch (#115)

* sync (#3)

* shuttle auto call

* Merge /vore into /master (#39)

* progress

* Compile errors fixed

No idea if it's test worthy tho as conflicts with race overhaul and
narky removal.

* Update admins.txt

* efforts continue

Fuck grab code, seriously

* grab code is cancer

* Execute the Narkism

Do not hesitate.

Show no mercy.

* holy shit grab code is awful

* have I bitched about grab code

My bitching, let me show you it

* código de agarre es una mierda

No really it is

* yeah I don't even know anymore.

* Lolnope. Fuck grab code

* I'm not even sure what to fix anymore

* Self eating is not an acceptable fate

* Taste the void, son.

* My code doesn't pass it's own sanity check.

Maybe it's a sign of things to come.

* uncommented and notes

* It Works and I Don't Know Why (#38)

* shuttle auto call

* it works and I don't know why

* Subsystem 12/21

Most Recent TG subsystem folder

* globalvars 12/21

Tossed out the flavor_misc and parallax files

* Onclick 12/21

as well as .dme updates

* _defines 12/21

ommited old _MC.dm

* _HELPERS 12/21

Preserved snowflake placement of furry sprites

* _defeines/genetics

reapplied narkism holdover for snowflake races.

* Oops forgot mutant colors

* modules porting 12/21 + Sounds/icons

Admin, Client and most of mob life files ommitted

* enviroment file

* Admin optimizations

ahelp log system kept

* Mob ports 12/21

Flavor text preserved

* datums ported 12/21

* Game ported 12/21

* batch of duplicate fixes/dogborg work

Dogborgs need to be modernized to refractored borg standards.

* moar fixes

* Maps and futher compile fixes

* port from cactus did

* fix format error

* Update preferences.dm

unfuck

* Revert "port from cactus did"

* unfuck

* more sprite work

* vore

* disabled roundstart xenos for now

* test merge

* Jesus tits did this finally fix compile issues?

* Initial test compiles. hooray.

* Admin ticket fixes

* I'll give you a bad argument you piece of shit dream maker I fucking swear on my mum

* who list wip

also ahelps are broken again. fuck if I know why

* discord bot basics

* maybe tickets work now & bot framework done

* ahelp callback readd

* Mentor system, Tickets, and discord (#151)

* sync (#3)

* shuttle auto call

* Merge /vore into /master (#39)

* progress

* Compile errors fixed

No idea if it's test worthy tho as conflicts with race overhaul and
narky removal.

* Update admins.txt

* efforts continue

Fuck grab code, seriously

* grab code is cancer

* Execute the Narkism

Do not hesitate.

Show no mercy.

* holy shit grab code is awful

* have I bitched about grab code

My bitching, let me show you it

* código de agarre es una mierda

No really it is

* yeah I don't even know anymore.

* Lolnope. Fuck grab code

* I'm not even sure what to fix anymore

* Self eating is not an acceptable fate

* Taste the void, son.

* My code doesn't pass it's own sanity check.

Maybe it's a sign of things to come.

* uncommented and notes

* It Works and I Don't Know Why (#38)

* shuttle auto call

* it works and I don't know why

* Subsystem 12/21

Most Recent TG subsystem folder

* globalvars 12/21

Tossed out the flavor_misc and parallax files

* Onclick 12/21

as well as .dme updates

* _defines 12/21

ommited old _MC.dm

* _HELPERS 12/21

Preserved snowflake placement of furry sprites

* _defeines/genetics

reapplied narkism holdover for snowflake races.

* Oops forgot mutant colors

* modules porting 12/21 + Sounds/icons

Admin, Client and most of mob life files ommitted

* enviroment file

* Admin optimizations

ahelp log system kept

* Mob ports 12/21

Flavor text preserved

* datums ported 12/21

* Game ported 12/21

* batch of duplicate fixes/dogborg work

Dogborgs need to be modernized to refractored borg standards.

* moar fixes

* Maps and futher compile fixes

* Tg modernization patch (#115)

* sync (#3)

* shuttle auto call

* Merge /vore into /master (#39)

* progress

* Compile errors fixed

No idea if it's test worthy tho as conflicts with race overhaul and
narky removal.

* Update admins.txt

* efforts continue

Fuck grab code, seriously

* grab code is cancer

* Execute the Narkism

Do not hesitate.

Show no mercy.

* holy shit grab code is awful

* have I bitched about grab code

My bitching, let me show you it

* código de agarre es una mierda

No really it is

* yeah I don't even know anymore.

* Lolnope. Fuck grab code

* I'm not even sure what to fix anymore

* Self eating is not an acceptable fate

* Taste the void, son.

* My code doesn't pass it's own sanity check.

Maybe it's a sign of things to come.

* uncommented and notes

* It Works and I Don't Know Why (#38)

* shuttle auto call

* it works and I don't know why

* Subsystem 12/21

Most Recent TG subsystem folder

* globalvars 12/21

Tossed out the flavor_misc and parallax files

* Onclick 12/21

as well as .dme updates

* _defines 12/21

ommited old _MC.dm

* _HELPERS 12/21

Preserved snowflake placement of furry sprites

* _defeines/genetics

reapplied narkism holdover for snowflake races.

* Oops forgot mutant colors

* modules porting 12/21 + Sounds/icons

Admin, Client and most of mob life files ommitted

* enviroment file

* Admin optimizations

ahelp log system kept

* Mob ports 12/21

Flavor text preserved

* datums ported 12/21

* Game ported 12/21

* batch of duplicate fixes/dogborg work

Dogborgs need to be modernized to refractored borg standards.

* moar fixes

* Maps and futher compile fixes

* port from cactus did

* fix format error

* Update preferences.dm

unfuck

* Revert "port from cactus did"

* unfuck

* more sprite work

* vore

* disabled roundstart xenos for now

* admin QOL

needs callback porting, TBD

* Mentor system initial port

I'm sure I've missed a fuckton of shit

* test merge

* Jesus tits did this finally fix compile issues?

* Initial test compiles. hooray.

* Admin ticket fixes

* I'll give you a bad argument you piece of shit dream maker I fucking swear on my mum

* who list wip

also ahelps are broken again. fuck if I know why

* discord bot basics

* maybe tickets work now & bot framework done

* ahelp callback readd

* vore tweaks

* progress

* dirtier fix than a korean hooker in the 60s

* The release your hooker will always fake

* you could save that hookers number but wouldn't you rather just vore the hooker instead

* Save system is literal black magic

* great googly moogly it's all gone to shit

* We May 2015 save code now

* fiddling with digestion code now

* fuck if I know anymore. I'm going to bed

* OWN UP YOUR OWN DIGESTION

* UNREGULATED GUTS ARE NON COMPLIANT

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

* BELLIES MUST COMPLY WITH USER OWNERSHIP

* Removed debug messages

* Unneeded verb additions

* file change tweaks

* WATCH YOUR SPACING, DRIVER

* Changelog and devourment for some mobs.

Because I knew people were gunna ask.

NO YOU CANNOT EAT THE FUCKING LEGION

* Vore code sync (#157)

* sync (#3)

* shuttle auto call

* Merge /vore into /master (#39)

* progress

* Compile errors fixed

No idea if it's test worthy tho as conflicts with race overhaul and
narky removal.

* Update admins.txt

* efforts continue

Fuck grab code, seriously

* grab code is cancer

* Execute the Narkism

Do not hesitate.

Show no mercy.

* holy shit grab code is awful

* have I bitched about grab code

My bitching, let me show you it

* código de agarre es una mierda

No really it is

* yeah I don't even know anymore.

* Lolnope. Fuck grab code

* I'm not even sure what to fix anymore

* Self eating is not an acceptable fate

* Taste the void, son.

* My code doesn't pass it's own sanity check.

Maybe it's a sign of things to come.

* uncommented and notes

* It Works and I Don't Know Why (#38)

* shuttle auto call

* it works and I don't know why

* Escape and Devourable

For the normies who play here yet complain about it.

* Things that should be committed

* unneeded files

* Sizeray works now

* tweaks and bed time going

* IT WORKS mostly

Need to get multiple guts and saving working tho

* save tweaks

* item hotfix

* gut examine message

* damifino

* save system works

also ensured some mobs have vore controls, so silicons can't even
remotely do vore things.

* code nitpicking

* Midnight oil

More like 6am oil.  Still having issues with actually eating anyone.

* Subsystem 12/21

Most Recent TG subsystem folder

* globalvars 12/21

Tossed out the flavor_misc and parallax files

* Onclick 12/21

as well as .dme updates

* _defines 12/21

ommited old _MC.dm

* _HELPERS 12/21

Preserved snowflake placement of furry sprites

* _defeines/genetics

reapplied narkism holdover for snowflake races.

* Oops forgot mutant colors

* modules porting 12/21 + Sounds/icons

Admin, Client and most of mob life files ommitted

* enviroment file

* Admin optimizations

ahelp log system kept

* Mob ports 12/21

Flavor text preserved

* datums ported 12/21

* Game ported 12/21

* batch of duplicate fixes/dogborg work

Dogborgs need to be modernized to refractored borg standards.

* moar fixes

* Maps and futher compile fixes

* missed commit

* Noms

* specific release doesn't work

* Tg modernization patch (#115)

* sync (#3)

* shuttle auto call

* Merge /vore into /master (#39)

* progress

* Compile errors fixed

No idea if it's test worthy tho as conflicts with race overhaul and
narky removal.

* Update admins.txt

* efforts continue

Fuck grab code, seriously

* grab code is cancer

* Execute the Narkism

Do not hesitate.

Show no mercy.

* holy shit grab code is awful

* have I bitched about grab code

My bitching, let me show you it

* código de agarre es una mierda

No really it is

* yeah I don't even know anymore.

* Lolnope. Fuck grab code

* I'm not even sure what to fix anymore

* Self eating is not an acceptable fate

* Taste the void, son.

* My code doesn't pass it's own sanity check.

Maybe it's a sign of things to come.

* uncommented and notes

* It Works and I Don't Know Why (#38)

* shuttle auto call

* it works and I don't know why

* Subsystem 12/21

Most Recent TG subsystem folder

* globalvars 12/21

Tossed out the flavor_misc and parallax files

* Onclick 12/21

as well as .dme updates

* _defines 12/21

ommited old _MC.dm

* _HELPERS 12/21

Preserved snowflake placement of furry sprites

* _defeines/genetics

reapplied narkism holdover for snowflake races.

* Oops forgot mutant colors

* modules porting 12/21 + Sounds/icons

Admin, Client and most of mob life files ommitted

* enviroment file

* Admin optimizations

ahelp log system kept

* Mob ports 12/21

Flavor text preserved

* datums ported 12/21

* Game ported 12/21

* batch of duplicate fixes/dogborg work

Dogborgs need to be modernized to refractored borg standards.

* moar fixes

* Maps and futher compile fixes

* port from cactus did

* fix format error

* Update preferences.dm

unfuck

* Revert "port from cactus did"

* unfuck

* more sprite work

* vore

* disabled roundstart xenos for now

* admin QOL

needs callback porting, TBD

* Mentor system initial port

I'm sure I've missed a fuckton of shit

* test merge

* Jesus tits did this finally fix compile issues?

* Initial test compiles. hooray.

* Admin ticket fixes

* I'll give you a bad argument you piece of shit dream maker I fucking swear on my mum

* who list wip

also ahelps are broken again. fuck if I know why

* discord bot basics

* maybe tickets work now & bot framework done

* ahelp callback readd

* vore tweaks

* progress

* dirtier fix than a korean hooker in the 60s

* The release your hooker will always fake

* you could save that hookers number but wouldn't you rather just vore the hooker instead

* Save system is literal black magic

* great googly moogly it's all gone to shit

* We May 2015 save code now

* fiddling with digestion code now

* fuck if I know anymore. I'm going to bed

* OWN UP YOUR OWN DIGESTION

* UNREGULATED GUTS ARE NON COMPLIANT

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

* BELLIES MUST COMPLY WITH USER OWNERSHIP

* Removed debug messages

* Unneeded verb additions

* file change tweaks

* WATCH YOUR SPACING, DRIVER

* Changelog and devourment for some mobs.

Because I knew people were gunna ask.

NO YOU CANNOT EAT THE FUCKING LEGION

* title screen change from Crow's PR.

* More of Crow's title screen stuff

* mode tweaks.... again

* gamemode voting in lobby via TalkingCactus
disabled ashwalkers as roundstart
Verk's species tweak
paralax starts disabled by default

* LOOC

* index sync problem (#158)

* digifix

* things

* furry races.dm

* actually deletes species_types

* maps

* tgui and stuff

* Sounds

* icon updates

* Defines and helpers

* global vars and on click

* controllers

* datums

* game folder

* fixes invisible flan mobs

* some modules

* dropbomb verb enhanced

* moar

* moar

* moar

* even more again

* and finally these for modules

* Some compile tweaks

* silly dme get updated you scrub

* compiles cleanly now

* various open PR fixes from TG

as of 0800 Texas Standard Time

* also fancy cryopods before I forget again

* headslug gold core fix

* edgy code of the modernization (#164)

* sync (#3)

* shuttle auto call

* Merge /vore into /master (#39)

* progress

* Compile errors fixed

No idea if it's test worthy tho as conflicts with race overhaul and
narky removal.

* Update admins.txt

* efforts continue

Fuck grab code, seriously

* grab code is cancer

* Execute the Narkism

Do not hesitate.

Show no mercy.

* holy shit grab code is awful

* have I bitched about grab code

My bitching, let me show you it

* código de agarre es una mierda

No really it is

* yeah I don't even know anymore.

* Lolnope. Fuck grab code

* I'm not even sure what to fix anymore

* Self eating is not an acceptable fate

* Taste the void, son.

* My code doesn't pass it's own sanity check.

Maybe it's a sign of things to come.

* uncommented and notes

* It Works and I Don't Know Why (#38)

* shuttle auto call

* it works and I don't know why

* Escape and Devourable

For the normies who play here yet complain about it.

* Things that should be committed

* unneeded files

* Sizeray works now

* tweaks and bed time going

* IT WORKS mostly

Need to get multiple guts and saving working tho

* save tweaks

* item hotfix

* gut examine message

* damifino

* save system works

also ensured some mobs have vore controls, so silicons can't even
remotely do vore things.

* code nitpicking

* Midnight oil

More like 6am oil.  Still having issues with actually eating anyone.

* Subsystem 12/21

Most Recent TG subsystem folder

* globalvars 12/21

Tossed out the flavor_misc and parallax files

* Onclick 12/21

as well as .dme updates

* _defines 12/21

ommited old _MC.dm

* _HELPERS 12/21

Preserved snowflake placement of furry sprites

* _defeines/genetics

reapplied narkism holdover for snowflake races.

* Oops forgot mutant colors

* modules porting 12/21 + Sounds/icons

Admin, Client and most of mob life files ommitted

* enviroment file

* Admin optimizations

ahelp log system kept

* Mob ports 12/21

Flavor text preserved

* datums ported 12/21

* Game ported 12/21

* batch of duplicate fixes/dogborg work

Dogborgs need to be modernized to refractored borg standards.

* moar fixes

* Maps and futher compile fixes

* missed commit

* Noms

* specific release doesn't work

* Tg modernization patch (#115)

* sync (#3)

* shuttle auto call

* Merge /vore into /master (#39)

* progress

* Compile errors fixed

No idea if it's test worthy tho as conflicts with race overhaul and
narky removal.

* Update admins.txt

* efforts continue

Fuck grab code, seriously

* grab code is cancer

* Execute the Narkism

Do not hesitate.

Show no mercy.

* holy shit grab code is awful

* have I bitched about grab code

My bitching, let me show you it

* código de agarre es una mierda

No really it is

* yeah I don't even know anymore.

* Lolnope. Fuck grab code

* I'm not even sure what to fix anymore

* Self eating is not an acceptable fate

* Taste the void, son.

* My code doesn't pass it's own sanity check.

Maybe it's a sign of things to come.

* uncommented and notes

* It Works and I Don't Know Why (#38)

* shuttle auto call

* it works and I don't know why

* Subsystem 12/21

Most Recent TG subsystem folder

* globalvars 12/21

Tossed out the flavor_misc and parallax files

* Onclick 12/21

as well as .dme updates

* _defines 12/21

ommited old _MC.dm

* _HELPERS 12/21

Preserved snowflake placement of furry sprites

* _defeines/genetics

reapplied narkism holdover for snowflake races.

* Oops forgot mutant colors

* modules porting 12/21 + Sounds/icons

Admin, Client and most of mob life files ommitted

* enviroment file

* Admin optimizations

ahelp log system kept

* Mob ports 12/21

Flavor text preserved

* datums ported 12/21

* Game ported 12/21

* batch of duplicate fixes/dogborg work

Dogborgs need to be modernized to refractored borg standards.

* moar fixes

* Maps and futher compile fixes

* port from cactus did

* fix format error

* Update preferences.dm

unfuck

* Revert "port from cactus did"

* unfuck

* more sprite work

* vore

* disabled roundstart xenos for now

* admin QOL

needs callback porting, TBD

* Mentor system initial port

I'm sure I've missed a fuckton of shit

* test merge

* Jesus tits did this finally fix compile issues?

* Initial test compiles. hooray.

* Admin ticket fixes

* I'll give you a bad argument you piece of shit dream maker I fucking swear on my mum

* who list wip

also ahelps are broken again. fuck if I know why

* discord bot basics

* maybe tickets work now & bot framework done

* ahelp callback readd

* vore tweaks

* progress

* Small fixes for dogborgs and sprite accessories:
-Ported the hidden snippets of the dogborg code.
-Reset module now resets pixel offset and icon directory again. (broke shit when reseting from dogborg)
-Medihound belly fixed.
-Husky body marking tweaked to not overlap arms in side view.
-Added husky ears that are basically wolf ears that use secondary color instead.

* dirtier fix than a korean hooker in the 60s

* The release your hooker will always fake

* you could save that hookers number but wouldn't you rather just vore the hooker instead

* Save system is literal black magic

* great googly moogly it's all gone to shit

* We May 2015 save code now

* fiddling with digestion code now

* fuck if I know anymore. I'm going to bed

* OWN UP YOUR OWN DIGESTION

* UNREGULATED GUTS ARE NON COMPLIANT

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

* BELLIES MUST COMPLY WITH USER OWNERSHIP

* Removed debug messages

* Unneeded verb additions

* file change tweaks

* WATCH YOUR SPACING, DRIVER

* Changelog and devourment for some mobs.

Because I knew people were gunna ask.

NO YOU CANNOT EAT THE FUCKING LEGION

* title screen change from Crow's PR.

* More of Crow's title screen stuff

* mode tweaks.... again

* gamemode voting in lobby via TalkingCactus
disabled ashwalkers as roundstart
Verk's species tweak
paralax starts disabled by default

* LOOC

* index sync problem (#158)

* digifix

* things

* furry races.dm

* actually deletes species_types

* maps

* tgui and stuff

* Sounds

* icon updates

* Defines and helpers

* global vars and on click

* controllers

* datums

* game folder

* fixes invisible flan mobs

* some modules

* dropbomb verb enhanced

* moar

* moar

* moar

* even more again

* and finally these for modules

* Some compile tweaks

* silly dme get updated you scrub

* compiles cleanly now

* various open PR fixes from TG

as of 0800 Texas Standard Time

* also fancy cryopods before I forget again

* headslug gold core fix

* some species and DNA tweaks

* Digest already damn you

* suddenly sound and resist works. wtf

* Minor tweaks, cryopod noise change

* Vore tested working, species working

* Merge test onto bleeding edgy (#165)

* sync (#3)

* shuttle auto call

* Merge /vore into /master (#39)

* progress

* Compile errors fixed

No idea if it's test worthy tho as conflicts with race overhaul and
narky removal.

* Update admins.txt

* efforts continue

Fuck grab code, seriously

* grab code is cancer

* Execute the Narkism

Do not hesitate.

Show no mercy.

* holy shit grab code is awful

* have I bitched about grab code

My bitching, let me show you it

* código de agarre es una mierda

No really it is

* yeah I don't even know anymore.

* Lolnope. Fuck grab code

* I'm not even sure what to fix anymore

* Self eating is not an acceptable fate

* Taste the void, son.

* My code doesn't pass it's own sanity check.

Maybe it's a sign of things to come.

* uncommented and notes

* It Works and I Don't Know Why (#38)

* shuttle auto call

* it works and I don't know why

* Escape and Devourable

For the normies who play here yet complain about it.

* Things that should be committed

* unneeded files

* Sizeray works now

* tweaks and bed time going

* IT WORKS mostly

Need to get multiple guts and saving working tho

* save tweaks

* item hotfix

* gut examine message

* damifino

* save system works

also ensured some mobs have vore controls, so silicons can't even
remotely do vore things.

* code nitpicking

* Midnight oil

More like 6am oil.  Still having issues with actually eating anyone.

* Subsystem 12/21

Most Recent TG subsystem folder

* globalvars 12/21

Tossed out the flavor_misc and parallax files

* Onclick 12/21

as well as .dme updates

* _defines 12/21

ommited old _MC.dm

* _HELPERS 12/21

Preserved snowflake placement of furry sprites

* _defeines/genetics

reapplied narkism holdover for snowflake races.

* Oops forgot mutant colors

* modules porting 12/21 + Sounds/icons

Admin, Client and most of mob life files ommitted

* enviroment file

* Admin optimizations

ahelp log system kept

* Mob ports 12/21

Flavor text preserved

* datums ported 12/21

* Game ported 12/21

* batch of duplicate fixes/dogborg work

Dogborgs need to be modernized to refractored borg standards.

* moar fixes

* Maps and futher compile fixes

* missed commit

* Noms

* specific release doesn't work

* Tg modernization patch (#115)

* sync (#3)

* shuttle auto call

* Merge /vore into /master (#39)

* progress

* Compile errors fixed

No idea if it's test worthy tho as conflicts with race overhaul and
narky removal.

* Update admins.txt

* efforts continue

Fuck grab code, seriously

* grab code is cancer

* Execute the Narkism

Do not hesitate.

Show no mercy.

* holy shit grab code is awful

* have I bitched about grab code

My bitching, let me show you it

* código de agarre es una mierda

No really it is

* yeah I don't even know anymore.

* Lolnope. Fuck grab code

* I'm not even sure what to fix anymore

* Self eating is not an acceptable fate

* Taste the void, son.

* My code doesn't pass it's own sanity check.

Maybe it's a sign of things to come.

* uncommented and notes

* It Works and I Don't Know Why (#38)

* shuttle auto call

* it works and I don't know why

* Subsystem 12/21

Most Recent TG subsystem folder

* globalvars 12/21

Tossed out the flavor_misc and parallax files

* Onclick 12/21

as well as .dme updates

* _defines 12/21

ommited old _MC.dm

* _HELPERS 12/21

Preserved snowflake placement of furry sprites

* _defeines/genetics

reapplied narkism holdover for snowflake races.

* Oops forgot mutant colors

* modules porting 12/21 + Sounds/icons

Admin, Client and most of mob life files ommitted

* enviroment file

* Admin optimizations

ahelp log system kept

* Mob ports 12/21

Flavor text preserved

* datums ported 12/21

* Game ported 12/21

* batch of duplicate fixes/dogborg work

Dogborgs need to be modernized to refractored borg standards.

* moar fixes

* Maps and futher compile fixes

* port from cactus did

* fix format error

* Update preferences.dm

unfuck

* Revert "port from cactus did"

* unfuck

* more sprite work

* vore

* disabled roundstart xenos for now

* admin QOL

needs callback porting, TBD

* Mentor system initial port

I'm sure I've missed a fuckton of shit

* test merge

* Jesus tits did this finally fix compile issues?

* Initial test compiles. hooray.

* Admin ticket fixes

* I'll give you a bad argument you piece of shit dream maker I fucking swear on my mum

* who list wip

also ahelps are broken again. fuck if I know why

* discord bot basics

* maybe tickets work now & bot framework done

* ahelp callback readd

* vore tweaks

* progress

* Small fixes for dogborgs and sprite accessories:
-Ported the hidden snippets of the dogborg code.
-Reset module now resets pixel offset and icon directory again. (broke shit when reseting from dogborg)
-Medihound belly fixed.
-Husky body marking tweaked to not overlap arms in side view.
-Added husky ears that are basically wolf ears that use secondary color instead.

* dirtier fix than a korean hooker in the 60s

* The release your hooker will always fake

* you could save that hookers number but wouldn't you rather just vore the hooker instead

* Save system is literal black magic

* great googly moogly it's all gone to shit

* We May 2015 save code now

* fiddling with digestion code now

* fuck if I know anymore. I'm going to bed

* OWN UP YOUR OWN DIGESTION

* UNREGULATED GUTS ARE NON COMPLIANT

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

* BELLIES MUST COMPLY WITH USER OWNERSHIP

* Removed debug messages

* Unneeded verb additions

* file change tweaks

* WATCH YOUR SPACING, DRIVER

* Changelog and devourment for some mobs.

Because I knew people were gunna ask.

NO YOU CANNOT EAT THE FUCKING LEGION

* title screen change from Crow's PR.

* More of Crow's title screen stuff

* mode tweaks.... again

* gamemode voting in lobby via TalkingCactus
disabled ashwalkers as roundstart
Verk's species tweak
paralax starts disabled by default

* LOOC

* index sync problem (#158)

* digifix

* things

* furry races.dm

* actually deletes species_types

* maps

* tgui and stuff

* Sounds

* icon updates

* Defines and helpers

* global vars and on click

* controllers

* datums

* game folder

* fixes invisible flan mobs

* some modules

* dropbomb verb enhanced

* moar

* moar

* moar

* even more again

* and finally these for modules

* Some compile tweaks

* silly dme get updated you scrub

* compiles cleanly now

* various open PR fixes from TG

as of 0800 Texas Standard Time

* also fancy cryopods before I forget again

* headslug gold core fix

* some species and DNA tweaks

* Digest already damn you

* suddenly sound and resist works. wtf

* Minor tweaks, cryopod noise change

* Vore tested working, species working

* travis map updates

* updates

* pool's closed due to lag

* datum pools are closed too

* Initializing new pool's closed

* Pool's closed and initializing shit is done

* sprite updates

* chattering is okay to do now.

* bleeblin edgy 1/23 (#166)

* sync (#3)

* shuttle auto call

* Merge /vore into /master (#39)

* progress

* Compile errors fixed

No idea if it's test worthy tho as conflicts with race overhaul and
narky removal.

* Update admins.txt

* efforts continue

Fuck grab code, seriously

* grab code is cancer

* Execute the Narkism

Do not hesitate.

Show no mercy.

* holy shit grab code is awful

* have I bitched about grab code

My bitching, let me show you it

* código de agarre es una mierda

No really it is

* yeah I don't even know anymore.

* Lolnope. Fuck grab code

* I'm not even sure what to fix anymore

* Self eating is not an acceptable fate

* Taste the void, son.

* My code doesn't pass it's own sanity check.

Maybe it's a sign of things to come.

* uncommented and notes

* It Works and I Don't Know Why (#38)

* shuttle auto call

* it works and I don't know why

* Escape and Devourable

For the normies who play here yet complain about it.

* Things that should be committed

* unneeded files

* Sizeray works now

* tweaks and bed time going

* IT WORKS mostly

Need to get multiple guts and saving working tho

* save tweaks

* item hotfix

* gut examine message

* damifino

* save system works

also ensured some mobs have vore controls, so silicons can't even
remotely do vore things.

* code nitpicking

* Midnight oil

More like 6am oil.  Still having issues with actually eating anyone.

* Subsystem 12/21

Most Recent TG subsystem folder

* globalvars 12/21

Tossed out the flavor_misc and parallax files

* Onclick 12/21

as well as .dme updates

* _defines 12/21

ommited old _MC.dm

* _HELPERS 12/21

Preserved snowflake placement of furry sprites

* _defeines/genetics

reapplied narkism holdover for snowflake races.

* Oops forgot mutant colors

* modules porting 12/21 + Sounds/icons

Admin, Client and most of mob life files ommitted

* enviroment file

* Admin optimizations

ahelp log system kept

* Mob ports 12/21

Flavor text preserved

* datums ported 12/21

* Game ported 12/21

* batch of duplicate fixes/dogborg work

Dogborgs need to be modernized to refractored borg standards.

* moar fixes

* Maps and futher compile fixes

* missed commit

* Noms

* specific release doesn't work

* Tg modernization patch (#115)

* sync (#3)

* shuttle auto call

* Merge /vore into /master (#39)

* progress

* Compile errors fixed

No idea if it's test worthy tho as conflicts with race overhaul and
narky removal.

* Update admins.txt

* efforts continue

Fuck grab code, seriously

* grab code is cancer

* Execute the Narkism

Do not hesitate.

Show no mercy.

* holy shit grab code is awful

* have I bitched about grab code

My bitching, let me show you it

* código de agarre es una mierda

No really it is

* yeah I don't even know anymore.

* Lolnope. Fuck grab code

* I'm not even sure what to fix anymore

* Self eating is not an acceptable fate

* Taste the void, son.

* My code doesn't pass it's own sanity check.

Maybe it's a sign of things to come.

* uncommented and notes

* It Works and I Don't Know Why (#38)

* shuttle auto call

* it works and I don't know why

* Subsystem 12/21

Most Recent TG subsystem folder

* globalvars 12/21

Tossed out the flavor_misc and parallax files

* Onclick 12/21

as well as .dme updates

* _defines 12/21

ommited old _MC.dm

* _HELPERS 12/21

Preserved snowflake placement of furry sprites

* _defeines/genetics

reapplied narkism holdover for snowflake races.

* Oops forgot mutant colors

* modules porting 12/21 + Sounds/icons

Admin, Client and most of mob life files ommitted

* enviroment file

* Admin optimizations

ahelp log system kept

* Mob ports 12/21

Flavor text preserved

* datums ported 12/21

* Game ported 12/21

* batch of duplicate fixes/dogborg work

Dogborgs need to be modernized to refractored borg standards.

* moar fixes

* Maps and futher compile fixes

* port from cactus did

* fix format error

* Update preferences.dm

unfuck

* Revert "port from cactus did"

* unfuck

* more sprite work

* vore

* disabled roundstart xenos for now

* admin QOL

needs callback porting, TBD

* Mentor system initial port

I'm sure I've missed a fuckton of shit

* test merge

* Jesus tits did this finally fix compile issues?

* Initial test compiles. hooray.

* Admin ticket fixes

* I'll give you a bad argument you piece of shit dream maker I fucking swear on my mum

* who list wip

also ahelps are broken again. fuck if I know why

* discord bot basics

* maybe tickets work now & bot framework done

* ahelp callback readd

* vore tweaks

* progress

* Small fixes for dogborgs and sprite accessories:
-Ported the hidden snippets of the dogborg code.
-Reset module now resets pixel offset and icon directory again. (broke shit when reseting from dogborg)
-Medihound belly fixed.
-Husky body marking tweaked to not overlap arms in side view.
-Added husky ears that are basically wolf ears that use secondary color instead.

* dirtier fix than a korean hooker in the 60s

* The release your hooker will always fake

* you could save that hookers number but wouldn't you rather just vore the hooker instead

* Save system is literal black magic

* great googly moogly it's all gone to shit

* We May 2015 save code now

* fiddling with digestion code now

* fuck if I know anymore. I'm going to bed

* OWN UP YOUR OWN DIGESTION

* UNREGULATED GUTS ARE NON COMPLIANT

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

* BELLIES MUST COMPLY WITH USER OWNERSHIP

* Removed debug messages

* Unneeded verb additions

* file change tweaks

* WATCH YOUR SPACING, DRIVER

* Changelog and devourment for some mobs.

Because I knew people were gunna ask.

NO YOU CANNOT EAT THE FUCKING LEGION

* title screen change from Crow's PR.

* More of Crow's title screen stuff

* mode tweaks.... again

* gamemode voting in lobby via TalkingCactus
disabled ashwalkers as roundstart
Verk's species tweak
paralax starts disabled by default

* LOOC

* index sync problem (#158)

* digifix

* things

* furry races.dm

* actually deletes species_types

* maps

* tgui and stuff

* Sounds

* icon updates

* Defines and helpers

* global vars and on click

* controllers

* datums

* game folder

* fixes invisible flan mobs

* some modules

* dropbomb verb enhanced

* moar

* moar

* moar

* even more again

* and finally these for modules

* Some compile tweaks

* silly dme get updated you scrub

* compiles cleanly now

* various open PR fixes from TG

as of 0800 Texas Standard Time

* also fancy cryopods before I forget again

* headslug gold core fix

* some species and DNA tweaks

* Digest already damn you

* suddenly sound and resist works. wtf

* Minor tweaks, cryopod noise change

* Vore tested working, species working

* travis map updates

* updates

* pool's closed due to lag

* datum pools are closed too

* Initializing new pool's closed

* Pool's closed and initializing shit is done

* sprite updates

* chattering is okay to do now.

* Update .travis.yml

* Update .travis.yml

* Update .travis.yml

* Revert "Modern modern"

* Revert "Revert "Modern modern""

* fix it fix it fix it fix it

* fixes title screen - thanks crow

* Riding code reverted

* possible tgui fix?

* who the fuck even knows if this is the problem

* adds moths and sharks (no colors yet, not greyscaled)
adds LOOC back

* "fixes" missing items in some machinery.

* slight tweaks to abductor spawns
borer event enabled (max 1)

* Update .travis.yml

* fixes shuttle purchase from comms

* fixes and QoL

* Polymorphing all is dangerous too

* re-fixes ahelp ticket system again

* metagaming check proving to be spamlicious

* Fixes not being able to see devoured mob poses

* fix for vehicle buckling

* ahelp timer runtime fix (#178)

* controller and game updates 1/29

* Defines, helpers, datums 1/29

* world.dm updates

* modules/admin tweaks

* everything in modules not a mob

* modules/mob fixes and such

No more PAIs ventcrawling

* icons, maps, tools, etc.

* compiler fixes

* round type vote fixed

* hardsuit cargo pack

* reduce ion and electric storm chance

* perms access for travis

* fix helmet to the suit
removes CE from crate

* changelog

* fuck

* perms for travis... again

* Update tgstation.dme

* Update tgstation.dme

* Donation race

* redpanda

* red panda

* size play work

* Size chemical basics

Needs testing/refining

* some fixing ports before I just fucking ported it anyway

* It's been a fucking week.

* commiting moar changes because github

* admins.txt lol

* icons

* defines and such

* globalvars and onclick

* Controllers

* datums

* game folder

* oh look, HoG is back

* modules pt 1

* client things

* more modules

* everything not mob code

* some mob stuff

* more mob things

* silicon mobs

* ayylims and monkeys

* human updates

* huh

* housekeeping is fired.

* last minute fixes

* more last minute things

* human parts double check'd

* more paper

* Icons are fixed

* double check of thermal protection code. (#191)
This commit is contained in:
TalkingCactus
2017-02-03 06:56:14 -05:00
committed by Poojawa
parent 7735dec0ec
commit f7c09077d2
2489 changed files with 830965 additions and 416701 deletions
+26 -48
View File
@@ -22,7 +22,7 @@
// Takes care blood loss and regeneration
/mob/living/carbon/human/handle_blood()
if(NOBLOOD in dna.species.specflags)
if(NOBLOOD in dna.species.species_traits)
bleed_rate = 0
return
@@ -86,7 +86,7 @@
add_splatter_floor(src.loc, 1)
/mob/living/carbon/human/bleed(amt)
if(!(NOBLOOD in dna.species.specflags))
if(!(NOBLOOD in dna.species.species_traits))
..()
@@ -162,8 +162,13 @@
blood_data["trace_chem"] = list2params(temp_chem)
if(mind)
blood_data["mind"] = mind
else if(last_mind)
blood_data["mind"] = last_mind
if(ckey)
blood_data["ckey"] = ckey
else if(last_mind)
blood_data["ckey"] = ckey(last_mind.key)
if(!suiciding)
blood_data["cloneable"] = 1
blood_data["blood_type"] = copytext(dna.blood_type,1,0)
@@ -188,7 +193,7 @@
/mob/living/carbon/human/get_blood_id()
if(dna.species.exotic_blood)
return dna.species.exotic_blood
else if((NOBLOOD in dna.species.specflags) || (disabilities & NOCLONE))
else if((NOBLOOD in dna.species.species_traits) || (disabilities & NOCLONE))
return
return "blood"
@@ -216,70 +221,43 @@
return list("O-", "O+")
if("L")
return list("L")
if("X")
return list("X")
//to add a splatter of blood or other mob liquid.
/mob/living/proc/add_splatter_floor(turf/T, small_drip)
if(get_blood_id() != "blood" && get_blood_id() != "xblood")
if(get_blood_id() != "blood")
return
if(!T)
T = get_turf(src)
var/list/temp_blood_DNA
if(small_drip)
// Only a certain number of drips (or one large splatter) can be on a given turf.
if(ishuman(src))
var/mob/living/carbon/human/H = src
if(H.dna.species.id == "xeno")
var/obj/effect/decal/cleanable/xdrip/xdrop = locate() in T
if(xdrop)
if(xdrop.drips < 3)
xdrop.drips++
xdrop.overlays |= pick(xdrop.random_icon_states)
xdrop.transfer_mob_blood_dna(src)
return
else
temp_blood_DNA = list()
temp_blood_DNA |= xdrop.blood_DNA.Copy()
qdel(xdrop)//the drip is replaced by a bigger splatter
else
xdrop = new(T)
xdrop.transfer_mob_blood_dna(src)
return
else
var/obj/effect/decal/cleanable/blood/drip/drop = locate() in T
if(drop)
if(drop.drips < 3)
drop.drips++
drop.overlays |= pick(drop.random_icon_states)
drop.transfer_mob_blood_dna(src)
return
else
temp_blood_DNA = list()
temp_blood_DNA |= drop.blood_DNA.Copy() //we transfer the dna from the drip to the splatter
qdel(drop)//the drip is replaced by a bigger splatter
else
drop = new(T)
var/obj/effect/decal/cleanable/blood/drip/drop = locate() in T
if(drop)
if(drop.drips < 3)
drop.drips++
drop.overlays |= pick(drop.random_icon_states)
drop.transfer_mob_blood_dna(src)
return
else
temp_blood_DNA = list()
temp_blood_DNA |= drop.blood_DNA.Copy() //we transfer the dna from the drip to the splatter
qdel(drop)//the drip is replaced by a bigger splatter
else
drop = new(T)
drop.transfer_mob_blood_dna(src)
return
// Find a blood decal or create a new one.
var/obj/effect/decal/cleanable/blood/B = locate() in T
if(!B)
if(ishuman(src))
var/mob/living/carbon/human/H = src
if(H.dna.species.id == "xeno")
B = new /obj/effect/decal/cleanable/xenoblood(T)
else
B = new /obj/effect/decal/cleanable/blood/splatter(T)
else
B = new /obj/effect/decal/cleanable/blood/splatter(T)
B = new /obj/effect/decal/cleanable/blood/splatter(T)
B.transfer_mob_blood_dna(src) //give blood info to the blood decal.
if(temp_blood_DNA)
B.blood_DNA |= temp_blood_DNA
/mob/living/carbon/human/add_splatter_floor(turf/T, small_drip)
if(!(NOBLOOD in dna.species.specflags))
if(!(NOBLOOD in dna.species.species_traits))
..()
/mob/living/carbon/alien/add_splatter_floor(turf/T, small_drip)
@@ -295,4 +273,4 @@
T = get_turf(src)
var/obj/effect/decal/cleanable/oil/B = locate() in T.contents
if(!B)
B = new(T)
B = new(T)
+8 -13
View File
@@ -6,7 +6,7 @@
density = 0
anchored = 1
invisibility = 60
burn_state = LAVA_PROOF
resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
/obj/effect/dummy/slaughter/relaymove(mob/user, direction)
forceMove(get_step(src,direction))
@@ -19,15 +19,12 @@
/obj/effect/dummy/slaughter/singularity_act()
return
/obj/effect/dummy/slaughter/Destroy()
..()
return QDEL_HINT_PUTINPOOL
/mob/living/proc/phaseout(obj/effect/decal/cleanable/B)
if(iscarbon(src))
var/mob/living/carbon/C = src
if(C.l_hand || C.r_hand)
for(var/obj/item/I in C.held_items)
//TODO make it toggleable to either forcedrop the items, or deny
//entry when holding them
// literally only an option for carbons though
@@ -53,7 +50,7 @@
playsound(get_turf(src), 'sound/magic/enter_blood.ogg', 100, 1, -1)
// Extinguish, unbuckle, stop being pulled, set our location into the
// dummy object
var/obj/effect/dummy/slaughter/holder = PoolOrNew(/obj/effect/dummy/slaughter,mobloc)
var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(mobloc)
src.ExtinguishMob()
// Keep a reference to whatever we're pulling, because forceMove()
@@ -68,7 +65,7 @@
return
// if the thing we're pulling isn't alive
if (!(istype(pullee, /mob/living)))
if (!isliving(pullee))
return
var/mob/living/victim = pullee
@@ -145,15 +142,14 @@
/mob/living/proc/exit_blood_effect(obj/effect/decal/cleanable/B)
playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
var/oldcolor = src.color
//Makes the mob have the color of the blood pool it came out of
var/newcolor = rgb(149, 10, 10)
if(istype(B, /obj/effect/decal/cleanable/xenoblood))
src.color = rgb(43, 186, 0)
else
src.color = rgb(149, 10, 10)
newcolor = rgb(43, 186, 0)
add_atom_colour(newcolor, TEMPORARY_COLOUR_PRIORITY)
// but only for a few seconds
spawn(30)
src.color = oldcolor
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, newcolor)
/mob/living/proc/phasein(obj/effect/decal/cleanable/B)
if(src.notransform)
@@ -172,7 +168,6 @@
var/mob/living/carbon/C = src
for(var/obj/item/weapon/bloodcrawl/BC in C)
BC.flags = null
C.unEquip(BC)
qdel(BC)
qdel(src.holder)
src.holder = null
@@ -1,20 +1,20 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
/obj/item/device/mmi
name = "Man-Machine Interface"
desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity, that nevertheless has become standard-issue on Nanotrasen stations."
icon = 'icons/obj/assemblies.dmi'
icon_state = "mmi_empty"
w_class = 3
w_class = WEIGHT_CLASS_NORMAL
origin_tech = "biotech=2;programming=3;engineering=2"
var/braintype = "Cyborg"
var/obj/item/device/radio/radio = null //Let's give it a radio.
var/hacked = 0 //Whether or not this is a Syndicate MMI
var/mob/living/carbon/brain/brainmob = null //The current occupant.
var/mob/living/brain/brainmob = null //The current occupant.
var/mob/living/silicon/robot = null //Appears unused.
var/obj/mecha = null //This does not appear to be used outside of reference in mecha.dm.
var/obj/item/organ/brain/brain = null //The actual brain
var/clockwork = FALSE //If this is a soul vessel
var/datum/ai_laws/laws = new()
var/force_replace_ai_name = FALSE
/obj/item/device/mmi/update_icon()
if(brain)
@@ -38,7 +38,9 @@
radio = new(src) //Spawns a radio inside the MMI.
radio.broadcasting = 0 //researching radio mmis turned the robofabs into radios because this didnt start as 0.
/obj/item/device/mmi/Initialize()
..()
laws.set_laws_config()
/obj/item/device/mmi/attackby(obj/item/O, mob/user, params)
user.changeNext_move(CLICK_CD_MELEE)
@@ -51,9 +53,9 @@
user << "<span class='warning'>You aren't sure where this brain came from, but you're pretty sure it's a useless brain!</span>"
return
if(!user.unEquip(O))
if(!user.transferItemToLoc(O, src))
return
var/mob/living/carbon/brain/B = newbrain.brainmob
var/mob/living/brain/B = newbrain.brainmob
if(!B.key)
B.notify_ghost_cloning("Someone has put your brain in a MMI!", source = src)
visible_message("[user] sticks \a [newbrain] into \the [src].")
@@ -68,9 +70,6 @@
living_mob_list += brainmob
brainmob.reset_perspective()
if(clockwork)
add_servant_of_ratvar(brainmob, TRUE)
newbrain.loc = src //P-put your brain in it
brain = newbrain
name = "Man-Machine Interface: [brainmob.real_name]"
@@ -78,12 +77,11 @@
feedback_inc("cyborg_mmis_filled",1)
return
else if(brainmob)
O.attack(brainmob, user) //Oh noooeeeee
return
..()
else
return ..()
/obj/item/device/mmi/attack_self(mob/user)
if(!brain)
@@ -91,23 +89,27 @@
user << "<span class='notice'>You toggle the MMI's radio system [radio.on==1 ? "on" : "off"].</span>"
else
user << "<span class='notice'>You unlock and upend the MMI, spilling the brain onto the floor.</span>"
brainmob.container = null //Reset brainmob mmi var.
brainmob.loc = brain //Throw mob into brain.
brainmob.stat = DEAD
brainmob.emp_damage = 0
brainmob.reset_perspective() //so the brainmob follows the brain organ instead of the mmi. And to update our vision
living_mob_list -= brainmob //Get outta here
dead_mob_list += brainmob
brain.brainmob = brainmob //Set the brain to use the brainmob
brainmob = null //Set mmi brainmob var to null
user.put_in_hands(brain) //puts brain in the user's hand or otherwise drops it on the user's turf
brain = null //No more brain in here
eject_brain(user)
update_icon()
name = "Man-Machine Interface"
/obj/item/device/mmi/proc/eject_brain(mob/user)
brainmob.container = null //Reset brainmob mmi var.
brainmob.loc = brain //Throw mob into brain.
brainmob.stat = DEAD
brainmob.emp_damage = 0
brainmob.reset_perspective() //so the brainmob follows the brain organ instead of the mmi. And to update our vision
living_mob_list -= brainmob //Get outta here
dead_mob_list += brainmob
brain.brainmob = brainmob //Set the brain to use the brainmob
brainmob = null //Set mmi brainmob var to null
if(user)
user.put_in_hands(brain) //puts brain in the user's hand or otherwise drops it on the user's turf
else
brain.forceMove(get_turf(src))
brain = null //No more brain in here
/obj/item/device/mmi/proc/transfer_identity(mob/living/L) //Same deal as the regular brain proc. Used for human-->robot people.
if(!brainmob)
brainmob = new(src)
@@ -115,9 +117,9 @@
brainmob.real_name = L.real_name
if(L.has_dna())
var/mob/living/carbon/C = L
if(!brainmob.dna)
brainmob.dna = new /datum/dna(brainmob)
C.dna.copy_dna(brainmob.dna)
if(!brainmob.stored_dna)
brainmob.stored_dna = new /datum/dna/stored(brainmob)
C.dna.copy_dna(brainmob.stored_dna)
brainmob.container = src
if(ishuman(L))
@@ -133,6 +135,8 @@
update_icon()
return
/obj/item/device/mmi/proc/replacement_ai_name()
return brainmob.name
/obj/item/device/mmi/verb/Toggle_Listening()
set name = "Toggle Listening"
@@ -151,7 +155,7 @@
brainmob << "<span class='notice'>Radio is [radio.listening==1 ? "now" : "no longer"] receiving broadcast.</span>"
/obj/item/device/mmi/emp_act(severity)
if(!brainmob)
if(!brainmob || iscyborg(loc))
return
else
switch(severity)
@@ -165,18 +169,31 @@
..()
/obj/item/device/mmi/Destroy()
if(isrobot(loc))
if(iscyborg(loc))
var/mob/living/silicon/robot/borg = loc
borg.mmi = null
if(brainmob)
qdel(brainmob)
brainmob = null
if(brain)
qdel(brain)
brain = null
if(mecha)
mecha = null
if(radio)
qdel(radio)
radio = null
return ..()
/obj/item/device/mmi/deconstruct(disassembled = TRUE)
if(brain)
eject_brain()
qdel(src)
/obj/item/device/mmi/examine(mob/user)
..()
if(brainmob)
var/mob/living/carbon/brain/B = brainmob
var/mob/living/brain/B = brainmob
if(!B.key || !B.mind || B.stat == DEAD)
user << "<span class='warning'>The MMI indicates the brain is completely unresponsive.</span>"
@@ -189,10 +206,10 @@
/obj/item/device/mmi/syndie
name = "Syndicate Man-Machine Interface"
desc = "Syndicate's own brand of MMI. It enforces laws designed to help Syndicate agents achieve their goals upon cyborgs created with it, but doesn't fit in Nanotrasen AI cores."
desc = "Syndicate's own brand of MMI. It enforces laws designed to help Syndicate agents achieve their goals upon cyborgs and AIs created with it."
origin_tech = "biotech=4;programming=4;syndicate=2"
hacked = 1
/obj/item/device/mmi/syndie/New()
..()
laws = new /datum/ai_laws/syndicate_override()
radio.on = 0
+67
View File
@@ -0,0 +1,67 @@
/mob/living/brain
languages_spoken = HUMAN
languages_understood = HUMAN
var/obj/item/device/mmi/container = null
var/timeofhostdeath = 0
var/emp_damage = 0//Handles a type of MMI damage
var/datum/dna/stored/stored_dna // dna var for brain. Used to store dna, brain dna is not considered like actual dna, brain.has_dna() returns FALSE.
stat = DEAD //we start dead by default
see_invisible = SEE_INVISIBLE_MINIMUM
/mob/living/brain/New(loc)
..()
create_dna(src)
stored_dna.initialize_dna(random_blood_type())
if(isturf(loc)) //not spawned in an MMI or brain organ (most likely adminspawned)
var/obj/item/organ/brain/OB = new(loc) //we create a new brain organ for it.
src.loc = OB
OB.brainmob = src
/mob/living/brain/proc/create_dna()
stored_dna = new /datum/dna/stored(src)
if(!stored_dna.species)
var/rando_race = pick(config.roundstart_races)
stored_dna.species = new rando_race()
/mob/living/brain/Destroy()
if(key) //If there is a mob connected to this thing. Have to check key twice to avoid false death reporting.
if(stat!=DEAD) //If not dead.
death(1) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA
ghostize() //Ghostize checks for key so nothing else is necessary.
container = null
return ..()
/mob/living/brain/update_canmove()
if(in_contents_of(/obj/mecha))
canmove = 1
else
canmove = 0
return canmove
/mob/living/brain/ex_act() //you cant blow up brainmobs because it makes transfer_to() freak out when borgs blow up.
return
/mob/living/brain/blob_act(obj/structure/blob/B)
return
/mob/living/brain/get_eye_protection()//no eyes
return 2
/mob/living/brain/get_ear_protection()//no ears
return 2
/mob/living/brain/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
return // no eyes, no flashing
/mob/living/brain/can_be_revived()
. = 1
if(!container || health <= HEALTH_THRESHOLD_DEAD)
return 0
/mob/living/brain/fully_replace_character_name(oldname,newname)
..()
if(stored_dna)
stored_dna.real_name = real_name
@@ -10,35 +10,35 @@
vital = 1
origin_tech = "biotech=5"
attack_verb = list("attacked", "slapped", "whacked")
var/mob/living/carbon/brain/brainmob = null
var/damaged_brain = 0 //whether the brain organ is damaged.
var/mob/living/brain/brainmob = null
var/damaged_brain = FALSE //whether the brain organ is damaged.
var/decoy_override = FALSE //I apologize to the security players, and myself, who abused this, but this is going to go.
/obj/item/organ/brain/Insert(mob/living/carbon/M, special = 0)
/obj/item/organ/brain/Insert(mob/living/carbon/C, special = 0)
..()
name = "brain"
if(brainmob)
if(M.key)
M.ghostize()
if(C.key)
C.ghostize()
if(brainmob.mind)
brainmob.mind.transfer_to(M)
brainmob.mind.transfer_to(C)
else
M.key = brainmob.key
C.key = brainmob.key
qdel(brainmob)
//Update the body's icon so it doesnt appear debrained anymore
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.update_hair(0)
C.update_hair()
/obj/item/organ/brain/Remove(mob/living/carbon/M, special = 0)
/obj/item/organ/brain/Remove(mob/living/carbon/C, special = 0)
..()
if(!special)
transfer_identity(M)
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.update_hair(0)
if(C.has_brain_worms())
var/mob/living/simple_animal/borer/B = C.has_brain_worms()
B.leave_victim() //Should remove borer if the brain is removed - RR
transfer_identity(C)
C.update_hair()
/obj/item/organ/brain/prepare_eat()
return // Too important to eat.
@@ -51,9 +51,9 @@
brainmob.timeofhostdeath = L.timeofdeath
if(L.has_dna())
var/mob/living/carbon/C = L
if(!brainmob.dna)
brainmob.dna = new /datum/dna(brainmob)
C.dna.copy_dna(brainmob.dna)
if(!brainmob.stored_dna)
brainmob.stored_dna = new /datum/dna/stored(brainmob)
C.dna.copy_dna(brainmob.stored_dna)
if(L.mind && L.mind.current && (L.mind.current.stat == DEAD))
L.mind.transfer_to(brainmob)
brainmob << "<span class='notice'>You feel slightly disoriented. That's normal when you're just a brain.</span>"
@@ -68,17 +68,20 @@
if(brainmob)
if(brainmob.client)
if(brainmob.health <= config.health_threshold_dead)
if(brainmob.health <= HEALTH_THRESHOLD_DEAD)
user << "It's lifeless and severely damaged."
else
user << "You can feel the small spark of life still left in this one."
else
user << "This one seems particularly lifeless. Perhaps it will regain some of its luster later."
else
user << "This one is completely devoid of life."
if(decoy_override)
user << "This one seems particularly lifeless. Perhaps it will regain some of its luster later."
else
user << "This one is completely devoid of life."
/obj/item/organ/brain/attack(mob/living/carbon/M, mob/user)
if(!istype(M))
/obj/item/organ/brain/attack(mob/living/carbon/C, mob/user)
if(!istype(C))
return ..()
add_fingerprint(user)
@@ -86,31 +89,30 @@
if(user.zone_selected != "head")
return ..()
var/mob/living/carbon/human/H = M
if(istype(H) && ((H.head && H.head.flags_cover & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) || (H.glasses && H.glasses.flags & GLASSESCOVERSEYES)))
if((C.head && (C.head.flags_cover & HEADCOVERSEYES)) || (C.wear_mask && (C.wear_mask.flags_cover & MASKCOVERSEYES)) || (C.glasses && (C.glasses.flags & GLASSESCOVERSEYES)))
user << "<span class='warning'>You're going to need to remove their head cover first!</span>"
return
//since these people will be dead M != usr
if(!M.getorgan(/obj/item/organ/brain))
if(istype(H) && !H.get_bodypart("head"))
if(!C.getorgan(/obj/item/organ/brain))
if(!C.get_bodypart("head"))
return
user.drop_item()
var/msg = "[M] has [src] inserted into \his head by [user]."
if(M == user)
msg = "[user] inserts [src] into \his head!"
var/msg = "[C] has [src] inserted into [C.p_their()] head by [user]."
if(C == user)
msg = "[user] inserts [src] into [user.p_their()] head!"
M.visible_message("<span class='danger'>[msg]</span>",
C.visible_message("<span class='danger'>[msg]</span>",
"<span class='userdanger'>[msg]</span>")
if(M != user)
M << "<span class='notice'>[user] inserts [src] into your head.</span>"
user << "<span class='notice'>You insert [src] into [M]'s head.</span>"
if(C != user)
C << "<span class='notice'>[user] inserts [src] into your head.</span>"
user << "<span class='notice'>You insert [src] into [C]'s head.</span>"
else
user << "<span class='notice'>You insert [src] into your head.</span>" //LOL
Insert(M)
Insert(C)
else
..()
@@ -1,4 +1,4 @@
/mob/living/carbon/brain/death(gibbed)
/mob/living/brain/death(gibbed)
if(stat == DEAD)
return
stat = DEAD
@@ -11,7 +11,7 @@
return ..()
/mob/living/carbon/brain/gib()
/mob/living/brain/gib()
if(container)
qdel(container)//Gets rid of the MMI if there is one
if(loc)
+34
View File
@@ -0,0 +1,34 @@
/datum/emote/brain
mob_type_allowed_typecache = list(/mob/living/brain)
mob_type_blacklist_typecache = list()
/datum/emote/brain/can_run_emote(mob/user)
. = ..()
var/mob/living/brain/B = user
if(!istype(B) || (!(B.container && istype(B.container, /obj/item/device/mmi))))
return FALSE
/datum/emote/brain/alarm
key = "alarm"
message = "sounds an alarm."
emote_type = EMOTE_AUDIBLE
/datum/emote/brain/alert
key = "alert"
message = "lets out a distressed noise."
emote_type = EMOTE_AUDIBLE
/datum/emote/brain/flash
key = "flash"
message = "lights' blink."
/datum/emote/brain/notice
key = "notice"
message = "plays a loud tone."
emote_type = EMOTE_AUDIBLE
/datum/emote/brain/whistle
key = "whistle"
key_third_person = "whistles"
message = "whistles."
emote_type = EMOTE_AUDIBLE
@@ -1,5 +1,5 @@
/mob/living/carbon/brain/Life()
/mob/living/brain/Life()
set invisibility = 0
set background = BACKGROUND_ENABLED
@@ -10,19 +10,10 @@
. = ..()
handle_emp_damage()
/mob/living/carbon/brain/handle_breathing()
return
/mob/living/carbon/brain/handle_mutations_and_radiation()
return
/mob/living/carbon/brain/handle_environment(datum/gas_mixture/environment)
return
/mob/living/carbon/brain/update_stat()
/mob/living/brain/update_stat()
if(status_flags & GODMODE)
return
if(health <= config.health_threshold_dead)
if(health <= HEALTH_THRESHOLD_DEAD)
if(stat != DEAD)
death()
var/obj/item/organ/brain/BR
@@ -34,27 +25,25 @@
BR.damaged_brain = 1 //beaten to a pulp
/* //currently unused feature, since brain outside a mmi is always dead.
/mob/living/carbon/brain/proc/handle_brain_revival_life()
/mob/living/brain/proc/handle_brain_revival_life()
if(stat != DEAD)
if(config.revival_brain_life != -1)
if( !container && (world.time - timeofhostdeath) > config.revival_brain_life)
death()
*/
/mob/living/carbon/brain/proc/handle_emp_damage()
/mob/living/brain/proc/handle_emp_damage()
if(emp_damage)
if(stat == DEAD)
emp_damage = 0
else
emp_damage = max(emp_damage-1, 0)
/mob/living/carbon/brain/handle_status_effects()
/mob/living/brain/handle_status_effects()
return
/mob/living/carbon/brain/handle_disabilities()
return
/mob/living/carbon/brain/handle_changeling()
/mob/living/brain/handle_disabilities()
return
@@ -5,7 +5,7 @@ var/global/posibrain_notif_cooldown = 0
desc = "A cube of shining metal, four inches to a side and covered in shallow grooves."
icon = 'icons/obj/assemblies.dmi'
icon_state = "posibrain"
w_class = 3
w_class = WEIGHT_CLASS_NORMAL
origin_tech = "biotech=3;programming=3;plasmatech=2"
var/notified = 0
var/askDelay = 600 //one minute
@@ -14,6 +14,7 @@ var/global/posibrain_notif_cooldown = 0
req_access = list(access_robotics)
mecha = null//This does not appear to be used outside of reference in mecha.dm.
braintype = "Android"
var/autoping = TRUE //if it pings on creation immediately
var/begin_activation_message = "<span class='notice'>You carefully locate the manual activation switch and start the positronic brain's boot process.</span>"
var/success_message = "<span class='notice'>The positronic brain pings, and its lights start flashing. Success!</span>"
var/fail_message = "<span class='notice'>The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?</span>"
@@ -25,6 +26,7 @@ var/global/posibrain_notif_cooldown = 0
var/new_mob_message = "<span class='notice'>The positronic brain chimes quietly.</span>"
var/dead_message = "<span class='deadsay'>It appears to be completely inactive. The reset light is blinking.</span>"
var/list/fluff_names = list("PBU","HIU","SINA","ARMA","OSI","HBL","MSO","RR","CHRI","CDB","HG","XSI","ORNG","GUN","KOR","MET","FRE","XIS","SLI","PKP","HOG","RZH","GOOF","MRPR","JJR","FIRC","INC","PHL","BGB","ANTR","MIW","WJ","JRD","CHOC","ANCL","JLLO","JNLG","KOS","TKRG","XAL","STLP","CBOS","DUNC","FXMC","DRSD")
var/picked_fluff_name //which fluff name we picked
/obj/item/device/mmi/posibrain/Topic(href, href_list)
@@ -38,7 +40,7 @@ var/global/posibrain_notif_cooldown = 0
notify_ghosts("[name] [msg] in [get_area(src)]!", ghost_sound = !newlymade ? 'sound/effects/ghost2.ogg':null, enter_link = "<a href=?src=\ref[src];activate=1>(Click to enter)</a>", source = src, action = NOTIFY_ATTACK)
if(!newlymade)
posibrain_notif_cooldown = 1
addtimer(src, "reset_posibrain_cooldown", askDelay, FALSE)
addtimer(CALLBACK(src, .proc/reset_posibrain_cooldown), askDelay)
/obj/item/device/mmi/posibrain/proc/reset_posibrain_cooldown()
posibrain_notif_cooldown = 0
@@ -79,11 +81,10 @@ var/global/posibrain_notif_cooldown = 0
name = "[initial(name)] ([C])"
brainmob.name = C.real_name
brainmob.real_name = C.real_name
brainmob.dna = C.dna
if(C.has_dna())
if(!brainmob.dna)
brainmob.dna = new /datum/dna(brainmob)
C.dna.copy_dna(brainmob.dna)
if(!brainmob.stored_dna)
brainmob.stored_dna = new /datum/dna/stored(brainmob)
C.dna.copy_dna(brainmob.stored_dna)
brainmob.timeofhostdeath = C.timeofdeath
brainmob.stat = CONSCIOUS
if(brainmob.mind)
@@ -94,61 +95,53 @@ var/global/posibrain_notif_cooldown = 0
brainmob.mind.remove_all_antag()
brainmob.mind.wipe_memory()
update_icon()
return
/obj/item/device/mmi/posibrain/proc/transfer_personality(mob/candidate)
if(used || (brainmob && brainmob.key)) //Prevents hostile takeover if two ghosts get the prompt or link for the same brain.
candidate << "This brain has already been taken! Please try your possesion again later!"
return
candidate << "This brain has already been taken! Please try your possession again later!"
return FALSE
notified = 0
brainmob.ckey = candidate.ckey
if(candidate.mind && !isobserver(candidate))
candidate.mind.transfer_to(brainmob)
else
brainmob.ckey = candidate.ckey
name = "[initial(name)] ([brainmob.name])"
brainmob << welcome_message
brainmob.mind.assigned_role = new_role
brainmob.stat = CONSCIOUS
dead_mob_list -= brainmob
living_mob_list += brainmob
if(clockwork)
add_servant_of_ratvar(brainmob, TRUE)
visible_message(new_mob_message)
update_icon()
used = 1
return TRUE
/obj/item/device/mmi/posibrain/examine()
set src in oview()
if(!usr || !src)
return
if( (usr.disabilities & BLIND || usr.stat) && !istype(usr,/mob/dead/observer) )
usr << "<span class='notice'>Something is there but you can't see it.</span>"
return
var/msg = "<span class='info'>*---------*\nThis is \icon[src] \a <EM>[src]</EM>!\n[desc]\n"
msg += "<span class='warning'>"
/obj/item/device/mmi/posibrain/examine(mob/user)
. = ..()
var/msg
if(brainmob && brainmob.key)
switch(brainmob.stat)
if(CONSCIOUS)
if(!src.brainmob.client)
msg += "It appears to be in stand-by mode.\n" //afk
msg = "It appears to be in stand-by mode." //afk
if(DEAD)
msg += "<span class='deadsay'>It appears to be completely inactive.</span>\n"
msg = "<span class='deadsay'>It appears to be completely inactive.</span>"
else
msg += "[dead_message]\n"
msg += "<span class='info'>*---------*</span>"
usr << msg
return
msg = "[dead_message]"
user << msg
/obj/item/device/mmi/posibrain/New()
brainmob = new(src)
brainmob.name = "[pick(fluff_names)]-[rand(100, 999)]"
picked_fluff_name = pick(fluff_names)
brainmob.name = "[picked_fluff_name]-[rand(100, 999)]"
brainmob.real_name = brainmob.name
brainmob.loc = src
brainmob.container = src
ping_ghosts("created", TRUE)
if(autoping)
ping_ghosts("created", TRUE)
..()
@@ -1,4 +1,4 @@
/mob/living/carbon/brain/say(message)
/mob/living/brain/say(message)
if(!(container && istype(container, /obj/item/device/mmi)))
return //No MMI, can't speak, bucko./N
else
@@ -9,15 +9,16 @@
message = Gibberish(message, (emp_damage*6))//scrambles the message, gets worse when emp_damage is higher
..()
/mob/living/carbon/brain/radio(message, message_mode, list/spans)
/mob/living/brain/radio(message, message_mode, list/spans)
if(message_mode && istype(container, /obj/item/device/mmi))
var/obj/item/device/mmi/R = container
if(R.radio)
R.radio.talk_into(src, message, , spans)
return ITALICS | REDUCE_RANGE
/mob/living/carbon/brain/lingcheck()
/mob/living/brain/lingcheck()
return 0
/mob/living/carbon/brain/treat_message(message)
/mob/living/brain/treat_message(message)
message = capitalize(message)
return message
@@ -4,35 +4,30 @@
/////////////////////////////////// EAR DAMAGE ////////////////////////////////////
/mob/living/carbon/brain/adjustEarDamage()
/mob/living/brain/adjustEarDamage()
return
/mob/living/carbon/brain/setEarDamage() // no ears to damage or heal
/mob/living/brain/setEarDamage() // no ears to damage or heal
return
/////////////////////////////////// EYE_BLIND ////////////////////////////////////
/mob/living/carbon/brain/blind_eyes() // no eyes to damage or heal
/mob/living/brain/blind_eyes() // no eyes to damage or heal
return
/mob/living/carbon/brain/adjust_blindness()
/mob/living/brain/adjust_blindness()
return
/mob/living/carbon/brain/set_blindness()
/mob/living/brain/set_blindness()
return
/////////////////////////////////// EYE_BLURRY ////////////////////////////////////
/mob/living/carbon/brain/blur_eyes()
/mob/living/brain/blur_eyes()
return
/mob/living/carbon/brain/adjust_blurriness()
/mob/living/brain/adjust_blurriness()
return
/mob/living/carbon/brain/set_blurriness()
/mob/living/brain/set_blurriness()
return
/////////////////////////////////// BLIND DISABILITY ////////////////////////////////////
/mob/living/carbon/brain/become_blind()
return
+13 -53
View File
@@ -7,10 +7,10 @@
name = "alien"
voice_name = "alien"
icon = 'icons/mob/alien.dmi'
gender = FEMALE
gender = FEMALE //All xenos are girls!!
dna = null
faction = list("alien")
ventcrawler = 2
ventcrawler = VENTCRAWLER_ALWAYS
languages_spoken = ALIEN
languages_understood = ALIEN
sight = SEE_MOBS
@@ -19,7 +19,7 @@
bubble_icon = "alien"
type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno
var/nightvision = 1
var/deathNotified = 0
devourable = 1
var/obj/item/weapon/card/id/wear_id = null // Fix for station bounced radios -- Skie
var/has_fine_manipulation = 0
@@ -38,35 +38,22 @@
verbs += /mob/living/proc/mob_sleep
verbs += /mob/living/proc/lay_down
internal_organs += new /obj/item/organ/brain/alien
internal_organs += new /obj/item/organ/alien/hivenode
internal_organs += new /obj/item/organ/tongue/alien
create_bodyparts() //initialize bodyparts
for(var/obj/item/organ/I in internal_organs)
I.Insert(src)
create_internal_organs()
AddAbility(new/obj/effect/proc_holder/alien/nightvisiontoggle(null))
..()
/mob/living/carbon/alien/create_internal_organs()
internal_organs += new /obj/item/organ/brain/alien
internal_organs += new /obj/item/organ/alien/hivenode
internal_organs += new /obj/item/organ/tongue/alien
..()
/mob/living/carbon/alien/assess_threat() // beepsky won't hunt aliums
return -10
/mob/living/carbon/alien/adjustToxLoss(amount)
return 0
/mob/living/carbon/alien/adjustFireLoss(amount) // Weak to Fire
if(amount > 0)
..(amount * 2)
else
..(amount)
return
/mob/living/carbon/alien/check_eye_prot()
return ..() + 2
/mob/living/carbon/alien/getToxLoss()
return 0
/mob/living/carbon/alien/handle_environment(datum/gas_mixture/environment)
if(!environment)
return
@@ -101,35 +88,6 @@
else
clear_alert("alien_fire")
/mob/living/carbon/alien/ex_act(severity, target)
..()
switch (severity)
if (1)
gib()
return
if (2)
adjustBruteLoss(60)
adjustFireLoss(60)
adjustEarDamage(30,120)
if(3)
adjustBruteLoss(30)
if (prob(50))
Paralyse(1)
adjustEarDamage(15,60)
updatehealth()
/mob/living/carbon/alien/handle_fire()//Aliens on fire code
if(..())
return
bodytemperature += BODYTEMP_HEATING_MAX //If you're on fire, you heat up!
return
/mob/living/carbon/alien/reagent_check(datum/reagent/R) //can metabolize all reagents
return 0
@@ -229,3 +187,5 @@ Des: Removes all infected images from the alien.
if(see_override)
see_invisible = see_override
/mob/living/carbon/alien/can_hold_items()
return has_fine_manipulation
@@ -1,3 +1,10 @@
/mob/living/carbon/alien/get_eye_protection()
return ..() + 2 //potential cyber implants + natural eye protection
/mob/living/carbon/alien/get_ear_protection()
return 2 //no ears
/mob/living/carbon/alien/hitby(atom/movable/AM, skipcatch, hitpush)
..(AM, skipcatch = 1, hitpush = 0)
@@ -7,11 +14,7 @@ As such, they can either help or harm other aliens. Help works like the human he
In all, this is a lot like the monkey code. /N
*/
/mob/living/carbon/alien/attack_alien(mob/living/carbon/alien/M)
if(!ticker || !ticker.mode)
M << "You cannot attack people before the game has started."
return
if (istype(loc, /turf) && istype(loc.loc, /area/start))
if(isturf(loc) && istype(loc.loc, /area/start))
M << "No attacking people at spawn, you jackass."
return
@@ -23,24 +26,22 @@ In all, this is a lot like the monkey code. /N
AdjustParalysis(-3)
AdjustStunned(-3)
AdjustWeakened(-3)
visible_message("<span class='notice'>[M.name] nuzzles [src] trying to wake it up!</span>")
visible_message("<span class='notice'>[M.name] nuzzles [src] trying to wake [p_them()] up!</span>")
if ("grab")
grabbedby(M)
else
if (health > 0)
M.do_attack_animation(src)
if(health > 0)
M.do_attack_animation(src, ATTACK_EFFECT_BITE)
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
var/damage = 1
visible_message("<span class='danger'>[M.name] bites [src]!</span>", \
"<span class='userdanger'>[M.name] bites [src]!</span>")
adjustBruteLoss(damage)
"<span class='userdanger'>[M.name] bites [src]!</span>", null, COMBAT_MESSAGE_RANGE)
adjustBruteLoss(1)
add_logs(M, src, "attacked")
updatehealth()
else
M << "<span class='warning'>[name] is too injured for that.</span>"
return
/mob/living/carbon/alien/attack_larva(mob/living/carbon/alien/larva/L)
@@ -56,8 +57,11 @@ In all, this is a lot like the monkey code. /N
help_shake_act(M)
if("grab")
grabbedby(M)
if ("harm", "disarm")
M.do_attack_animation(src)
if ("harm")
M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
return 1
if("disarm")
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
return 1
return 0
@@ -65,9 +69,8 @@ In all, this is a lot like the monkey code. /N
/mob/living/carbon/alien/attack_paw(mob/living/carbon/monkey/M)
if(..())
if (stat != DEAD)
adjustBruteLoss(rand(1, 3))
updatehealth()
return
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
apply_damage(rand(1, 3), BRUTE, affecting)
/mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M)
@@ -96,3 +99,28 @@ In all, this is a lot like the monkey code. /N
adjustBruteLoss(damage)
add_logs(M, src, "attacked")
updatehealth()
/mob/living/carbon/alien/ex_act(severity, target, origin)
if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
return
..()
switch (severity)
if (1)
gib()
return
if (2)
take_overall_damage(60, 60)
adjustEarDamage(30,120)
if(3)
take_overall_damage(30,0)
if(prob(50))
Paralyse(1)
adjustEarDamage(15,60)
/mob/living/carbon/alien/soundbang_act(intensity = 1, stun_pwr = 1, damage_pwr = 5, deafen_pwr = 15)
return 0
/mob/living/carbon/alien/acid_act(acidpwr, acid_volume)
return 0//aliens are immune to acid.
@@ -0,0 +1,21 @@
/mob/living/carbon/alien/getToxLoss()
return 0
/mob/living/carbon/alien/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE) //alien immune to tox damage
return FALSE
/mob/living/carbon/alien/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE) // Weak to Fire
if(amount > 0)
amount *= 2
. = ..()
//aliens are immune to stamina damage.
/mob/living/carbon/alien/adjustStaminaLoss(amount, updating_stamina = 1)
return
/mob/living/carbon/alien/setStaminaLoss(amount, updating_stamina = 1)
return
+7 -18
View File
@@ -1,25 +1,14 @@
/mob/living/carbon/alien/spawn_gibs()
xgibs(loc, viruses)
/mob/living/carbon/alien/spawn_gibs(with_bodyparts)
if(with_bodyparts)
new /obj/effect/gibspawner/xeno(loc,viruses)
else
new /obj/effect/gibspawner/xenobodypartless(loc,viruses)
/mob/living/carbon/alien/gib_animation()
PoolOrNew(/obj/effect/overlay/temp/gib_animation, list(loc, "gibbed-a"))
new /obj/effect/overlay/temp/gib_animation(loc, "gibbed-a")
/mob/living/carbon/alien/spawn_dust()
new /obj/effect/decal/remains/xeno(loc)
/mob/living/carbon/alien/dust_animation()
PoolOrNew(/obj/effect/overlay/temp/dust_animation, list(loc, "dust-a"))
/mob/living/carbon/alien/proc/deathNotice(var/area/AR, var/turf/T)
if(src.z == 2) //Admin fuckery can continue without giving false death rattles to aliens on station or elsewhere.
return
src.deathNotified = 1
T = get_turf(src)
var/mob/living/carbon/alien/A
for(A in world)
A << "<span class='userdanger'>[src.name] has died at [T.loc.name]! </span>"
/mob/living/carbon/alien/death(gibbed)
if(!deathNotified)
deathNotice()
..()
new /obj/effect/overlay/temp/dust_animation(loc, "dust-a")
@@ -0,0 +1,30 @@
/datum/emote/living/alien
mob_type_allowed_typecache = list(/mob/living/carbon/alien)
/datum/emote/living/alien/gnarl
key = "gnarl"
key_third_person = "gnarls"
message = "gnarls and shows its teeth..."
/datum/emote/living/alien/hiss
key = "hiss"
key_third_person = "hisses"
message_alien = "hisses."
message_larva = "hisses softly."
/datum/emote/living/alien/hiss/run_emote(mob/user, params)
. = ..()
if(. && isalienadult(user))
playsound(user.loc, "hiss", 40, 1, 1)
/datum/emote/living/alien/roar
key = "roar"
key_third_person = "roars"
message_alien = "roars"
message_larva = "sofly roars"
emote_type = EMOTE_AUDIBLE
/datum/emote/living/alien/roar/run_emote(mob/user, params)
. = ..()
if(. && isalienadult(user))
playsound(user.loc, 'sound/voice/hiss5.ogg', 40, 1, 1)
@@ -11,7 +11,6 @@ Doesn't work on other aliens/AI.*/
panel = "Alien"
var/plasma_cost = 0
var/check_turf = 0
var/has_action = 1
var/datum/action/spell_action/alien/action = null
var/action_icon = 'icons/mob/actions.dmi'
@@ -49,7 +48,7 @@ Doesn't work on other aliens/AI.*/
if(!silent)
user << "<span class='noticealien'>Not enough plasma stored.</span>"
return 0
if(check_turf && (!isturf(user.loc) || istype(user.loc, /turf/open/space)))
if(check_turf && (!isturf(user.loc) || isspaceturf(user.loc)))
if(!silent)
user << "<span class='noticealien'>Bad place for a garden!</span>"
return 0
@@ -64,7 +63,7 @@ Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien/plant/fire(mob/living/carbon/user)
if(locate(/obj/structure/alien/weeds/node) in get_turf(user))
src << "There's already a weed node here."
user << "There's already a weed node here."
return 0
user.visible_message("<span class='alertalien'>[user] has planted some alien weeds!</span>")
new/obj/structure/alien/weeds/node(user.loc)
@@ -123,14 +122,14 @@ Doesn't work on other aliens/AI.*/
if (get_dist(user,M) <= 1)
M.adjustPlasma(amount)
user.adjustPlasma(-amount)
M << "<span class='noticealien'>[user] has transfered [amount] plasma to you.</span>"
user << "<span class='noticealien'>You trasfer [amount] plasma to [M]</span>"
M << "<span class='noticealien'>[user] has transferred [amount] plasma to you.</span>"
user << "<span class='noticealien'>You transfer [amount] plasma to [M]</span>"
else
user << "<span class='noticealien'>You need to be closer!</span>"
return
/obj/effect/proc_holder/alien/acid
name = "Corrossive Acid"
name = "Corrosive Acid"
desc = "Drench an object in acid, destroying it over time."
plasma_cost = 200
action_icon_state = "alien_acid"
@@ -141,30 +140,16 @@ Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien/acid/on_lose(mob/living/carbon/user)
user.verbs.Remove(/mob/living/carbon/proc/corrosive_acid)
/obj/effect/proc_holder/alien/acid/proc/corrode(target,mob/living/carbon/user = usr)
/obj/effect/proc_holder/alien/acid/proc/corrode(atom/target,mob/living/carbon/user = usr)
if(target in oview(1,user))
// OBJ CHECK
if(isobj(target))
var/obj/I = target
if(I.unacidable) //So the aliens don't destroy energy fields/singularies/other aliens/etc with their acid.
user << "<span class='noticealien'>You cannot dissolve this object.</span>"
return 0
// TURF CHECK
else if(istype(target, /turf))
var/turf/T = target
// R WALL
if(istype(T, /turf/closed/wall/r_wall))
user << "<span class='noticealien'>You cannot dissolve this object.</span>"
return 0
// R FLOOR
if(istype(T, /turf/open/floor/engine))
user << "<span class='noticealien'>You cannot dissolve this object.</span>"
return 0
else// Not a type we can acid.
if(target.acid_act(200, 100))
user.visible_message("<span class='alertalien'>[user] vomits globs of vile stuff all over [target]. It begins to sizzle and melt under the bubbling mess of acid!</span>")
return 1
else
user << "<span class='noticealien'>You cannot dissolve this object.</span>"
return 0
new /obj/effect/acid(get_turf(target), target)
user.visible_message("<span class='alertalien'>[user] vomits globs of vile stuff all over [target]. It begins to sizzle and melt under the bubbling mess of acid!</span>")
return 1
else
src << "<span class='noticealien'>Target is too far away.</span>"
return 0
@@ -172,8 +157,10 @@ Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien/acid/fire(mob/living/carbon/alien/user)
var/O = input("Select what to dissolve:","Dissolve",null) as obj|turf in oview(1,user)
if(!O) return 0
return corrode(O,user)
if(!O || user.incapacitated())
return 0
else
return corrode(O,user)
/mob/living/carbon/proc/corrosive_acid(O as obj|turf in oview(1)) // right click menu verb ugh
set name = "Corrossive Acid"
@@ -191,39 +178,40 @@ Doesn't work on other aliens/AI.*/
name = "Spit Neurotoxin"
desc = "Spits neurotoxin at someone, paralyzing them for a short time."
action_icon_state = "alien_neurotoxin_0"
var/active = 0
active = FALSE
/obj/effect/proc_holder/alien/neurotoxin/fire(mob/living/carbon/user)
var/message
if(active)
user.ranged_ability = null
user << "<span class='notice'>You empty your neurotoxin gland.</span>"
active = 0
else if(user.ranged_ability && user.ranged_ability != src)
user << "<span class='warning'>You already have another aimed ability readied! Cancel it first."
return
message = "<span class='notice'>You empty your neurotoxin gland.</span>"
remove_ranged_ability(message)
else
user.ranged_ability = src
active = 1
user << "<span class='notice'>You prepare your neurotoxin gland. <B>Left-click to fire at a target!</B></span>"
message = "<span class='notice'>You prepare your neurotoxin gland. <B>Left-click to fire at a target!</B></span>"
add_ranged_ability(user, message, TRUE)
user.client.click_intercept = user.ranged_ability
/obj/effect/proc_holder/alien/neurotoxin/update_icon()
action.button_icon_state = "alien_neurotoxin_[active]"
action.UpdateButtonIcon()
/obj/effect/proc_holder/alien/neurotoxin/InterceptClickOn(mob/living/carbon/user, params, atom/target)
var/p_cost = 50
if(!iscarbon(user) || user.lying || user.stat)
/obj/effect/proc_holder/alien/neurotoxin/InterceptClickOn(mob/living/caller, params, atom/target)
if(..())
return
user.next_click = world.time + 6
user.face_atom(target)
var/p_cost = 50
if(!iscarbon(ranged_ability_user) || ranged_ability_user.lying || ranged_ability_user.stat)
remove_ranged_ability(ranged_ability_user)
return
var/mob/living/carbon/user = ranged_ability_user
if(user.getPlasma() < p_cost)
user << "<span class='warning'>You need at least [p_cost] plasma to spit.</span>"
remove_ranged_ability()
return
var/turf/T = user.loc
var/turf/U = get_step(user, user.dir) // Get the tile infront of the move, based on their direction
if(!isturf(U) || !isturf(T))
return 0
return FALSE
user.visible_message("<span class='danger'>[user] spits neurotoxin!", "<span class='alertalien'>You spit neurotoxin.</span>")
var/obj/item/projectile/bullet/neurotoxin/A = new /obj/item/projectile/bullet/neurotoxin(user.loc)
@@ -233,12 +221,25 @@ Doesn't work on other aliens/AI.*/
user.newtonian_move(get_dir(U, T))
user.adjustPlasma(-p_cost)
return 1
return TRUE
/obj/effect/proc_holder/alien/neurotoxin/on_lose(mob/living/carbon/user)
if(user.ranged_ability == src)
user.ranged_ability = null
/obj/effect/proc_holder/alien/neurotoxin/add_ranged_ability(mob/living/user, msg)
..()
if(isalienadult(user))
var/mob/living/carbon/alien/humanoid/A = user
A.drooling = 1
A.update_icons()
/obj/effect/proc_holder/alien/neurotoxin/remove_ranged_ability(mob/living/user, msg)
..()
if(isalienadult(user))
var/mob/living/carbon/alien/humanoid/A = user
A.drooling = 0
A.update_icons()
/obj/effect/proc_holder/alien/resin
name = "Secrete Resin"
@@ -308,7 +309,7 @@ Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien/sneak
name = "Sneak"
desc = "Blend into the shadows to stalk your prey."
var/active = 0
active = 0
action_icon_state = "alien_sneak"
@@ -3,15 +3,18 @@
caste = "d"
maxHealth = 125
health = 125
icon_state = "aliend_s"
icon_state = "aliend"
/mob/living/carbon/alien/humanoid/drone/New()
AddAbility(new/obj/effect/proc_holder/alien/evolve(null))
..()
/mob/living/carbon/alien/humanoid/drone/create_internal_organs()
internal_organs += new /obj/item/organ/alien/plasmavessel/large
internal_organs += new /obj/item/organ/alien/resinspinner
internal_organs += new /obj/item/organ/alien/acid
AddAbility(new/obj/effect/proc_holder/alien/evolve(null))
..()
/mob/living/carbon/alien/humanoid/drone/movement_delay()
@@ -36,7 +39,7 @@
if(!isturf(user.loc))
user << "<span class='notice'>You can't evolve here!</span>"
return 0
if(!alien_type_present(/mob/living/carbon/alien/humanoid/royal))
if(!get_alien_type(/mob/living/carbon/alien/humanoid/royal))
var/mob/living/carbon/alien/humanoid/royal/praetorian/new_xeno = new (user.loc)
user.alien_evolve(new_xeno)
return 1
@@ -3,10 +3,10 @@
caste = "h"
maxHealth = 125
health = 125
icon_state = "alienh_s"
icon_state = "alienh"
var/obj/screen/leap_icon = null
/mob/living/carbon/alien/humanoid/hunter/New()
/mob/living/carbon/alien/humanoid/hunter/create_internal_organs()
internal_organs += new /obj/item/organ/alien/plasmavessel/small
..()
@@ -45,17 +45,21 @@
if(leaping || stat || buckled || lying)
return
if(!has_gravity(src) || !has_gravity(A))
if(!has_gravity() || !A.has_gravity())
src << "<span class='alertalien'>It is unsafe to leap without gravity!</span>"
//It's also extremely buggy visually, so it's balance+bugfix
return
else //Maybe uses plasma in the future, although that wouldn't make any sense...
leaping = 1
weather_immunities += "lava"
update_icons()
throw_at(A,MAX_ALIEN_LEAP_DIST,1, spin=0, diagonals_first = 1)
leaping = 0
update_icons()
throw_at(A, MAX_ALIEN_LEAP_DIST, 1, spin=0, diagonals_first = 1, callback = CALLBACK(src, .leap_end))
/mob/living/carbon/alien/humanoid/hunter/proc/leap_end()
leaping = 0
weather_immunities -= "lava"
update_icons()
/mob/living/carbon/alien/humanoid/hunter/throw_impact(atom/A)
@@ -63,18 +67,20 @@
return ..()
if(A)
if(istype(A, /mob/living))
if(isliving(A))
var/mob/living/L = A
var/blocked = 0
if(ishuman(A))
var/mob/living/carbon/human/H = A
if(H.check_shields(90, "the [name]", src, attack_type = THROWN_PROJECTILE_ATTACK))
if(H.check_shields(0, "the [name]", src, attack_type = LEAP_ATTACK))
blocked = 1
if(!blocked)
L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>")
L.Weaken(5)
sleep(2)//Runtime prevention (infinite bump() calls on hulks)
step_towards(src,L)
else
Weaken(2, 1, 1)
toggle_leap(0)
pounce_cooldown = !pounce_cooldown
@@ -82,7 +88,7 @@
pounce_cooldown = !pounce_cooldown
else if(A.density && !A.CanPass(src))
visible_message("<span class ='danger'>[src] smashes into [A]!</span>", "<span class ='alertalien'>[src] smashes into [A]!</span>")
weakened = 2
Weaken(2, 1, 1)
if(leaping)
leaping = 0
@@ -11,14 +11,18 @@
real_name = name
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno(src))
AddAbility(new /obj/effect/proc_holder/alien/royal/praetorian/evolve())
..()
/mob/living/carbon/alien/humanoid/royal/praetorian/create_internal_organs()
internal_organs += new /obj/item/organ/alien/plasmavessel/large
internal_organs += new /obj/item/organ/alien/resinspinner
internal_organs += new /obj/item/organ/alien/acid
internal_organs += new /obj/item/organ/alien/neurotoxin
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno(src))
AddAbility(new /obj/effect/proc_holder/alien/royal/praetorian/evolve())
..()
/mob/living/carbon/alien/humanoid/royal/praetorian/movement_delay()
. = ..()
. += 1
@@ -38,7 +42,7 @@
if(node.recent_queen_death)
user << "<span class='danger'>You are still too burdened with guilt to evolve into a queen.</span>"
return 0
if(!alien_type_present(/mob/living/carbon/alien/humanoid/royal/queen))
if(!get_alien_type(/mob/living/carbon/alien/humanoid/royal/queen))
var/mob/living/carbon/alien/humanoid/royal/queen/new_xeno = new (user.loc)
user.alien_evolve(new_xeno)
if(new_xeno.client.prefs.unlock_content)
@@ -3,15 +3,19 @@
caste = "s"
maxHealth = 150
health = 150
icon_state = "aliens_s"
icon_state = "aliens"
/mob/living/carbon/alien/humanoid/sentinel/New()
internal_organs += new /obj/item/organ/alien/plasmavessel
internal_organs += new /obj/item/organ/alien/acid
internal_organs += new /obj/item/organ/alien/neurotoxin
AddAbility(new /obj/effect/proc_holder/alien/sneak)
..()
/mob/living/carbon/alien/humanoid/sentinel/create_internal_organs()
internal_organs += new /obj/item/organ/alien/plasmavessel
internal_organs += new /obj/item/organ/alien/acid
internal_organs += new /obj/item/organ/alien/neurotoxin
..()
/mob/living/carbon/alien/humanoid/sentinel/movement_delay()
. = ..()
@@ -1,24 +1,12 @@
/mob/living/carbon/alien/humanoid/death(gibbed)
if(stat == DEAD)
return
stat = DEAD
if(!deathNotified) //Did we message the other aliens that we died?
deathNotice() //If not, do so now. This proc will change the deathNotified var to 1 so it never happens again.
. = ..()
if(!gibbed)
playsound(loc, 'sound/voice/hiss6.ogg', 80, 1, 1)
visible_message("<span class='name'>[src]</span> lets out a waning guttural screech, green blood bubbling from its maw...")
update_canmove()
update_icons()
status_flags |= CANPUSH
if(fireloss >= (maxHealth/2))
spawn(10)
visible_message("<span class='warning'>[src] starts shaking...</span>")
spawn(30)
src.gib()
return ..()
update_canmove()
update_icons()
status_flags |= CANPUSH
//When the alien queen dies, all others must pay the price for letting her die.
/mob/living/carbon/alien/humanoid/royal/queen/death(gibbed)
@@ -32,20 +20,4 @@
if(istype(node)) // just in case someone would ever add a diffirent node to hivenode slot
node.queen_death()
return ..(gibbed)
/mob/living/carbon/alien/humanoid/gib()
visible_message("<span class='danger'>[src] explodes in a shower of acid blood and gibs!</span>")
for(var/mob/living/M in viewers(2, src))
if(ishuman(M))
M << "<span class='userdanger'>You're sprayed with acid blood!</span>"
M.adjustFireLoss(15)
M.reagents.add_reagent("xblood",5)
else if(ismonkey(M))
M << "<span class='userdanger'>You're sprayed with acid blood!</span>"
M.adjustFireLoss(15)
M.reagents.add_reagent("xblood",5)
else if(!isalien(M))
M << "<span class='userdanger'>You're sprayed with acid blood!</span>"
M.adjustFireLoss(15)
..()
return ..()
@@ -1,8 +1,10 @@
/mob/living/carbon/alien/humanoid
name = "alien"
icon_state = "alien_s"
icon_state = "alien"
pass_flags = PASSTABLE
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno = 5, /obj/item/stack/sheet/animalhide/xeno = 1)
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
limb_destroyer = 1
var/obj/item/r_store = null
var/obj/item/l_store = null
var/caste = ""
@@ -13,89 +15,35 @@
var/custom_pixel_x_offset = 0 //for admin fuckery.
var/custom_pixel_y_offset = 0
var/sneaking = 0 //For sneaky-sneaky mode and appropriate slowdown
var/drooling = 0 //For Neruotoxic spit overlays
bodyparts = list(/obj/item/bodypart/chest/alien, /obj/item/bodypart/head/alien, /obj/item/bodypart/l_arm/alien,
/obj/item/bodypart/r_arm/alien, /obj/item/bodypart/r_leg/alien, /obj/item/bodypart/l_leg/alien)
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/humanoid/New()
AddAbility(new/obj/effect/proc_holder/alien/regurgitate(null))
..()
/mob/living/carbon/alien/humanoid/movement_delay()
. = ..()
. += move_delay_add + config.alien_delay + sneaking //move_delay_add is used to slow aliens with stuns
/mob/living/carbon/alien/humanoid/emp_act(severity)
if(r_store) r_store.emp_act(severity)
if(l_store) l_store.emp_act(severity)
..()
/mob/living/carbon/alien/humanoid/attack_hulk(mob/living/carbon/human/user)
if(user.a_intent == "harm")
..(user, 1)
adjustBruteLoss(15)
var/hitverb = "punched"
if(mob_size < MOB_SIZE_LARGE)
Paralyse(1)
step_away(src,user,15)
sleep(1)
step_away(src,user,15)
hitverb = "slammed"
playsound(loc, "punch", 25, 1, -1)
visible_message("<span class='danger'>[user] has [hitverb] [src]!</span>", \
"<span class='userdanger'>[user] has [hitverb] [src]!</span>")
return 1
/mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M)
if(..())
switch(M.a_intent)
if ("harm")
var/damage = rand(1, 9)
if (prob(90))
playsound(loc, "punch", 25, 1, -1)
visible_message("<span class='danger'>[M] has punched [src]!</span>", \
"<span class='userdanger'>[M] has punched [src]!</span>")
if ((stat != DEAD) && (damage > 9 || prob(5)))//Regular humans have a very small chance of weakening an alien.
Paralyse(2)
visible_message("<span class='danger'>[M] has weakened [src]!</span>", \
"<span class='userdanger'>[M] has weakened [src]!</span>")
adjustBruteLoss(damage)
add_logs(M, src, "attacked")
updatehealth()
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to punch [src]!</span>")
if ("disarm")
if (!lying)
if (prob(5))
Paralyse(2)
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
add_logs(M, src, "pushed")
visible_message("<span class='danger'>[M] has pushed down [src]!</span>", \
"<span class='userdanger'>[M] has pushed down [src]!</span>")
else
if (prob(50))
drop_item()
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] has disarmed [src]!</span>", \
"<span class='userdanger'>[M] has disarmed [src]!</span>")
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to disarm [src]!</span>")
/mob/living/carbon/alien/humanoid/restrained(ignore_grab)
. = handcuffed
/mob/living/carbon/alien/humanoid/show_inv(mob/user)
user.set_machine(src)
var/dat = {"
var/list/dat = list()
dat += {"
<HR>
<B><FONT size=3>[name]</FONT></B>
<HR>
<BR><B>Left Hand:</B> <A href='?src=\ref[src];item=[slot_l_hand]'> [l_hand ? l_hand : "Nothing"]</A>
<BR><B>Right Hand:</B> <A href='?src=\ref[src];item=[slot_r_hand]'> [r_hand ? r_hand : "Nothing"]</A>
<BR><A href='?src=\ref[src];pouches=1'>Empty Pouches</A>"}
<HR>"}
for(var/i in 1 to held_items.len)
var/obj/item/I = get_item_for_held_index(i)
dat += "<BR><B>[get_held_index_name(i)]:</B><A href='?src=\ref[src];item=[slot_hands];hand_index=[i]'>[(I && !(I.flags & ABSTRACT)) ? I : "<font color=grey>Empty</font>"]</a>"
dat += "<BR><A href='?src=\ref[src];pouches=1'>Empty Pouches</A>"
if(handcuffed)
dat += "<BR><A href='?src=\ref[src];item=[slot_handcuffed]'>Handcuffed</A>"
@@ -106,7 +54,7 @@
<BR>
<BR><A href='?src=\ref[user];mach_close=mob\ref[src]'>Close</A>
"}
user << browse(dat, "window=mob\ref[src];size=325x500")
user << browse(dat.Join(), "window=mob\ref[src];size=325x500")
onclose(user, "mob\ref[src]")
@@ -118,8 +66,8 @@
visible_message("<span class='danger'>[usr] tries to empty [src]'s pouches.</span>", \
"<span class='userdanger'>[usr] tries to empty [src]'s pouches.</span>")
if(do_mob(usr, src, POCKET_STRIP_DELAY * 0.5))
unEquip(r_store)
unEquip(l_store)
dropItemToGround(r_store)
dropItemToGround(l_store)
/mob/living/carbon/alien/humanoid/cuff_resist(obj/item/I)
playsound(src, 'sound/voice/hiss5.ogg', 40, 1, 1) //Alien roars when starting to break free
@@ -147,39 +95,29 @@
else
return initial(pixel_x)
/mob/living/carbon/alien/humanoid/check_ear_prot()
return 1
/mob/living/carbon/alien/humanoid/get_permeability_protection()
return 0.8
/mob/living/carbon/alien/humanoid/alien_evolve(mob/living/carbon/alien/humanoid/new_xeno)
drop_l_hand()
drop_r_hand()
drop_all_held_items()
for(var/atom/movable/A in stomach_contents)
stomach_contents.Remove(A)
new_xeno.stomach_contents.Add(A)
A.loc = new_xeno
..()
//For alien evolution/promotion procs. Checks for
proc/alien_type_present(var/alienpath)
//For alien evolution/promotion/queen finder procs. Checks for an active alien of that type
/proc/get_alien_type(var/alienpath)
for(var/mob/living/carbon/alien/humanoid/A in living_mob_list)
if(!istype(A, alienpath))
continue
if(!A.key || A.stat == DEAD) //Only living aliens with a ckey are valid.
continue
return 1
return 0
return A
return FALSE
/mob/living/carbon/alien/humanoid/check_breath(datum/gas_mixture/breath)
if(breath && breath.total_moles() > 0 && !sneaking)
playsound(get_turf(src), pick('sound/voice/lowHiss2.ogg', 'sound/voice/lowHiss3.ogg', 'sound/voice/lowHiss4.ogg'), 50, 0, -5)
..()
/mob/living/carbon/alien/humanoid/grabbedby(mob/living/carbon/user, supress_message = 0)
if(user == src && pulling && grab_state >= GRAB_AGGRESSIVE && !pulling.anchored && iscarbon(pulling))
devour_mob(pulling, devour_time = 60)
else
..()
@@ -0,0 +1,68 @@
/mob/living/carbon/alien/humanoid/grabbedby(mob/living/carbon/user, supress_message = 0)
if(user == src && pulling && grab_state >= GRAB_AGGRESSIVE && !pulling.anchored && iscarbon(pulling))
devour_mob(pulling, devour_time = 60)
else
..()
/mob/living/carbon/alien/humanoid/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
if(user.a_intent == INTENT_HARM)
..(user, 1)
adjustBruteLoss(15)
var/hitverb = "punched"
if(mob_size < MOB_SIZE_LARGE)
step_away(src,user,15)
sleep(1)
step_away(src,user,15)
hitverb = "slammed"
playsound(loc, "punch", 25, 1, -1)
visible_message("<span class='danger'>[user] has [hitverb] [src]!</span>", \
"<span class='userdanger'>[user] has [hitverb] [src]!</span>", null, COMBAT_MESSAGE_RANGE)
return 1
/mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M)
if(..())
switch(M.a_intent)
if ("harm")
var/damage = rand(1, 9)
if (prob(90))
playsound(loc, "punch", 25, 1, -1)
visible_message("<span class='danger'>[M] has punched [src]!</span>", \
"<span class='userdanger'>[M] has punched [src]!</span>", null, COMBAT_MESSAGE_RANGE)
if ((stat != DEAD) && (damage > 9 || prob(5)))//Regular humans have a very small chance of weakening an alien.
Paralyse(2)
visible_message("<span class='danger'>[M] has weakened [src]!</span>", \
"<span class='userdanger'>[M] has weakened [src]!</span>")
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
apply_damage(damage, BRUTE, affecting)
add_logs(M, src, "attacked")
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='userdanger'>[M] has attempted to punch [src]!</span>", \
"<span class='userdanger'>[M] has attempted to punch [src]!</span>", null, COMBAT_MESSAGE_RANGE)
if ("disarm")
if (!lying)
if (prob(5))
Paralyse(2)
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
add_logs(M, src, "pushed")
visible_message("<span class='danger'>[M] has pushed down [src]!</span>", \
"<span class='userdanger'>[M] has pushed down [src]!</span>")
else
if (prob(50))
drop_item()
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] has disarmed [src]!</span>", \
"<span class='userdanger'>[M] has disarmed [src]!</span>", null, COMBAT_MESSAGE_RANGE)
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='userdanger'>[M] has attempted to disarm [src]!</span>",\
"<span class='userdanger'>[M] has attempted to disarm [src]!</span>", null, COMBAT_MESSAGE_RANGE)
/mob/living/carbon/alien/humanoid/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
if(!no_effect && !visual_effect_icon)
visual_effect_icon = ATTACK_EFFECT_CLAW
..()
@@ -1,4 +1,4 @@
/mob/living/carbon/alien/humanoid/unEquip(obj/item/I)
/mob/living/carbon/alien/humanoid/doUnEquip(obj/item/I)
. = ..()
if(!. || !I)
return
@@ -1,4 +1,4 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
/mob/living/carbon/alien/humanoid/proc/adjust_body_temperature(current, loc_temp, boost)
var/temperature = current
@@ -2,7 +2,7 @@
//Common stuffs for Praetorian and Queen
icon = 'icons/mob/alienqueen.dmi'
status_flags = 0
ventcrawler = 0 //pull over that ass too fat
ventcrawler = VENTCRAWLER_NONE //pull over that ass too fat
unique_name = 0
pixel_x = -16
bubble_icon = "alienroyal"
@@ -22,7 +22,27 @@
maxHealth = 400
health = 400
icon_state = "alienq"
var/datum/action/small_sprite/smallsprite = new/datum/action/small_sprite()
/datum/action/small_sprite
name = "Toggle Giant Sprite - Others will always see you as giant"
button_icon_state = "smallqueen"
background_icon_state = "bg_alien"
var/small = 0
/datum/action/small_sprite/Trigger()
..()
if(!small)
var/image/I = image(icon = 'icons/mob/alien.dmi' , icon_state = "alienq_running", loc = owner)
I.override = 1
I.pixel_x -= owner.pixel_x
I.pixel_y -= owner.pixel_y
owner.add_alt_appearance("smallqueen", I, list(owner))
small = 1
else
owner.remove_alt_appearance("smallqueen")
small = 0
/mob/living/carbon/alien/humanoid/royal/queen/New()
//there should only be one queen
@@ -37,18 +57,22 @@
real_name = src.name
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno(src))
AddAbility(new/obj/effect/proc_holder/alien/royal/queen/promote())
smallsprite.Grant(src)
..()
/mob/living/carbon/alien/humanoid/royal/queen/create_internal_organs()
internal_organs += new /obj/item/organ/alien/plasmavessel/large/queen
internal_organs += new /obj/item/organ/alien/resinspinner
internal_organs += new /obj/item/organ/alien/acid
internal_organs += new /obj/item/organ/alien/neurotoxin
internal_organs += new /obj/item/organ/alien/eggsac
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno(src))
AddAbility(new/obj/effect/proc_holder/alien/royal/queen/promote())
..()
/mob/living/carbon/alien/humanoid/royal/queen/movement_delay()
. = ..()
. += 5
. += 3
//Queen verbs
/obj/effect/proc_holder/alien/lay_egg
@@ -78,7 +102,7 @@
/obj/effect/proc_holder/alien/royal/queen/promote/fire(mob/living/carbon/alien/user)
var/obj/item/queenpromote/prom
if(alien_type_present(/mob/living/carbon/alien/humanoid/royal/praetorian/))
if(get_alien_type(/mob/living/carbon/alien/humanoid/royal/praetorian/))
user << "<span class='noticealien'>You already have a Praetorian!</span>"
return 0
else
@@ -99,14 +123,14 @@
name = "\improper royal parasite"
desc = "Inject this into one of your grown children to promote her to a Praetorian!"
icon_state = "alien_medal"
flags = ABSTRACT|NODROP
flags = ABSTRACT|NODROP|DROPDEL
icon = 'icons/mob/alien.dmi'
/obj/item/queenpromote/attack(mob/living/M, mob/living/carbon/alien/humanoid/user)
if(!isalienadult(M) || istype(M, /mob/living/carbon/alien/humanoid/royal))
user << "<span class='noticealien'>You may only use this with your adult, non-royal children!</span>"
return
if(alien_type_present(/mob/living/carbon/alien/humanoid/royal/praetorian/))
if(get_alien_type(/mob/living/carbon/alien/humanoid/royal/praetorian/))
user << "<span class='noticealien'>You already have a Praetorian!</span>"
return
@@ -161,4 +185,4 @@
desc = ""
icon_state = "alienq"
caste = "q"
update_icons()
update_icons()
@@ -20,8 +20,12 @@
icon_state = "alien[caste]_sleep"
else if(mob_size == MOB_SIZE_LARGE)
icon_state = "alien[caste]"
if(drooling)
add_overlay("alienspit_[caste]")
else
icon_state = "alien[caste]_s"
icon_state = "alien[caste]"
if(drooling)
add_overlay("alienspit")
if(leaping)
if(alt_icon == initial(alt_icon))
@@ -38,6 +42,8 @@
alt_icon = old_icon
pixel_x = get_standard_pixel_x_offset(lying)
pixel_y = get_standard_pixel_y_offset(lying)
update_inv_hands()
update_inv_handcuffed()
/mob/living/carbon/alien/humanoid/regenerate_icons()
if(!..())
@@ -50,28 +56,40 @@
..()
update_icons()
/mob/living/carbon/alien/humanoid/update_inv_handcuffed()
remove_overlay(HANDCUFF_LAYER)
var/cuff_icon = "aliencuff"
var/dmi_file = 'icons/mob/alien.dmi'
if(mob_size == MOB_SIZE_LARGE)
cuff_icon = "aliencuff_[caste]"
dmi_file = 'icons/mob/alienqueen.dmi'
if(handcuffed)
overlays_standing[HANDCUFF_LAYER] = image(dmi_file,icon_state= cuff_icon, layer =-HANDCUFF_LAYER)
apply_overlay(HANDCUFF_LAYER)
//Royals have bigger sprites, so inhand things must be handled differently.
/mob/living/carbon/alien/humanoid/royal/update_inv_r_hand()
/mob/living/carbon/alien/humanoid/royal/update_inv_hands()
..()
remove_overlay(R_HAND_LAYER)
if(r_hand)
var/itm_state = r_hand.item_state
if(!itm_state)
itm_state = r_hand.icon_state
remove_overlay(HANDS_LAYER)
var/list/hands = list()
var/image/I = image("icon" = alt_inhands_file , "icon_state"="[itm_state][caste]_r", "layer"=-R_HAND_LAYER)
overlays_standing[R_HAND_LAYER] = I
apply_overlay(R_HAND_LAYER)
/mob/living/carbon/alien/humanoid/royal/update_inv_l_hand()
..()
remove_overlay(L_HAND_LAYER)
var/obj/item/l_hand = get_item_for_held_index(1)
if(l_hand)
var/itm_state = l_hand.item_state
if(!itm_state)
itm_state = l_hand.icon_state
var/image/I = image("icon" = alt_inhands_file , "icon_state"="[itm_state][caste]_l", "layer"=-HANDS_LAYER)
hands += I
var/image/I = image("icon" = alt_inhands_file , "icon_state"="[itm_state][caste]_l", "layer"=-L_HAND_LAYER)
overlays_standing[L_HAND_LAYER] = I
apply_overlay(L_HAND_LAYER)
var/obj/item/r_hand = get_item_for_held_index(2)
if(r_hand)
var/itm_state = r_hand.item_state
if(!itm_state)
itm_state = r_hand.icon_state
var/image/I = image("icon" = alt_inhands_file , "icon_state"="[itm_state][caste]_r", "layer"=-HANDS_LAYER)
hands += I
overlays_standing[HANDS_LAYER] = hands
apply_overlay(HANDS_LAYER)
@@ -1,10 +1,22 @@
/mob/living/carbon/alien/larva/death(gibbed)
if(stat == DEAD)
return
stat = DEAD
icon_state = "larva_dead"
if(!gibbed)
visible_message("<span class='name'>[src]</span> lets out a waning high-pitched cry.")
. = ..()
return ..(gibbed)
update_icons()
/mob/living/carbon/alien/larva/spawn_gibs(with_bodyparts)
if(with_bodyparts)
new /obj/effect/gibspawner/larva(loc,viruses)
else
new /obj/effect/gibspawner/larvabodypartless(loc,viruses)
/mob/living/carbon/alien/larva/gib_animation()
new /obj/effect/overlay/temp/gib_animation(loc, "gibbed-l")
/mob/living/carbon/alien/larva/spawn_dust()
new /obj/effect/decal/remains/xeno(loc)
/mob/living/carbon/alien/larva/dust_animation()
new /obj/effect/overlay/temp/dust_animation(loc, "dust-l")
@@ -1,3 +1,3 @@
//can't unequip since it can't equip anything
/mob/living/carbon/alien/larva/unEquip(obj/item/W)
/mob/living/carbon/alien/larva/doUnEquip(obj/item/W)
return
@@ -14,16 +14,20 @@
var/time_of_birth
rotate_on_lying = 0
bodyparts = list(/obj/item/bodypart/chest/larva, /obj/item/bodypart/head/larva)
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/larva/New()
regenerate_icons()
internal_organs += new /obj/item/organ/alien/plasmavessel/small/tiny
AddAbility(new/obj/effect/proc_holder/alien/hide(null))
AddAbility(new/obj/effect/proc_holder/alien/larva_evolve(null))
..()
/mob/living/carbon/alien/larva/create_internal_organs()
internal_organs += new /obj/item/organ/alien/plasmavessel/small/tiny
..()
//This needs to be fixed
/mob/living/carbon/alien/larva/Stat()
..()
@@ -39,37 +43,6 @@
/mob/living/carbon/alien/larva/attack_ui(slot_id)
return
/mob/living/carbon/alien/larva/attack_hulk(mob/living/carbon/human/user)
if(user.a_intent == "harm")
..(user, 1)
adjustBruteLoss(5 + rand(1,9))
Paralyse(1)
spawn()
step_away(src,user,15)
sleep(1)
step_away(src,user,15)
return 1
/mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M)
if(..())
var/damage = rand(1, 9)
if (prob(90))
playsound(loc, "punch", 25, 1, -1)
add_logs(M, src, "attacked")
visible_message("<span class='danger'>[M] has kicked [src]!</span>", \
"<span class='userdanger'>[M] has kicked [src]!</span>")
if ((stat != DEAD) && (damage > 4.9))
Paralyse(rand(5,10))
adjustBruteLoss(damage)
updatehealth()
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to kick [src]!</span>", \
"<span class='userdanger'>[M] has attempted to kick [src]!</span>")
return
/mob/living/carbon/alien/larva/restrained(ignore_grab)
. = 0
@@ -0,0 +1,31 @@
/mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M)
if(..())
var/damage = rand(1, 9)
if (prob(90))
playsound(loc, "punch", 25, 1, -1)
add_logs(M, src, "attacked")
visible_message("<span class='danger'>[M] has kicked [src]!</span>", \
"<span class='userdanger'>[M] has kicked [src]!</span>", null, COMBAT_MESSAGE_RANGE)
if ((stat != DEAD) && (damage > 4.9))
Paralyse(rand(5,10))
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
apply_damage(damage, BRUTE, affecting)
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to kick [src]!</span>", \
"<span class='userdanger'>[M] has attempted to kick [src]!</span>", null, COMBAT_MESSAGE_RANGE)
/mob/living/carbon/alien/larva/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
if(user.a_intent == INTENT_HARM)
..(user, 1)
adjustBruteLoss(5 + rand(1,9))
new /datum/forced_movement(src, get_step_away(user,src, 30), 1)
return 1
/mob/living/carbon/alien/larva/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
if(!no_effect && !visual_effect_icon)
visual_effect_icon = ATTACK_EFFECT_BITE
..()
@@ -1,4 +1,4 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
/mob/living/carbon/alien/larva/Life()
set invisibility = 0
@@ -6,7 +6,7 @@
if (notransform)
return
if(..())
if(..()) //not dead
// GROW!
if(amount_grown < max_grown)
amount_grown++
@@ -20,7 +20,7 @@
if(health<= -maxHealth || !getorgan(/obj/item/organ/brain))
death()
return
if(paralysis || sleeping || getOxyLoss() > 50 || (status_flags & FAKEDEATH) || health <= config.health_threshold_crit)
if(paralysis || sleeping || getOxyLoss() > 50 || (status_flags & FAKEDEATH) || health <= HEALTH_THRESHOLD_CRIT)
if(stat == CONSCIOUS)
stat = UNCONSCIOUS
blind_eyes(1)
@@ -1,6 +1,6 @@
/obj/effect/proc_holder/alien/hide
name = "Hide"
desc = "Allows to hide beneath tables or certain items. Toggled on or off."
desc = "Allows aliens to hide beneath tables or certain items. Toggled on or off."
plasma_cost = 0
action_icon_state = "alien_hide"
@@ -15,14 +15,14 @@
"<span class='noticealien'>You are now hiding.</span>")
else
user.layer = MOB_LAYER
user.visible_message("[user.] slowly peaks up from the ground...", \
user.visible_message("[user.] slowly peeks up from the ground...", \
"<span class='noticealien'>You stop hiding.</span>")
return 1
/obj/effect/proc_holder/alien/larva_evolve
name = "Evolve"
desc = "Evolve into a fully grown Alien."
desc = "Evolve into a higher alien caste."
plasma_cost = 0
action_icon_state = "alien_evolve_larva"
@@ -38,9 +38,9 @@
if(L.amount_grown >= L.max_grown) //TODO ~Carn
L << "<span class='name'>You are growing into a beautiful alien! It is time to choose a caste.</span>"
L << "<span class='info'>There are three to choose from:"
L << "<span class='name'>Hunters</span> <span class='info'>are the most agile caste tasked with hunting for hosts. They are faster than a human and can even pounce, but are not much tougher than a drone.</span>"
L << "<span class='name'>Hunters</span> <span class='info'>are the most agile caste, tasked with hunting for hosts. They are faster than a human and can even pounce, but are not much tougher than a drone.</span>"
L << "<span class='name'>Sentinels</span> <span class='info'>are tasked with protecting the hive. With their ranged spit, invisibility, and high health, they make formidable guardians and acceptable secondhand hunters.</span>"
L << "<span class='name'>Drones</span> <span class='info'>are the weakest and slowest of the castes, but can grow into the queen if there is none, and are vital to maintaining a hive with their resin secretion abilities.</span>"
L << "<span class='name'>Drones</span> <span class='info'>are the weakest and slowest of the castes, but can grow into a praetorian and then queen if no queen exists, and are vital to maintaining a hive with their resin secretion abilities.</span>"
var/alien_caste = alert(L, "Please choose which alien caste you shall belong to.",,"Hunter","Sentinel","Drone")
if(user.incapacitated()) //something happened to us while we were choosing.
@@ -5,7 +5,7 @@
/mob/living/carbon/alien/larva/update_icons()
var/state = 0
if(amount_grown > 150)
if(amount_grown > 80)
state = 2
else if(amount_grown > 50)
state = 1
@@ -1,3 +1,6 @@
/mob/living/carbon/alien/Life()
findQueen()
return..()
/mob/living/carbon/alien/check_breath(datum/gas_mixture/breath)
if(status_flags & GODMODE)
@@ -42,4 +45,10 @@
move_delay_add = max(0, move_delay_add - rand(1, 2))
/mob/living/carbon/alien/handle_changeling()
return
/mob/living/carbon/alien/handle_fire()//Aliens on fire code
if(..())
return
bodytemperature += BODYTEMP_HEATING_MAX //If you're on fire, you heat up!
return
@@ -31,7 +31,7 @@
name = "plasma vessel"
icon_state = "plasma"
origin_tech = "biotech=5;plasmatech=4"
w_class = 3
w_class = WEIGHT_CLASS_NORMAL
zone = "chest"
slot = "plasmavessel"
alien_powers = list(/obj/effect/proc_holder/alien/plant, /obj/effect/proc_holder/alien/transfer)
@@ -49,7 +49,7 @@
/obj/item/organ/alien/plasmavessel/large
name = "large plasma vessel"
icon_state = "plasma_large"
w_class = 4
w_class = WEIGHT_CLASS_BULKY
storedPlasma = 200
max_plasma = 500
plasma_rate = 15
@@ -61,7 +61,7 @@
/obj/item/organ/alien/plasmavessel/small
name = "small plasma vessel"
icon_state = "plasma_small"
w_class = 2
w_class = WEIGHT_CLASS_SMALL
storedPlasma = 100
max_plasma = 150
plasma_rate = 5
@@ -69,7 +69,7 @@
/obj/item/organ/alien/plasmavessel/small/tiny
name = "tiny plasma vessel"
icon_state = "plasma_tiny"
w_class = 1
w_class = WEIGHT_CLASS_TINY
max_plasma = 100
alien_powers = list(/obj/effect/proc_holder/alien/transfer)
@@ -107,7 +107,7 @@
zone = "head"
slot = "hivenode"
origin_tech = "biotech=5;magnets=4;bluespace=3"
w_class = 1
w_class = WEIGHT_CLASS_TINY
var/recent_queen_death = 0 //Indicates if the queen died recently, aliens are heavily weakened while this is active.
alien_powers = list(/obj/effect/proc_holder/alien/whisper)
@@ -182,6 +182,6 @@
icon_state = "eggsac"
zone = "groin"
slot = "eggsac"
w_class = 4
w_class = WEIGHT_CLASS_BULKY
origin_tech = "biotech=6"
alien_powers = list(/obj/effect/proc_holder/alien/lay_egg)
+28 -1
View File
@@ -4,4 +4,31 @@
hud_used.alien_plasma_display.maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='magenta'>[round(getPlasma())]</font></div>"
/mob/living/carbon/alien/larva/updatePlasmaDisplay()
return
return
/mob/living/carbon/alien/proc/findQueen()
if(hud_used)
hud_used.alien_queen_finder.cut_overlays()
var/mob/queen = get_alien_type(/mob/living/carbon/alien/humanoid/royal/queen)
if(!queen)
return
var/turf/Q = get_turf(queen)
var/turf/A = get_turf(src)
if(Q.z != A.z) //The queen is on a different Z level, we cannot sense that far.
return
var/Qdir = get_dir(src, Q)
var/Qdist = get_dist(src, Q)
image(icon,loc,icon_state,layer,dir)
var/finder_icon = "finder_center" //Overlay showed when adjacent to or on top of the queen!
switch(Qdist)
if(2 to 7)
finder_icon = "finder_near"
if(8 to 20)
finder_icon = "finder_med"
if(21 to INFINITY)
finder_icon = "finder_far"
var/image/finder_eye = image('icons/mob/screen_alien.dmi', icon_state = finder_icon, dir = Qdir)
hud_used.alien_queen_finder.add_overlay(finder_eye)
/mob/living/carbon/alien/humanoid/royal/queen/findQueen()
return //Queen already knows where she is. Hopefully.
@@ -41,7 +41,7 @@ var/const/ALIEN_AFK_BRACKET = 450 // 45 seconds
if(prob(4))
owner << "<span class='danger'>Your muscles ache.</span>"
if(prob(20))
owner.take_organ_damage(1)
owner.take_bodypart_damage(1)
if(prob(4))
owner << "<span class='danger'>Your stomach hurts.</span>"
if(prob(20))
@@ -99,7 +99,7 @@ var/const/ALIEN_AFK_BRACKET = 450 // 45 seconds
new_xeno.notransform = 0
new_xeno.invisibility = 0
if(gib_on_success)
owner.gib()
owner.gib(TRUE)
else
owner.adjustBruteLoss(40)
owner.overlays -= overlay
@@ -1,4 +1,4 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
//TODO: Make these simple_animals
@@ -14,7 +14,7 @@ var/const/MAX_ACTIVE_TIME = 400
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
w_class = WEIGHT_CLASS_TINY //note: can be picked up by aliens unlike most other items of w_class below 4
flags = MASKINTERNALS
throw_range = 5
tint = 3
@@ -23,8 +23,8 @@ var/const/MAX_ACTIVE_TIME = 400
var/stat = CONSCIOUS //UNCONSCIOUS is the idle state in this case
var/sterile = 0
var/real = 1 //0 for the toy, 1 for real. Sure I could istype, but fuck that.
var/sterile = FALSE
var/real = TRUE //0 for the toy, 1 for real. Sure I could istype, but fuck that.
var/strength = 5
var/attached = 0
@@ -33,6 +33,16 @@ var/const/MAX_ACTIVE_TIME = 400
name = "Lamarr"
sterile = 1
/obj/item/clothing/mask/facehugger/dead
icon_state = "facehugger_dead"
item_state = "facehugger_inactive"
stat = DEAD
/obj/item/clothing/mask/facehugger/impregnated
icon_state = "facehugger_impregnated"
item_state = "facehugger_impregnated"
stat = DEAD
/obj/item/clothing/mask/facehugger/attack_alien(mob/user) //can be picked up by aliens
attack_hand(user)
return
@@ -45,8 +55,8 @@ var/const/MAX_ACTIVE_TIME = 400
/obj/item/clothing/mask/facehugger/attack(mob/living/M, mob/user)
..()
user.unEquip(src)
Attach(M)
if(user.temporarilyRemoveItemFromInventory(src))
Attach(M)
/obj/item/clothing/mask/facehugger/examine(mob/user)
..()
@@ -68,7 +78,6 @@ var/const/MAX_ACTIVE_TIME = 400
/obj/item/clothing/mask/facehugger/bullet_act(obj/item/projectile/P)
if(P.damage)
Die()
return
/obj/item/clothing/mask/facehugger/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > 300)
@@ -92,7 +101,7 @@ var/const/MAX_ACTIVE_TIME = 400
return Attach(AM)
return 0
/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed, mob/thrower, spin)
/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback)
if(!..())
return
if(stat == CONSCIOUS)
@@ -107,62 +116,82 @@ var/const/MAX_ACTIVE_TIME = 400
icon_state = "[initial(icon_state)]"
Attach(hit_atom)
/obj/item/clothing/mask/facehugger/proc/Attach(mob/living/M)
if(!isliving(M))
return 0
if((!iscorgi(M) && !iscarbon(M)) || isalien(M))
return 0
if(attached)
return 0
else
attached++
spawn(MAX_IMPREGNATION_TIME)
attached = 0
if(M.getorgan(/obj/item/organ/alien/hivenode))
return 0
if(M.getorgan(/obj/item/organ/body_egg/alien_embryo))
return 0
/obj/item/clothing/mask/facehugger/proc/valid_to_attach(mob/living/M)
// valid targets: corgis, carbons except aliens and devils
// facehugger state early exit checks
if(stat != CONSCIOUS)
return 0
if(!sterile) M.take_organ_damage(strength,0) //done here so that even borgs and humans in helmets take damage
return FALSE
if(attached)
return FALSE
if(!iscorgi(M) && !iscarbon(M))
return FALSE
if(iscarbon(M))
// disallowed carbons
if(isalien(M) || isdevil(M))
return FALSE
var/mob/living/carbon/target = M
// gotta have a head to be implanted (no changelings or sentient plants)
if(!target.get_bodypart("head"))
return FALSE
if(target.getorgan(/obj/item/organ/alien/hivenode) || target.getorgan(/obj/item/organ/body_egg/alien_embryo))
return FALSE
// carbon, has head, not alien or devil, has no hivenode or embryo: valid
return TRUE
else if(iscorgi(M))
// corgi: valid
return TRUE
/obj/item/clothing/mask/facehugger/proc/Attach(mob/living/M)
if(!valid_to_attach(M))
return FALSE
// passed initial checks - time to leap!
M.visible_message("<span class='danger'>[src] leaps at [M]'s face!</span>", \
"<span class='userdanger'>[src] leaps at [M]'s face!</span>")
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.is_mouth_covered(head_only = 1))
H.visible_message("<span class='danger'>[src] smashes against [H]'s [H.head]!</span>", \
"<span class='userdanger'>[src] smashes against [H]'s [H.head]!</span>")
Die()
return 0
"<span class='userdanger'>[src] leaps at [M]'s face!</span>")
// probiscis-blocker handling
if(iscarbon(M))
var/mob/living/carbon/target = M
if(target.wear_mask)
if(prob(20))
return 0
var/obj/item/clothing/W = target.wear_mask
if(W.flags & NODROP)
return 0
target.unEquip(W)
target.visible_message("<span class='danger'>[src] tears [W] off of [target]'s face!</span>", \
return FALSE
if(!istype(W,/obj/item/clothing/mask/facehugger))
target.dropItemToGround(W)
target.visible_message("<span class='danger'>[src] tears [W] off of [target]'s face!</span>", \
"<span class='userdanger'>[src] tears [W] off of [target]'s face!</span>")
src.loc = target
target.equip_to_slot(src, slot_wear_mask,,0)
if(!sterile)
M.Paralyse(MAX_IMPREGNATION_TIME/6) //something like 25 ticks = 20 seconds with the default settings
else if (iscorgi(M))
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.is_mouth_covered(head_only = 1))
H.visible_message("<span class='danger'>[src] smashes against [H]'s [H.head]!</span>", \
"<span class='userdanger'>[src] smashes against [H]'s [H.head]!</span>")
Die()
return FALSE
forceMove(target)
target.equip_to_slot_if_possible(src, slot_wear_mask, 0, 1, 1)
// early returns and validity checks done: attach.
attached++
//ensure we detach once we no longer need to be attached
spawn(MAX_IMPREGNATION_TIME)
attached = 0
if (iscorgi(M))
var/mob/living/simple_animal/pet/dog/corgi/C = M
loc = C
C.facehugger = src
C.regenerate_icons()
if(!sterile)
M.take_bodypart_damage(strength,0) //done here so that humans in helmets take damage
M.Paralyse(MAX_IMPREGNATION_TIME/6) //something like 25 ticks = 20 seconds with the default settings
GoIdle() //so it doesn't jump the people that tear it off
spawn(rand(MIN_IMPREGNATION_TIME,MAX_IMPREGNATION_TIME))
Impregnate(M)
return 1
return TRUE // time for a smoke
/obj/item/clothing/mask/facehugger/proc/Impregnate(mob/living/target)
if(!target || target.stat == DEAD) //was taken off or something
@@ -182,7 +211,7 @@ var/const/MAX_ACTIVE_TIME = 400
icon_state = "[initial(icon_state)]_impregnated"
var/obj/item/bodypart/chest/LC = target.get_bodypart("chest")
if((!LC || LC.status != ORGAN_ROBOTIC) && !target.getorgan(/obj/item/organ/body_egg/alien_embryo))
if((!LC || LC.status != BODYPART_ROBOTIC) && !target.getorgan(/obj/item/organ/body_egg/alien_embryo))
new /obj/item/organ/body_egg/alien_embryo(target)
if(iscorgi(target))
@@ -0,0 +1,11 @@
/mob/living/carbon/alien/update_damage_overlays() //aliens don't have damage overlays.
return
/mob/living/carbon/alien/update_body() // we don't use the bodyparts or body layers for aliens.
return
/mob/living/carbon/alien/update_body_parts()//we don't use the bodyparts layer for aliens.
return
@@ -1,63 +0,0 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
/mob/living/carbon/brain
languages_spoken = HUMAN
languages_understood = HUMAN
var/obj/item/device/mmi/container = null
var/timeofhostdeath = 0
var/emp_damage = 0//Handles a type of MMI damage
has_limbs = 0
stat = DEAD //we start dead by default
see_invisible = SEE_INVISIBLE_MINIMUM
/mob/living/carbon/brain/New(loc)
..()
if(isturf(loc)) //not spawned in an MMI or brain organ (most likely adminspawned)
var/obj/item/organ/brain/OB = new(loc) //we create a new brain organ for it.
src.loc = OB
OB.brainmob = src
/mob/living/carbon/brain/Destroy()
if(key) //If there is a mob connected to this thing. Have to check key twice to avoid false death reporting.
if(stat!=DEAD) //If not dead.
death(1) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA
ghostize() //Ghostize checks for key so nothing else is necessary.
container = null
return ..()
/mob/living/carbon/brain/update_canmove()
if(in_contents_of(/obj/mecha))
canmove = 1
else
canmove = 0
return canmove
/mob/living/carbon/brain/toggle_throw_mode()
return
/mob/living/carbon/brain/ex_act() //you cant blow up brainmobs because it makes transfer_to() freak out when borgs blow up.
return
/mob/living/carbon/brain/blob_act(obj/effect/blob/B)
return
/mob/living/carbon/brain/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default
return
/mob/living/carbon/brain/check_ear_prot()
return 1
/mob/living/carbon/brain/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
return // no eyes, no flashing
/mob/living/carbon/brain/update_damage_hud()
return //no red circles for brain
/mob/living/carbon/brain/can_be_revived()
. = 1
if(!container || health <= config.health_threshold_dead)
return 0
/mob/living/carbon/brain/update_sight()
return
@@ -1,71 +0,0 @@
/mob/living/carbon/brain/emote(act,m_type=1,message = null)
if(!(container && istype(container, /obj/item/device/mmi)))//No MMI, no emotes
return
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
act = copytext(act, 1, t1)
if(src.stat == DEAD)
return
switch(act)
if ("alarm")
src << "You sound an alarm."
message = "<B>[src]</B> sounds an alarm."
m_type = 2
if ("alert")
src << "You let out a distressed noise."
message = "<B>[src]</B> lets out a distressed noise."
m_type = 2
if ("beep","beeps")
src << "You beep."
message = "<B>[src]</B> beeps."
m_type = 2
if ("blink","blinks")
message = "<B>[src]</B> blinks."
m_type = 1
if ("boop","boops")
src << "You boop."
message = "<B>[src]</B> boops."
m_type = 2
if ("flash")
message = "The lights on <B>[src]</B> flash quickly."
m_type = 1
if ("notice")
src << "You play a loud tone."
message = "<B>[src]</B> plays a loud tone."
m_type = 2
if ("whistle","whistles")
src << "You whistle."
message = "<B>[src]</B> whistles."
m_type = 2
if ("help")
src << "Help for MMI emotes. You can use these emotes with say \"*emote\":\nalarm, alert, beep, blink, boop, flash, notice, whistle"
else
src << "<span class='notice'>Unusable emote '[act]'. Say *help for a list.</span>"
return
if (message)
log_emote("[name]/[key] : [message]")
for(var/mob/M in dead_mob_list)
if (!M.client || istype(M, /mob/new_player))
continue //skip monkeys, leavers, and new_players
if(M.stat == DEAD && (M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTSIGHT)) && !(M in viewers(src,null)))
M.show_message(message)
if (m_type & 1)
visible_message(message)
else if (m_type & 2)
audible_message(message)
+163 -172
View File
@@ -3,15 +3,18 @@
/mob/living/carbon/New()
create_reagents(1000)
update_body_parts() //to update the carbon's new bodyparts appearance
..()
/mob/living/carbon/Destroy()
for(var/atom/movable/guts in internal_organs)
for(var/guts in internal_organs)
qdel(guts)
for(var/atom/movable/food in stomach_contents)
qdel(food)
for(var/BP in bodyparts)
qdel(BP)
for(var/imp in implants)
qdel(imp)
bodyparts = list()
remove_from_all_data_huds()
if(dna)
@@ -25,19 +28,12 @@
audible_message("<span class='warning'>You hear something rumbling inside [src]'s stomach...</span>", \
"<span class='warning'>You hear something rumbling.</span>", 4,\
"<span class='userdanger'>Something is rumbling inside your stomach!</span>")
var/obj/item/I = user.get_active_hand()
var/obj/item/I = user.get_active_held_item()
if(I && I.force)
var/d = rand(round(I.force / 4), I.force)
if(istype(src, /mob/living/carbon/human))
var/mob/living/carbon/human/H = src
var/organ = H.get_bodypart("chest")
if (istype(organ, /obj/item/bodypart))
var/obj/item/bodypart/temp = organ
if(temp.take_damage(d, 0))
H.update_damage_overlays(0)
H.updatehealth()
else
src.take_organ_damage(d)
var/obj/item/bodypart/BP = get_bodypart("chest")
if(BP.receive_damage(d, 0))
update_damage_overlays()
visible_message("<span class='danger'>[user] attacks [src]'s stomach wall with the [I.name]!</span>", \
"<span class='userdanger'>[user] attacks your stomach wall with the [I.name]!</span>")
playsound(user.loc, 'sound/effects/attackblob.ogg', 50, 1)
@@ -49,140 +45,67 @@
src.gib()
/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, override = 0, tesla_shock = 0)
shock_damage *= siemens_coeff
if(dna && dna.species)
shock_damage *= dna.species.siemens_coeff
if(shock_damage<1 && !override)
return 0
if(reagents.has_reagent("teslium"))
shock_damage *= 1.5 //If the mob has teslium in their body, shocks are 50% more damaging!
take_overall_damage(0,shock_damage)
//src.adjustFireLoss(shock_damage)
//src.updatehealth()
visible_message(
"<span class='danger'>[src] was shocked by \the [source]!</span>", \
"<span class='userdanger'>You feel a powerful shock coursing through your body!</span>", \
"<span class='italics'>You hear a heavy electrical crack.</span>" \
)
jitteriness += 1000 //High numbers for violent convulsions
do_jitter_animation(jitteriness)
stuttering += 2
if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5))
Stun(2)
spawn(20)
jitteriness = max(jitteriness - 990, 10) //Still jittery, but vastly less
if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5))
Stun(3)
Weaken(3)
if(override)
return override
else
return shock_damage
/mob/living/carbon/swap_hand(held_index)
if(!held_index)
held_index = (active_hand_index % held_items.len)+1
/mob/living/carbon/swap_hand()
var/obj/item/item_in_hand = src.get_active_hand()
var/obj/item/item_in_hand = src.get_active_held_item()
if(item_in_hand) //this segment checks if the item in your hand is twohanded.
if(istype(item_in_hand,/obj/item/weapon/twohanded))
if(item_in_hand:wielded == 1)
usr << "<span class='warning'>Your other hand is too busy holding the [item_in_hand.name]</span>"
return
src.hand = !( src.hand )
if(hud_used && hud_used.inv_slots[slot_l_hand] && hud_used.inv_slots[slot_r_hand])
var/oindex = active_hand_index
active_hand_index = held_index
if(hud_used)
var/obj/screen/inventory/hand/H
H = hud_used.inv_slots[slot_l_hand]
H.update_icon()
H = hud_used.inv_slots[slot_r_hand]
H.update_icon()
/*if (!( src.hand ))
src.hands.setDir(NORTH)
else
src.hands.setDir(SOUTH)*/
return
H = hud_used.hand_slots["[oindex]"]
if(H)
H.update_icon()
H = hud_used.hand_slots["[held_index]"]
if(H)
H.update_icon()
/mob/living/carbon/activate_hand(selhand) //0 or "r" or "right" for right hand; 1 or "l" or "left" for left hand.
/mob/living/carbon/activate_hand(selhand) //l/r OR 1-held_items.len
if(!selhand)
selhand = (active_hand_index % held_items.len)+1
if(istext(selhand))
selhand = lowertext(selhand)
if(selhand == "right" || selhand == "r")
selhand = 0
selhand = 2
if(selhand == "left" || selhand == "l")
selhand = 1
if(selhand != src.hand)
swap_hand()
if(selhand != active_hand_index)
swap_hand(selhand)
else
mode() // Activate held item
/mob/living/carbon/proc/help_shake_act(mob/living/carbon/M)
if(on_fire)
M << "<span class='warning'>You can't put them out with just your bare hands!"
return
/mob/living/carbon/attackby(obj/item/I, mob/user, params)
if(lying && surgeries.len)
if(user != src && user.a_intent == INTENT_HELP)
for(var/datum/surgery/S in surgeries)
if(S.next_step(user))
return 1
return ..()
if(health >= 0 && !(status_flags & FAKEDEATH))
if(lying)
M.visible_message("<span class='notice'>[M] shakes [src] trying to get them up!</span>", \
"<span class='notice'>You shake [src] trying to get them up!</span>")
else
M.visible_message("<span class='notice'>[M] hugs [src] to make them feel better!</span>", \
"<span class='notice'>You hug [src] to make them feel better!</span>")
AdjustSleeping(-5)
AdjustParalysis(-3)
AdjustStunned(-3)
AdjustWeakened(-3)
if(resting)
resting = 0
update_canmove()
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
/mob/living/carbon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
/mob/living/carbon/throw_impact(atom/hit_atom)
. = ..()
var/damage = intensity - check_eye_prot()
if(.) // we've been flashed
if(visual)
if(hit_atom.density && isturf(hit_atom))
Weaken(1)
take_bodypart_damage(10)
if(iscarbon(hit_atom) && hit_atom != src)
var/mob/living/carbon/victim = hit_atom
if(victim.movement_type & FLYING)
return
if(weakeyes)
Stun(2)
if (damage == 1)
src << "<span class='warning'>Your eyes sting a little.</span>"
if(prob(40))
adjust_eye_damage(1)
else if (damage == 2)
src << "<span class='warning'>Your eyes burn.</span>"
adjust_eye_damage(rand(2, 4))
else if( damage > 3)
src << "<span class='warning'>Your eyes itch and burn severely!</span>"
adjust_eye_damage(rand(12, 16))
if(eye_damage > 10)
blind_eyes(damage)
blur_eyes(damage * rand(3, 6))
if(eye_damage > 20)
if(prob(eye_damage - 20))
if(become_nearsighted())
src << "<span class='warning'>Your eyes start to burn badly!</span>"
else if(prob(eye_damage - 25))
if(become_blind())
src << "<span class='warning'>You can't see anything!</span>"
else
src << "<span class='warning'>Your eyes are really starting to hurt. This can't be good for you!</span>"
if(has_bane(BANE_LIGHT))
mind.disrupt_spells(-500)
return 1
else if(damage == 0) // just enough protection
if(prob(20))
src << "<span class='notice'>Something bright flashes in the corner of your vision!</span>"
if(has_bane(BANE_LIGHT))
mind.disrupt_spells(0)
victim.Weaken(1)
Weaken(1)
victim.take_bodypart_damage(10)
take_bodypart_damage(10)
visible_message("<span class='danger'>[src] crashes into [victim], knocking them both over!</span>", "<span class='userdanger'>You violently crash into [victim]!</span>")
playsound(src,'sound/weapons/punch1.ogg',50,1)
//Throwing stuff
@@ -217,7 +140,7 @@
return
var/atom/movable/thrown_thing
var/obj/item/I = src.get_active_hand()
var/obj/item/I = src.get_active_held_item()
if(!I)
if(pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
@@ -234,7 +157,7 @@
else if(!(I.flags & (NODROP|ABSTRACT)))
thrown_thing = I
unEquip(I)
dropItemToGround(I)
if(thrown_thing)
visible_message("<span class='danger'>[src] has thrown [thrown_thing].</span>")
@@ -256,8 +179,11 @@
<HR>
<BR><B>Head:</B> <A href='?src=\ref[src];item=[slot_head]'> [(head && !(head.flags&ABSTRACT)) ? head : "Nothing"]</A>
<BR><B>Mask:</B> <A href='?src=\ref[src];item=[slot_wear_mask]'> [(wear_mask && !(wear_mask.flags&ABSTRACT)) ? wear_mask : "Nothing"]</A>
<BR><B>Left Hand:</B> <A href='?src=\ref[src];item=[slot_l_hand]'> [(l_hand && !(l_hand.flags&ABSTRACT)) ? l_hand : "Nothing"]</A>
<BR><B>Right Hand:</B> <A href='?src=\ref[src];item=[slot_r_hand]'> [(r_hand && !(r_hand.flags&ABSTRACT)) ? r_hand : "Nothing"]</A>"}
<BR><B>Neck:</B> <A href='?src=\ref[src];item=[slot_neck]'> [(wear_neck && !(wear_neck.flags&ABSTRACT)) ? wear_neck : "Nothing"]</A>"}
for(var/i in 1 to held_items.len)
var/obj/item/I = get_item_for_held_index(i)
dat += "<BR><B>[get_held_index_name(i)]:</B></td><td><A href='?src=\ref[src];item=[slot_hands];hand_index=[i]'>[(I && !(I.flags & ABSTRACT)) ? I : "Nothing"]</a>"
dat += "<BR><B>Back:</B> <A href='?src=\ref[src];item=[slot_back]'>[back ? back : "Nothing"]</A>"
@@ -305,13 +231,6 @@
/mob/living/carbon/is_muzzled()
return(istype(src.wear_mask, /obj/item/clothing/mask/muzzle))
/mob/living/carbon/blob_act(obj/effect/blob/B)
if (stat == DEAD)
return
else
show_message("<span class='userdanger'>The blob attacks!</span>")
adjustBruteLoss(10)
/mob/living/carbon/proc/spin(spintime, speed)
set waitfor = 0
var/D = dir
@@ -347,7 +266,7 @@
/mob/living/carbon/resist_fire()
fire_stacks -= 5
Weaken(3,1)
Weaken(3, 1, 1)
spin(32,2)
visible_message("<span class='danger'>[src] rolls on the floor, trying to put themselves out!</span>", \
"<span class='notice'>You stop, drop, and roll!</span>")
@@ -360,13 +279,20 @@
/mob/living/carbon/resist_restraints()
var/obj/item/I = null
var/type = 0
if(handcuffed)
I = handcuffed
type = 1
else if(legcuffed)
I = legcuffed
type = 2
if(I)
changeNext_move(CLICK_CD_BREAKOUT)
last_special = world.time + CLICK_CD_BREAKOUT
if(type == 1)
changeNext_move(CLICK_CD_BREAKOUT)
last_special = world.time + CLICK_CD_BREAKOUT
if(type == 2)
changeNext_move(CLICK_CD_RANGE)
last_special = world.time + CLICK_CD_RANGE
cuff_resist(I)
@@ -407,6 +333,7 @@
W.dropped(src)
if (W)
W.layer = initial(W.layer)
W.plane = initial(W.plane)
if (legcuffed)
var/obj/item/weapon/W = legcuffed
legcuffed = null
@@ -418,6 +345,7 @@
W.dropped(src)
if (W)
W.layer = initial(W.layer)
W.plane = initial(W.plane)
/mob/living/carbon/proc/clear_cuffs(obj/item/I, cuff_break)
if(!I.loc || buckled)
@@ -452,6 +380,9 @@
legcuffed = null
update_inv_legcuffed()
return
else
dropItemToGround(I)
return
return TRUE
/mob/living/carbon/proc/is_mouth_covered(head_only = 0, mask_only = 0)
@@ -464,15 +395,11 @@
else
return initial(pixel_y)
/mob/living/carbon/check_ear_prot()
if(head && (head.flags & HEADBANGPROTECT))
return 1
/mob/living/carbon/proc/accident(obj/item/I)
if(!I || (I.flags & (NODROP|ABSTRACT)))
return
unEquip(I)
dropItemToGround(I)
var/modifier = 0
if(disabilities & CLUMSY)
@@ -496,17 +423,6 @@
var/turf/target = get_turf(loc)
I.throw_at(target,I.throw_range,I.throw_speed,src)
/mob/living/carbon/emp_act(severity)
for(var/obj/item/organ/O in internal_organs)
O.emp_act(severity)
..()
/mob/living/carbon/check_eye_prot()
var/number = ..()
for(var/obj/item/organ/cyberimp/eyes/EFP in internal_organs)
number += EFP.flash_protect
return number
/mob/living/carbon/proc/AddAbility(obj/effect/proc_holder/alien/A)
abilities.Add(A)
A.on_gain(src)
@@ -535,11 +451,19 @@
add_abilities_to_panel()
/mob/living/carbon/attack_ui(slot)
if(!has_hand_for_held_index(active_hand_index))
return 0
return ..()
/mob/living/carbon/proc/vomit(var/lost_nutrition = 10, var/blood = 0, var/stun = 1, var/distance = 0, var/message = 1, var/toxic = 0)
if(dna && dna.species && NOHUNGER in dna.species.species_traits)
return 1
if(nutrition < 100 && !blood)
if(message)
visible_message("<span class='warning'>[src] dry heaves!</span>", \
"<span class='userdanger'>You try to throw up, but there's nothing your stomach!</span>")
"<span class='userdanger'>You try to throw up, but there's nothing in your stomach!</span>")
if(stun)
Weaken(10)
return 1
@@ -575,12 +499,27 @@
return 1
/mob/living/carbon/fully_replace_character_name(oldname,newname)
..()
if(dna)
dna.real_name = real_name
//Updates the mob's health from bodyparts and mob damage variables
/mob/living/carbon/updatehealth()
if(status_flags & GODMODE)
return
var/total_burn = 0
var/total_brute = 0
for(var/X in bodyparts) //hardcoded to streamline things a bit
var/obj/item/bodypart/BP = X
total_brute += BP.brute_dam
total_burn += BP.burn_dam
health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute
update_stat()
if(((maxHealth - total_burn) < HEALTH_THRESHOLD_DEAD) && stat == DEAD )
become_husk()
med_hud_set_health()
/mob/living/carbon/update_sight()
if(!client)
return
@@ -636,7 +575,7 @@
if(!client)
return
if(stat == UNCONSCIOUS && health <= config.health_threshold_crit)
if(stat == UNCONSCIOUS && health <= HEALTH_THRESHOLD_CRIT)
var/severity = 0
switch(health)
if(-20 to -10) severity = 1
@@ -714,10 +653,10 @@
if(status_flags & GODMODE)
return
if(stat != DEAD)
if(health<= config.health_threshold_dead || !getorgan(/obj/item/organ/brain))
if(health<= HEALTH_THRESHOLD_DEAD || !getorgan(/obj/item/organ/brain))
death()
return
if(paralysis || sleeping || getOxyLoss() > 50 || (status_flags & FAKEDEATH) || health <= config.health_threshold_crit)
if(paralysis || sleeping || getOxyLoss() > 50 || (status_flags & FAKEDEATH) || health <= HEALTH_THRESHOLD_CRIT)
if(stat == CONSCIOUS)
stat = UNCONSCIOUS
blind_eyes(1)
@@ -735,8 +674,7 @@
//called when we get cuffed/uncuffed
/mob/living/carbon/proc/update_handcuffed()
if(handcuffed)
drop_r_hand()
drop_l_hand()
drop_all_held_items()
stop_pulling()
throw_alert("handcuffed", /obj/screen/alert/restrained/handcuffed, new_master = src.handcuffed)
else
@@ -752,8 +690,11 @@
if(B)
B.damaged_brain = 0
for(var/datum/disease/D in viruses)
D.cure(0)
if (D.severity != NONTHREAT)
D.cure(0)
if(admin_revive)
regenerate_limbs()
regenerate_organs()
handcuffed = initial(handcuffed)
for(var/obj/item/weapon/restraints/R in contents) //actually remove cuffs from inventory
qdel(R)
@@ -771,7 +712,8 @@
if(qdeleted(src))
return
var/organs_amt = 0
for(var/obj/item/organ/O in internal_organs)
for(var/X in internal_organs)
var/obj/item/organ/O = X
if(prob(50))
organs_amt++
O.Remove(src)
@@ -781,12 +723,61 @@
..()
/mob/living/carbon/adjustToxLoss(amount, updating_health=1)
if(has_dna() && TOXINLOVER in dna.species.specflags) //damage becomes healing and healing becomes damage
amount = -amount
if(amount > 0)
blood_volume -= 5*amount
else
blood_volume -= amount
return ..()
/mob/living/carbon/ExtinguishMob()
for(var/X in get_equipped_items())
var/obj/item/I = X
I.acid_level = 0 //washes off the acid on our clothes
I.extinguish() //extinguishes our clothes
..()
/mob/living/carbon/fakefire(var/fire_icon = "Generic_mob_burning")
var/image/new_fire_overlay = image("icon"='icons/mob/OnFire.dmi', "icon_state"= fire_icon, "layer"=-FIRE_LAYER)
new_fire_overlay.appearance_flags = RESET_COLOR
overlays_standing[FIRE_LAYER] = new_fire_overlay
apply_overlay(FIRE_LAYER)
/mob/living/carbon/fakefireextinguish()
remove_overlay(FIRE_LAYER)
/mob/living/carbon/proc/devour_mob(mob/living/carbon/C, devour_time = 130)
C.visible_message("<span class='danger'>[src] is attempting to devour [C]!</span>", \
"<span class='userdanger'>[src] is attempting to devour you!</span>")
if(!do_mob(src, C, devour_time))
return
if(pulling && pulling == C && grab_state >= GRAB_AGGRESSIVE && a_intent == INTENT_GRAB)
C.visible_message("<span class='danger'>[src] devours [C]!</span>", \
"<span class='userdanger'>[src] devours you!</span>")
C.forceMove(src)
stomach_contents.Add(C)
add_logs(src, C, "devoured")
/mob/living/carbon/proc/create_bodyparts()
var/l_arm_index_next = -1
var/r_arm_index_next = 0
for(var/X in bodyparts)
var/obj/item/bodypart/O = new X()
O.owner = src
bodyparts.Remove(X)
bodyparts.Add(O)
if(O.body_part == ARM_LEFT)
l_arm_index_next += 2
O.held_index = l_arm_index_next //1, 3, 5, 7...
hand_bodyparts += O
else if(O.body_part == ARM_RIGHT)
r_arm_index_next += 2
O.held_index = r_arm_index_next //2, 4, 6, 8...
hand_bodyparts += O
/mob/living/carbon/proc/create_internal_organs()
for(var/X in internal_organs)
var/obj/item/organ/I = X
I.Insert(src)
/mob/living/carbon/vv_get_dropdown()
. = ..()
. += "---"
.["Make AI"] = "?_src_=vars;makeai=\ref[src]"
.["Modify bodypart"] = "?_src_=vars;editbodypart=\ref[src]"
.["Modify organs"] = "?_src_=vars;editorgans=\ref[src]"
+230 -36
View File
@@ -1,6 +1,22 @@
/mob/living/carbon/get_eye_protection()
var/number = ..()
for(var/obj/item/organ/cyberimp/eyes/EFP in internal_organs)
number += EFP.flash_protect
return number
/mob/living/carbon/get_ear_protection()
if(head && (head.flags & HEADBANGPROTECT))
return 1
/mob/living/carbon/check_projectile_dismemberment(obj/item/projectile/P, def_zone)
var/obj/item/bodypart/affecting = get_bodypart(def_zone)
if(affecting && affecting.dismemberable && affecting.get_damage() >= (affecting.max_damage - P.dismemberment))
affecting.dismember(P.damtype)
/mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked = 0)
if(!skipcatch) //ugly, but easy
if(in_throw_mode && !get_active_hand()) //empty active hand and we're in throw mode
if(in_throw_mode && !get_active_held_item()) //empty active hand and we're in throw mode
if(canmove && !restrained())
if(istype(AM, /obj/item))
var/obj/item/I = AM
@@ -11,25 +27,46 @@
return 1
..()
/mob/living/carbon/throw_impact(atom/hit_atom)
. = ..()
if(hit_atom.density && isturf(hit_atom))
Weaken(1)
take_organ_damage(10)
/mob/living/carbon/attackby(obj/item/I, mob/user, params)
if(lying)
if(surgeries.len)
if(user != src && user.a_intent == "help")
for(var/datum/surgery/S in surgeries)
if(S.next_step(user, src))
return 1
return ..()
/mob/living/carbon/attacked_by(obj/item/I, mob/living/user)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(user.zone_selected))
if(!affecting) //missing limb? we select the first bodypart (you can never have zero, because of chest)
affecting = bodyparts[1]
send_item_attack_message(I, user, affecting.name)
if(I.force)
apply_damage(I.force, I.damtype, affecting)
damage_clothes(I.force, I.damtype, "melee", affecting.body_zone)
if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC)
if(prob(33))
I.add_mob_blood(src)
var/turf/location = get_turf(src)
add_splatter_floor(location)
if(get_dist(user, src) <= 1) //people with TK won't get smeared with blood
user.add_mob_blood(src)
if(affecting.body_zone == "head")
if(wear_mask)
wear_mask.add_mob_blood(src)
update_inv_wear_mask()
if(wear_neck)
wear_neck.add_mob_blood(src)
update_inv_neck()
if(head)
head.add_mob_blood(src)
update_inv_head()
//dismemberment
var/probability = I.get_dismemberment_chance(affecting)
if(prob(probability))
if(affecting.dismember(I.damtype))
I.add_mob_blood(src)
playsound(get_turf(src), I.get_dismember_sound(), 80, 1)
return TRUE //successful attack
/mob/living/carbon/attack_drone(mob/living/simple_animal/drone/user)
return //so we don't call the carbon's attack_hand().
/mob/living/carbon/attack_hand(mob/living/carbon/human/user)
if(!iscarbon(user))
return
for(var/datum/disease/D in viruses)
if(D.IsSpreadByTouch())
@@ -39,19 +76,15 @@
if(D.IsSpreadByTouch())
ContractDisease(D)
if(lying)
if(user.a_intent == "help")
if(surgeries.len)
for(var/datum/surgery/S in surgeries)
if(S.next_step(user, src))
return 1
if(lying && surgeries.len)
if(user.a_intent == INTENT_HELP)
for(var/datum/surgery/S in surgeries)
if(S.next_step(user))
return 1
return 0
/mob/living/carbon/attack_paw(mob/living/carbon/monkey/M)
if(!istype(M, /mob/living/carbon))
return 0
for(var/datum/disease/D in viruses)
if(D.IsSpreadByTouch())
M.ContractDisease(D)
@@ -60,7 +93,7 @@
if(D.IsSpreadByTouch())
ContractDisease(D)
if(M.a_intent == "help")
if(M.a_intent == INTENT_HELP)
help_shake_act(M)
return 0
@@ -95,14 +128,175 @@
updatehealth()
return 1
/mob/living/carbon/proc/devour_mob(mob/living/carbon/C, devour_time = 130)
C.visible_message("<span class='danger'>[src] is attempting to devour [C]!</span>", \
"<span class='userdanger'>[src] is attempting to devour you!</span>")
if(!do_mob(src, C, devour_time))
/mob/living/carbon/proc/dismembering_strike(mob/living/attacker, dam_zone)
if(!attacker.limb_destroyer)
return dam_zone
var/obj/item/bodypart/affecting
if(dam_zone && attacker.client)
affecting = get_bodypart(ran_zone(dam_zone))
else
var/list/things_to_ruin = shuffle(bodyparts.Copy())
for(var/B in things_to_ruin)
var/obj/item/bodypart/bodypart = B
if(bodypart.body_zone == "head" || bodypart.body_zone == "chest")
continue
if(!affecting || ((affecting.get_damage() / affecting.max_damage) < (bodypart.get_damage() / bodypart.max_damage)))
affecting = bodypart
if(affecting)
dam_zone = affecting.body_zone
if(affecting.get_damage() >= affecting.max_damage)
affecting.dismember()
return null
return affecting.body_zone
return dam_zone
/mob/living/carbon/blob_act(obj/structure/blob/B)
if (stat == DEAD)
return
if(pulling && pulling == C && grab_state >= GRAB_AGGRESSIVE && a_intent == "grab")
C.visible_message("<span class='danger'>[src] devours [C]!</span>", \
"<span class='userdanger'>[src] devours you!</span>")
C.forceMove(src)
stomach_contents.Add(C)
add_logs(src, C, "devoured")
else
show_message("<span class='userdanger'>The blob attacks!</span>")
adjustBruteLoss(10)
/mob/living/carbon/emp_act(severity)
for(var/X in internal_organs)
var/obj/item/organ/O = X
O.emp_act(severity)
..()
/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0, illusion = 0)
shock_damage *= siemens_coeff
if(dna && dna.species)
shock_damage *= dna.species.siemens_coeff
if(shock_damage<1 && !override)
return 0
if(reagents.has_reagent("teslium"))
shock_damage *= 1.5 //If the mob has teslium in their body, shocks are 50% more damaging!
if(illusion)
adjustStaminaLoss(shock_damage)
else
take_overall_damage(0,shock_damage)
visible_message(
"<span class='danger'>[src] was shocked by \the [source]!</span>", \
"<span class='userdanger'>You feel a powerful shock coursing through your body!</span>", \
"<span class='italics'>You hear a heavy electrical crack.</span>" \
)
jitteriness += 1000 //High numbers for violent convulsions
do_jitter_animation(jitteriness)
stuttering += 2
if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5))
Stun(2)
spawn(20)
jitteriness = max(jitteriness - 990, 10) //Still jittery, but vastly less
if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5))
Stun(3)
Weaken(3)
if(override)
return override
else
return shock_damage
/mob/living/carbon/proc/help_shake_act(mob/living/carbon/M)
if(on_fire)
M << "<span class='warning'>You can't put them out with just your bare hands!"
return
if(health >= 0 && !(status_flags & FAKEDEATH))
if(lying)
M.visible_message("<span class='notice'>[M] shakes [src] trying to get [p_them()] up!</span>", \
"<span class='notice'>You shake [src] trying to get [p_them()] up!</span>")
else
M.visible_message("<span class='notice'>[M] hugs [src] to make [p_them()] feel better!</span>", \
"<span class='notice'>You hug [src] to make [p_them()] feel better!</span>")
AdjustSleeping(-5)
AdjustParalysis(-3)
AdjustStunned(-3)
AdjustWeakened(-3)
if(resting)
resting = 0
update_canmove()
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
/mob/living/carbon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
. = ..()
var/damage = intensity - get_eye_protection()
if(.) // we've been flashed
if(visual)
return
if (damage == 1)
src << "<span class='warning'>Your eyes sting a little.</span>"
if(prob(40))
adjust_eye_damage(1)
else if (damage == 2)
src << "<span class='warning'>Your eyes burn.</span>"
adjust_eye_damage(rand(2, 4))
else if( damage > 3)
src << "<span class='warning'>Your eyes itch and burn severely!</span>"
adjust_eye_damage(rand(12, 16))
if(eye_damage > 10)
blind_eyes(damage)
blur_eyes(damage * rand(3, 6))
if(eye_damage > 20)
if(prob(eye_damage - 20))
if(become_nearsighted())
src << "<span class='warning'>Your eyes start to burn badly!</span>"
else if(prob(eye_damage - 25))
if(become_blind())
src << "<span class='warning'>You can't see anything!</span>"
else
src << "<span class='warning'>Your eyes are really starting to hurt. This can't be good for you!</span>"
if(has_bane(BANE_LIGHT))
mind.disrupt_spells(-500)
return 1
else if(damage == 0) // just enough protection
if(prob(20))
src << "<span class='notice'>Something bright flashes in the corner of your vision!</span>"
if(has_bane(BANE_LIGHT))
mind.disrupt_spells(0)
/mob/living/carbon/soundbang_act(intensity = 1, stun_pwr = 1, damage_pwr = 5, deafen_pwr = 15)
var/ear_safety = get_ear_protection()
if(ear_safety < 2) //has ears
var/effect_amount = intensity - ear_safety
if(effect_amount > 0)
if(stun_pwr)
Stun(stun_pwr*effect_amount)
Weaken(stun_pwr*effect_amount)
if(deafen_pwr || damage_pwr)
setEarDamage(ear_damage + damage_pwr*effect_amount, max(ear_deaf, deafen_pwr*effect_amount))
if (ear_damage >= 15)
src << "<span class='warning'>Your ears start to ring badly!</span>"
if(prob(ear_damage - 5))
src << "<span class='warning'>You can't hear anything!</span>"
disabilities |= DEAF
else if(ear_damage >= 5)
src << "<span class='warning'>Your ears start to ring!</span>"
src << sound('sound/weapons/flash_ring.ogg',0,1,0,250)
return effect_amount //how soundbanged we are
/mob/living/carbon/damage_clothes(damage_amount, damage_type = BRUTE, damage_flag = 0, def_zone)
if(damage_type != BRUTE && damage_type != BURN)
return
damage_amount *= 0.5 //0.5 multiplier for balance reason, we don't want clothes to be too easily destroyed
if(!def_zone || def_zone == "head")
var/obj/item/clothing/hit_clothes
if(wear_mask)
hit_clothes = wear_mask
if(wear_neck)
hit_clothes = wear_neck
if(head)
hit_clothes = head
if(hit_clothes)
hit_clothes.take_damage(damage_amount, damage_type, damage_flag, 0)
@@ -1,9 +1,8 @@
/mob/living/
var/list/stomach_contents = list()
/mob/living/carbon
gender = MALE
//var/list/stomach_contents = list()
pressure_resistance = 15
possible_a_intents = list(INTENT_HELP, INTENT_HARM)
var/list/stomach_contents = list()
var/list/internal_organs = list() //List of /obj/item/organ in the mob. They don't go in the contents for some reason I don't want to know.
var/list/internal_organs_slot = list() //Same as above, but stores "slot ID" - "organ" pairs for easy access.
@@ -15,17 +14,24 @@
//inventory slots
var/obj/item/back = null
var/obj/item/clothing/mask/wear_mask = null
var/obj/item/clothing/neck/wear_neck = null
var/obj/item/weapon/tank/internal = null
var/obj/item/head = null
var/obj/item/gloves = null //only used by humans
var/obj/item/shoes = null //only used by humans.
var/obj/item/clothing/glasses/glasses = null //only used by humans.
var/obj/item/ears = null //only used by humans.
var/datum/dna/dna = null//Carbon
var/datum/mind/last_mind = null //last mind to control this mob, for blood-based cloning
var/failed_last_breath = 0 //This is used to determine if the mob failed a breath. If they did fail a brath, they will attempt to breathe each tick, otherwise just once per 4 ticks.
var/co2overloadtime = null
var/temperature_resistance = T0C+75
has_limbs = 1
var/obj/item/weapon/reagent_containers/food/snacks/meat/slab/type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/
var/obj/item/weapon/reagent_containers/food/snacks/meat/slab/type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab
var/list/obj/effect/proc_holder/alien/abilities = list()
var/gib_type = /obj/effect/decal/cleanable/blood/gibs
@@ -34,4 +40,8 @@
var/tinttotal = 0 // Total level of visualy impairing items
var/list/bodyparts = list() //Gets filled up in the constructor (New() proc in human.dm and monkey.dm)
var/list/bodyparts = list(/obj/item/bodypart/chest, /obj/item/bodypart/head, /obj/item/bodypart/l_arm,
/obj/item/bodypart/r_arm, /obj/item/bodypart/r_leg, /obj/item/bodypart/l_leg)
//Gets filled up in create_bodyparts()
var/list/hand_bodyparts = list() //a collection of arms (or actually whatever the fug /bodyparts you monsters use to wreck my systems)
@@ -1,16 +1,35 @@
/mob/living/carbon/movement_delay()
. = ..()
. += grab_state * 3
if(legcuffed)
. += legcuffed.slowdown
var/FP
if(iscarbon(src))
var/mob/living/carbon/C = src
var/obj/item/device/flightpack/F = C.get_flightpack()
if(istype(F) && F.flight)
FP = 1
. = ..(FP)
if(!FP)
. += grab_state * 1 //Flightpacks are too powerful to be slowed too much by the weight of a corpse.
else
. += grab_state * 3 //can't go fast while grabbing something.
if(!get_leg_ignore()) //ignore the fact we lack legs
var/leg_amount = get_num_legs()
. += 6 - 3*leg_amount //the fewer the legs, the slower the mob
if(!leg_amount)
. += 6 - 3*get_num_arms() //crawling is harder with fewer arms
if(legcuffed)
. += legcuffed.slowdown
var/const/NO_SLIP_WHEN_WALKING = 1
var/const/SLIDE = 2
var/const/GALOSHES_DONT_HELP = 4
var/const/SLIDE_ICE = 8
/mob/living/carbon/slip(s_amount, w_amount, obj/O, lube)
add_logs(src,, "slipped",, "on [O ? O.name : "floor"]")
if(movement_type & FLYING)
return 0
if(!(lube&SLIDE_ICE))
add_logs(src,, "slipped",, "on [O ? O.name : "floor"]")
return loc.handle_slip(src, s_amount, w_amount, O, lube)
@@ -20,6 +39,10 @@ var/const/GALOSHES_DONT_HELP = 4
if(!isturf(loc))
return 0
var/obj/item/device/flightpack/F = get_flightpack()
if(istype(F) && (F.flight) && F.allow_thrust(0.01, src))
return 1
// Do we have a jetpack implant (and is it on)?
var/obj/item/organ/cyberimp/chest/thrusters/T = getorganslot("thrusters")
if(istype(T) && movement_dir && T.allow_thrust(0.01))
@@ -29,14 +52,14 @@ var/const/GALOSHES_DONT_HELP = 4
if(istype(J) && (movement_dir || J.stabilizers) && J.allow_thrust(0.01, src))
return 1
/mob/living/carbon/Move(NewLoc, direct)
. = ..()
if(.)
if(src.nutrition && src.stat != 2)
src.nutrition -= HUNGER_FACTOR/10
if(src.m_intent == "run")
src.nutrition -= HUNGER_FACTOR/10
if((src.disabilities & FAT) && src.m_intent == "run" && src.bodytemperature <= 360)
src.bodytemperature += 2
if(. && mob_has_gravity()) //floating is easy
if(dna && dna.species && (NOHUNGER in dna.species.species_traits))
nutrition = NUTRITION_LEVEL_FED - 1 //just less than feeling vigorous
else if(nutrition && stat != DEAD)
nutrition -= HUNGER_FACTOR/10
if(m_intent == MOVE_INTENT_RUN)
nutrition -= HUNGER_FACTOR/10
if((disabilities & FAT) && m_intent == MOVE_INTENT_RUN && bodytemperature <= 360)
bodytemperature += 2
@@ -0,0 +1,193 @@
/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = 0)
var/hit_percent = (100-blocked)/100
if(!damage || hit_percent <= 0)
return 0
var/obj/item/bodypart/BP = null
if(islimb(def_zone)) //we specified a bodypart object
BP = def_zone
else
if(!def_zone)
def_zone = ran_zone(def_zone)
BP = get_bodypart(check_zone(def_zone))
if(!BP)
BP = bodyparts[1]
switch(damagetype)
if(BRUTE)
if(BP)
if(BP.receive_damage(damage * hit_percent, 0))
update_damage_overlays()
else //no bodypart, we deal damage with a more general method.
adjustBruteLoss(damage * hit_percent)
if(BURN)
if(BP)
if(BP.receive_damage(0, damage * hit_percent))
update_damage_overlays()
else
adjustFireLoss(damage * hit_percent)
if(TOX)
adjustToxLoss(damage * hit_percent)
if(OXY)
adjustOxyLoss(damage * hit_percent)
if(CLONE)
adjustCloneLoss(damage * hit_percent)
if(STAMINA)
adjustStaminaLoss(damage * hit_percent)
return 1
//These procs fetch a cumulative total damage from all bodyparts
/mob/living/carbon/getBruteLoss()
var/amount = 0
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
amount += BP.brute_dam
return amount
/mob/living/carbon/getFireLoss()
var/amount = 0
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
amount += BP.burn_dam
return amount
/mob/living/carbon/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
return FALSE
if(amount > 0)
take_overall_damage(amount, 0, updating_health)
else
heal_overall_damage(-amount, 0, 0, 1, updating_health)
return amount
/mob/living/carbon/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
return FALSE
if(amount > 0)
take_overall_damage(0, amount, updating_health)
else
heal_overall_damage(0, -amount, 0, 1, updating_health)
return amount
/mob/living/carbon/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && has_dna() && TOXINLOVER in dna.species.species_traits) //damage becomes healing and healing becomes damage
amount = -amount
if(amount > 0)
blood_volume -= 5*amount
else
blood_volume -= amount
return ..()
////////////////////////////////////////////
//Returns a list of damaged bodyparts
/mob/living/carbon/proc/get_damaged_bodyparts(brute, burn)
var/list/obj/item/bodypart/parts = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if((brute && BP.brute_dam) || (burn && BP.burn_dam))
parts += BP
return parts
//Returns a list of damageable bodyparts
/mob/living/carbon/proc/get_damageable_bodyparts()
var/list/obj/item/bodypart/parts = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(BP.brute_dam + BP.burn_dam < BP.max_damage)
parts += BP
return parts
//Heals ONE bodypart randomly selected from damaged ones.
//It automatically updates damage overlays if necessary
//It automatically updates health status
/mob/living/carbon/heal_bodypart_damage(brute, burn, only_robotic = 0, only_organic = 1)
var/list/obj/item/bodypart/parts = get_damaged_bodyparts(brute,burn)
if(!parts.len)
return
var/obj/item/bodypart/picked = pick(parts)
if(picked.heal_damage(brute, burn, only_robotic, only_organic))
update_damage_overlays()
//Damages ONE bodypart randomly selected from damagable ones.
//It automatically updates damage overlays if necessary
//It automatically updates health status
/mob/living/carbon/take_bodypart_damage(brute, burn)
var/list/obj/item/bodypart/parts = get_damageable_bodyparts()
if(!parts.len)
return
var/obj/item/bodypart/picked = pick(parts)
if(picked.receive_damage(brute,burn))
update_damage_overlays()
//Heal MANY bodyparts, in random order
/mob/living/carbon/heal_overall_damage(brute, burn, only_robotic = 0, only_organic = 1, updating_health = 1)
var/list/obj/item/bodypart/parts = get_damaged_bodyparts(brute,burn)
var/update = 0
while(parts.len && (brute>0 || burn>0) )
var/obj/item/bodypart/picked = pick(parts)
var/brute_was = picked.brute_dam
var/burn_was = picked.burn_dam
update |= picked.heal_damage(brute,burn, only_robotic, only_organic, 0)
brute -= (brute_was-picked.brute_dam)
burn -= (burn_was-picked.burn_dam)
parts -= picked
if(updating_health)
updatehealth()
if(update)
update_damage_overlays()
// damage MANY bodyparts, in random order
/mob/living/carbon/take_overall_damage(brute, burn, updating_health = 1)
if(status_flags & GODMODE)
return //godmode
var/list/obj/item/bodypart/parts = get_damageable_bodyparts()
var/update = 0
while(parts.len && (brute>0 || burn>0) )
var/obj/item/bodypart/picked = pick(parts)
var/brute_per_part = round(brute/parts.len, 0.01)
var/burn_per_part = round(burn/parts.len, 0.01)
var/brute_was = picked.brute_dam
var/burn_was = picked.burn_dam
update |= picked.receive_damage(brute_per_part,burn_per_part, 0)
brute -= (picked.brute_dam - brute_was)
burn -= (picked.burn_dam - burn_was)
parts -= picked
if(updating_health)
updatehealth()
if(update)
update_damage_overlays()
/mob/living/carbon/adjustStaminaLoss(amount, updating_stamina = 1)
if(status_flags & GODMODE)
return 0
staminaloss = Clamp(staminaloss + amount, 0, maxHealth*2)
if(updating_stamina)
update_stamina()
/mob/living/carbon/setStaminaLoss(amount, updating_stamina = 1)
if(status_flags & GODMODE)
return 0
staminaloss = amount
if(updating_stamina)
update_stamina()
+43 -10
View File
@@ -1,21 +1,54 @@
/mob/living/carbon/death(gibbed)
if(stat == DEAD)
return
silent = 0
losebreath = 0
..()
/mob/living/carbon/gib(no_brain, no_organs)
if(!gibbed)
emote("deathgasp")
. = ..()
if(ticker && ticker.mode)
ticker.mode.check_win() //Calls the rounds wincheck, mainly for wizard, malf, and changeling now
/mob/living/carbon/gib(no_brain, no_organs, no_bodyparts)
for(var/mob/M in src)
if(M in stomach_contents)
stomach_contents.Remove(M)
M.loc = loc
M.forceMove(loc)
visible_message("<span class='danger'>[M] bursts out of [src]!</span>")
..()
/mob/living/carbon/spill_organs(no_brain)
for(var/obj/item/organ/I in internal_organs)
if(no_brain && istype(I, /obj/item/organ/brain))
continue
if(I)
/mob/living/carbon/spill_organs(no_brain, no_organs, no_bodyparts)
if(!no_bodyparts)
if(no_organs)//so the organs don't get transfered inside the bodyparts we'll drop.
for(var/X in internal_organs)
qdel(X)
else //we're going to drop all bodyparts except chest, so the only organs that needs spilling are those inside it.
for(var/X in internal_organs)
var/obj/item/organ/O = X
if(no_brain && istype(O, /obj/item/organ/brain))
qdel(O) //so the brain isn't transfered to the head when the head drops.
continue
var/org_zone = check_zone(O.zone) //both groin and chest organs.
if(org_zone == "chest")
O.Remove(src)
O.forceMove(get_turf(src))
O.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
else
for(var/X in internal_organs)
var/obj/item/organ/I = X
if(no_brain && istype(I, /obj/item/organ/brain))
qdel(I)
continue
I.Remove(src)
I.loc = get_turf(src)
I.throw_at_fast(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
I.forceMove(get_turf(src))
I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
/mob/living/carbon/spread_bodyparts()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
BP.drop_limb()
BP.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
+72 -186
View File
@@ -1,200 +1,86 @@
//This only assumes that the mob has a body and face with at least one eye, and one mouth.
//Things like airguitar can be done without arms, and the flap thing makes so little sense it's a keeper.
//Intended to be called by a higher up emote proc if the requested emote isn't in the custom emotes.
/datum/emote/living/carbon
mob_type_allowed_typecache = list(/mob/living/carbon)
/mob/living/carbon/emote(act,m_type=1,message = null)
var/param = null
/datum/emote/living/carbon/airguitar
key = "airguitar"
message = "is strumming the air and headbanging like a safari chimp."
restraint_check = TRUE
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1)
/datum/emote/living/carbon/blink
key = "blink"
key_third_person = "blinks"
message = "blinks."
var/muzzled = is_muzzled()
//var/m_type = 1
/datum/emote/living/carbon/blink_r
key = "blink_r"
message = "blinks rapidly."
switch(act)//Even carbon organisms want it alphabetically ordered..
if ("aflap")
if (!src.restrained())
message = "<B>[src]</B> flaps \his wings ANGRILY!"
m_type = 2
/datum/emote/living/carbon/clap
key = "clap"
key_third_person = "claps"
message = "claps."
muzzle_ignore = TRUE
restraint_check = TRUE
emote_type = EMOTE_AUDIBLE
if ("airguitar")
if (!src.restrained())
message = "<B>[src]</B> is strumming the air and headbanging like a safari chimp."
m_type = 1
/datum/emote/living/carbon/gnarl
key = "gnarl"
key_third_person = "gnarls"
message = "gnarls and shows its teeth..."
mob_type_allowed_typecache = list(/mob/living/carbon/monkey, /mob/living/carbon/alien)
if ("blink","blinks")
message = "<B>[src]</B> blinks."
m_type = 1
/datum/emote/living/carbon/moan
key = "moan"
key_third_person = "moans"
message = "moans!"
message_mime = "appears to moan!"
emote_type = EMOTE_AUDIBLE
if ("blink_r")
message = "<B>[src]</B> blinks rapidly."
m_type = 1
/datum/emote/living/carbon/roll
key = "roll"
key_third_person = "rolls"
message = "rolls."
mob_type_allowed_typecache = list(/mob/living/carbon/monkey, /mob/living/carbon/alien)
restraint_check = TRUE
if ("blush","blushes")
message = "<B>[src]</B> blushes."
m_type = 1
/datum/emote/living/carbon/scratch
key = "scratch"
key_third_person = "scratches"
message = "scratches."
mob_type_allowed_typecache = list(/mob/living/carbon/monkey, /mob/living/carbon/alien)
restraint_check = TRUE
if ("bow","bows")
if (!src.buckled)
var/M = null
if (param)
for (var/mob/A in view(1, src))
if (param == A.name)
M = A
break
if (!M)
param = null
if (param)
message = "<B>[src]</B> bows to [param]."
else
message = "<B>[src]</B> bows."
m_type = 1
/datum/emote/living/carbon/screech
key = "screech"
key_third_person = "screeches"
message = "screeches."
mob_type_allowed_typecache = list(/mob/living/carbon/monkey, /mob/living/carbon/alien)
if ("burp","burps")
if (!muzzled)
..(act)
/datum/emote/living/carbon/sign
key = "sign"
key_third_person = "signs"
message_param = "signs the number %t."
mob_type_allowed_typecache = list(/mob/living/carbon/monkey, /mob/living/carbon/alien)
restraint_check = TRUE
if ("choke","chokes")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a strong noise."
m_type = 2
/datum/emote/living/carbon/sign/select_param(mob/user, params)
. = ..()
if(!isnum(text2num(params)))
return message
if ("chuckle","chuckles")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a noise."
m_type = 2
/datum/emote/living/carbon/sign/signal
key = "signal"
key_third_person = "signals"
message_param = "raises %t fingers."
mob_type_allowed_typecache = list(/mob/living/carbon/human)
restraint_check = TRUE
if ("clap","claps")
if (!src.restrained())
message = "<B>[src]</B> claps."
m_type = 2
/datum/emote/living/carbon/tail
key = "tail"
message = "waves their tail."
mob_type_allowed_typecache = list(/mob/living/carbon/monkey, /mob/living/carbon/alien)
if ("cough","coughs")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a strong noise."
m_type = 2
if ("deathgasp","deathgasps")
message = "<B>[src]</B> seizes up and falls limp, \his eyes dead and lifeless..."
m_type = 1
if ("flap","flaps")
if (!src.restrained())
message = "<B>[src]</B> flaps \his wings."
m_type = 2
if ("gasp","gasps")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a weak noise."
m_type = 2
if ("giggle","giggles")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a noise."
m_type = 2
if ("laugh","laughs")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a noise."
if ("me")
if(!silent)
..()
return
if ("nod","nods")
message = "<B>[src]</B> nods."
m_type = 1
if ("scream","screams")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a very loud noise."
m_type = 2
if ("shake","shakes")
message = "<B>[src]</B> shakes \his head."
m_type = 1
if ("sneeze","sneezes")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a strange noise."
m_type = 2
if ("sigh","sighs")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> sighs."
m_type = 2
if ("sniff","sniffs")
message = "<B>[src]</B> sniffs."
m_type = 2
if ("snore","snores")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a noise."
m_type = 2
if ("whimper","whimpers")
if (!muzzled)
..(act)
else
message = "<B>[src]</B> makes a weak noise."
m_type = 2
if ("wink","winks")
message = "<B>[src]</B> winks."
m_type = 1
if ("yawn","yawns")
if (!muzzled)
..(act)
if ("help")
src << "Help for emotes. You can use these emotes with say \"*emote\":\n\naflap, airguitar, blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, dance, deathgasp, drool, flap, frown, gasp, giggle, glare-(none)/mob, grin, jump, laugh, look, me, nod, point-atom, scream, shake, sigh, sit, smile, sneeze, sniff, snore, stare-(none)/mob, sulk, sway, tremble, twitch, twitch_s, wave, whimper, wink, yawn"
else
..(act)
if (message)
log_emote("[name]/[key] : [message]")
//Hearing gasp and such every five seconds is not good emotes were not global for a reason.
// Maybe some people are okay with that.
for(var/mob/M in dead_mob_list)
if(!M.client || istype(M, /mob/new_player))
continue //skip monkeys, leavers and new players
if(M.stat == DEAD && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null)))
M.show_message(message)
if (m_type & 1)
visible_message(message)
else if (m_type & 2)
audible_message(message)
/datum/emote/living/carbon/wink
key = "wink"
key_third_person = "winks"
message = "winks."
+70 -44
View File
@@ -1,64 +1,90 @@
/mob/living/carbon/examine(mob/user)
var/t_He = p_they(TRUE)
var/t_His = p_their(TRUE)
var/t_his = p_their()
var/t_him = p_them()
var/t_has = p_have()
var/t_is = p_are()
var/msg = "<span class='info'>*---------*\nThis is \icon[src] \a <EM>[src]</EM>!\n"
if (handcuffed)
msg += "It is \icon[src.handcuffed] handcuffed!\n"
msg += "<span class='warning'>[t_He] [t_is] \icon[src.handcuffed] handcuffed!</span>\n"
if (head)
msg += "It has \icon[src.head] \a [src.head] on its head. \n"
msg += "[t_He] [t_is] wearing \icon[src.head] \a [src.head] on [t_his] head. \n"
if (wear_mask)
msg += "It has \icon[src.wear_mask] \a [src.wear_mask] on its face.\n"
if (l_hand)
msg += "It has \icon[src.l_hand] \a [src.l_hand] in its left hand.\n"
if (r_hand)
msg += "It has \icon[src.r_hand] \a [src.r_hand] in its right hand.\n"
msg += "[t_He] [t_is] wearing \icon[src.wear_mask] \a [src.wear_mask] on [t_his] face.\n"
if (wear_neck)
msg += "[t_He] [t_is] wearing \icon[src.wear_neck] \a [src.wear_neck] around [t_his] neck.\n"
for(var/obj/item/I in held_items)
if(!(I.flags & ABSTRACT))
if(I.blood_DNA)
msg += "<span class='warning'>[t_He] [t_is] holding \icon[I] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in [t_his] [get_held_index_name(get_held_index_of_item(I))]!</span>\n"
else
msg += "[t_He] [t_is] holding \icon[I] \a [I] in [t_his] [get_held_index_name(get_held_index_of_item(I))].\n"
if (back)
msg += "It has \icon[src.back] \a [src.back] on its back.\n"
msg += "[t_He] [t_has] \icon[src.back] \a [src.back] on [t_his] back.\n"
var/appears_dead = 0
if (stat == DEAD)
msg += "<span class='deadsay'>It is limp and unresponsive, with no signs of life.</span>\n"
else
msg += "<span class='warning'>"
var/temp = getBruteLoss()
if(temp)
if (temp < 30)
msg += "It has minor bruising.\n"
else
msg += "<B>It has severe bruising!</B>\n"
appears_dead = 1
if(getorgan(/obj/item/organ/brain))
msg += "<span class='deadsay'>[t_He] [t_is] limp and unresponsive, with no signs of life.</span>\n"
else if(get_bodypart("head"))
msg += "<span class='deadsay'>[t_He] appears that [t_his] brain is missing...</span>\n"
temp = getFireLoss()
if(temp)
if (temp < 30)
msg += "It has minor burns.\n"
else
msg += "<B>It has severe burns!</B>\n"
var/list/missing = get_missing_limbs()
for(var/t in missing)
if(t=="head")
msg += "<span class='deadsay'><B>[t_His] [parse_zone(t)] is missing!</B></span>\n"
continue
msg += "<span class='warning'><B>[t_His] [parse_zone(t)] is missing!</B></span>\n"
temp = getCloneLoss()
if(temp)
if(getCloneLoss() < 30)
msg += "It is slightly deformed.\n"
else
msg += "<b>It is severely deformed.</b>\n"
msg += "<span class='warning'>"
var/temp = getBruteLoss()
if(temp)
if (temp < 30)
msg += "[t_He] [t_has] minor bruising.\n"
else
msg += "<B>[t_He] [t_has] severe bruising!</B>\n"
if(getBrainLoss() > 60)
msg += "It seems to be clumsy and unable to think.\n"
temp = getFireLoss()
if(temp)
if (temp < 30)
msg += "[t_He] [t_has] minor burns.\n"
else
msg += "<B>[t_He] [t_has] severe burns!</B>\n"
if(fire_stacks > 0)
msg += "It's covered in something flammable.\n"
if(fire_stacks < 0)
msg += "It's soaked in water.\n"
temp = getCloneLoss()
if(temp)
if(getCloneLoss() < 30)
msg += "[t_He] [t_is] slightly deformed.\n"
else
msg += "<b>[t_He] [t_is] severely deformed.</b>\n"
if(pulledby && pulledby.grab_state)
msg += "It's restrained by [pulledby]'s grip.\n"
if(getBrainLoss() > 60)
msg += "[t_He] seems to be clumsy and unable to think.\n"
if(fire_stacks > 0)
msg += "[t_He] [t_is] covered in something flammable.\n"
if(fire_stacks < 0)
msg += "[t_He] [t_is] looks a little soaked.\n"
if(pulledby && pulledby.grab_state)
msg += "[t_He] [t_is] restrained by [pulledby]'s grip.\n"
msg += "</span>"
if(!appears_dead)
if(stat == UNCONSCIOUS)
msg += "It isn't responding to anything around it; it seems to be asleep.\n"
msg += "</span>"
msg += "[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep.\n"
if(digitalcamo)
msg += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly unsimian manner.\n"
if(digitalcamo)
msg += "It is moving its body in an unnatural and blatantly unsimian manner.\n"
if(!getorgan(/obj/item/organ/brain))
msg += "<span class='deadsay'>It appears that it's brain is missing...</span>\n"
msg += "*---------*</span>"
user << msg
user << msg
@@ -0,0 +1,5 @@
/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = 0)
// depending on the species, it will run the corresponding apply_damage code there
return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src)
+12 -25
View File
@@ -1,11 +1,14 @@
/mob/living/carbon/human/gib_animation()
PoolOrNew(/obj/effect/overlay/temp/gib_animation, list(loc, "gibbed-h"))
new /obj/effect/overlay/temp/gib_animation(loc, "gibbed-h")
/mob/living/carbon/human/dust_animation()
PoolOrNew(/obj/effect/overlay/temp/dust_animation, list(loc, "dust-h"))
new /obj/effect/overlay/temp/dust_animation(loc, "dust-h")
/mob/living/carbon/human/spawn_gibs()
hgibs(loc, viruses, dna)
/mob/living/carbon/human/spawn_gibs(with_bodyparts)
if(with_bodyparts)
new /obj/effect/gibspawner/human(loc, viruses, dna)
else
new /obj/effect/gibspawner/humanbodypartless(loc, viruses, dna)
/mob/living/carbon/human/spawn_dust()
new /obj/effect/decal/remains/human(loc)
@@ -13,7 +16,9 @@
/mob/living/carbon/human/death(gibbed)
if(stat == DEAD)
return
stat = DEAD
. = ..()
dizziness = 0
jitteriness = 0
heart_attack = 0
@@ -23,39 +28,21 @@
if(M.occupant == src)
M.go_out()
if(!gibbed)
emote("deathgasp") //let the world KNOW WE ARE DEAD
dna.species.spec_death(gibbed, src)
if(ticker && ticker.mode)
sql_report_death(src)
ticker.mode.check_win() //Calls the rounds wincheck, mainly for wizard, malf, and changeling now
. = ..(gibbed)
if(mind && mind.devilinfo)
spawn(0)
mind.devilinfo.beginResurrectionCheck(src)
INVOKE_ASYNC(mind.devilinfo, /datum/devilinfo.proc/beginResurrectionCheck, src)
/mob/living/carbon/human/proc/makeSkeleton()
status_flags |= DISFIGURED
set_species(/datum/species/skeleton)
return 1
/mob/living/carbon/proc/ChangeToHusk()
if(disabilities & HUSK)
return
disabilities |= HUSK
status_flags |= DISFIGURED //makes them unknown without fucking up other stuff like admintools
return 1
/mob/living/carbon/human/ChangeToHusk()
. = ..()
if(.)
update_hair()
update_body()
/mob/living/carbon/proc/Drain()
ChangeToHusk()
become_husk()
disabilities |= NOCLONE
blood_volume = 0
return 1
+104 -403
View File
@@ -1,414 +1,126 @@
/mob/living/carbon/human/emote(act,m_type=1,message = null)
if(stat == DEAD && (act != "deathgasp") || (status_flags & FAKEDEATH)) //if we're faking, don't emote at all
return
/datum/emote/living/carbon/human
mob_type_allowed_typecache = list(/mob/living/carbon/human)
var/param = null
/datum/emote/living/carbon/human/cry
key = "cry"
key_third_person = "cries"
message = "cries."
emote_type = EMOTE_AUDIBLE
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1)
/datum/emote/living/carbon/human/dap
key = "dap"
key_third_person = "daps"
message = "sadly can't find anybody to give daps to, and daps themself. Shameful."
message_param = "give daps to %t."
restraint_check = TRUE
/datum/emote/living/carbon/human/eyebrow
key = "eyebrow"
message = "raises an eyebrow."
var/muzzled = is_muzzled()
//var/m_type = 1
/datum/emote/living/carbon/human/grumble
key = "grumble"
key_third_person = "grumbles"
message = "grumbles!"
emote_type = EMOTE_AUDIBLE
for (var/obj/item/weapon/implant/I in src)
if (I.implanted)
I.trigger(act, src)
/datum/emote/living/carbon/human/handshake
key = "handshake"
message = "shakes their own hands."
message_param = "shakes hands with %t."
restraint_check = TRUE
emote_type = EMOTE_AUDIBLE
var/miming=0
if(mind)
miming=mind.miming
/datum/emote/living/carbon/human/hug
key = "hug"
key_third_person = "hugs"
message = "hugs themself."
message_param = "hugs %t."
restraint_check = TRUE
emote_type = EMOTE_AUDIBLE
switch(act) //Please keep this alphabetically ordered when adding or changing emotes.
if ("aflap") //Any emote on human that uses miming must be left in, oh well.
if (!src.restrained())
message = "<B>[src]</B> flaps \his wings ANGRILY!"
m_type = 2
/datum/emote/living/carbon/human/mumble
key = "mumble"
key_third_person = "mumbles"
message = "mumbles!"
emote_type = EMOTE_AUDIBLE
if ("choke","chokes")
if (miming)
message = "<B>[src]</B> clutches \his throat desperately!"
else
..(act)
/datum/emote/living/carbon/human/pale
key = "pale"
message = "goes pale for a second."
if ("chuckle","chuckles")
if(miming)
message = "<B>[src]</B> appears to chuckle."
else
..(act)
/datum/emote/living/carbon/human/raise
key = "raise"
key_third_person = "raises"
message = "raises a hand."
restraint_check = TRUE
if ("clap","claps")
if (!src.restrained())
message = "<B>[src]</B> claps."
m_type = 2
/datum/emote/living/carbon/human/salute
key = "salute"
key_third_person = "salutes"
message = "salutes."
message_param = "salutes to %t."
restraint_check = TRUE
if ("collapse","collapses")
Paralyse(2)
adjustStaminaLoss(100) // Hampers abuse against simple mobs, but still leaves it a viable option.
message = "<B>[src]</B> collapses!"
m_type = 2
/datum/emote/living/carbon/human/shrug
key = "shrug"
key_third_person = "shrugs"
message = "shrugs."
if ("cough","coughs")
if (miming)
message = "<B>[src]</B> appears to cough!"
else
if (!muzzled)
message = "<B>[src]</B> coughs!"
m_type = 2
else
message = "<B>[src]</B> makes a strong noise."
m_type = 2
/datum/emote/living/carbon/human/wag
key = "wag"
key_third_person = "wags"
message = "wags their tail."
if ("cry","crys","cries") //I feel bad if people put s at the end of cry. -Sum99
if (miming)
message = "<B>[src]</B> cries."
else
if (!muzzled)
message = "<B>[src]</B> cries."
m_type = 2
else
message = "<B>[src]</B> makes a weak noise. \He frowns."
m_type = 2
/datum/emote/living/carbon/human/wag/run_emote(mob/user, params)
. = ..()
var/mob/living/carbon/human/H = user
if(.)
H.startTailWag()
else
H.endTailWag()
if ("custom")
if(jobban_isbanned(src, "emote"))
src << "You cannot send custom emotes (banned)"
return
if(src.client)
if(client.prefs.muted & MUTE_IC)
src << "You cannot send IC messages (muted)."
return
var/input = copytext(sanitize(input("Choose an emote to display.") as text|null),1,MAX_MESSAGE_LEN)
if (!input)
return
if(copytext(input,1,5) == "says")
src << "<span class='danger'>Invalid emote.</span>"
return
else if(copytext(input,1,9) == "exclaims")
src << "<span class='danger'>Invalid emote.</span>"
return
else if(copytext(input,1,6) == "yells")
src << "<span class='danger'>Invalid emote.</span>"
return
else if(copytext(input,1,5) == "asks")
src << "<span class='danger'>Invalid emote.</span>"
return
else
var/input2 = input("Is this a visible or hearable emote?") in list("Visible","Hearable")
if (input2 == "Visible")
m_type = 1
else if (input2 == "Hearable")
if(miming)
return
m_type = 2
else
alert("Unable to use this emote, must be either hearable or visible.")
return
message = "<B>[src]</B> [input]"
/datum/emote/living/carbon/human/wag/can_run_emote(mob/user)
if(!..())
return FALSE
var/mob/living/carbon/human/H = user
if(H.dna && H.dna.species && (("tail_lizard" in H.dna.species.mutant_bodyparts) || (H.dna.features["tail_human"] != "None")))
return TRUE
if ("dap","daps")
m_type = 1
if (!src.restrained())
var/M = null
if (param)
for (var/mob/A in view(1, src))
if (param == A.name)
M = A
break
if (M)
message = "<B>[src]</B> gives daps to [M]."
else
message = "<B>[src]</B> sadly can't find anybody to give daps to, and daps \himself. Shameful."
/datum/emote/living/carbon/human/wag/select_message_type(mob/user)
. = ..()
var/mob/living/carbon/human/H = user
if(("waggingtail_lizard" in H.dna.species.mutant_bodyparts) || ("waggingtail_human" in H.dna.species.mutant_bodyparts))
. = null
if ("eyebrow")
message = "<B>[src]</B> raises an eyebrow."
m_type = 1
if ("flap","flaps")
if (!src.restrained())
message = "<B>[src]</B> flaps \his wings."
m_type = 2
if(((dna.features["wings"] != "None") && !("wings" in dna.species.mutant_bodyparts)))
OpenWings()
addtimer(src, "CloseWings", 20)
if ("wings")
if (!src.restrained())
if(dna && dna.species &&((dna.features["wings"] != "None") && ("wings" in dna.species.mutant_bodyparts)))
message = "<B>[src]</B> opens \his wings."
OpenWings()
else if(dna && dna.species &&((dna.features["wings"] != "None") && ("wingsopen" in dna.species.mutant_bodyparts)))
message = "<B>[src]</B> closes \his wings."
CloseWings()
else
src << "<span class='notice'>Unusable emote '[act]'. Say *help for a list.</span>"
if ("gasp","gasps")
if (miming)
message = "<B>[src]</B> appears to be gasping!"
else
..(act)
if ("giggle","giggles")
if (miming)
message = "<B>[src]</B> giggles silently!"
else
..(act)
if ("groan","groans")
if (miming)
message = "<B>[src]</B> appears to groan!"
else
if (!muzzled)
message = "<B>[src]</B> groans!"
m_type = 2
else
message = "<B>[src]</B> makes a loud noise."
m_type = 2
if ("grumble","grumbles")
if (!muzzled)
message = "<B>[src]</B> grumbles!"
else
message = "<B>[src]</B> makes a noise."
m_type = 2
if ("handshake")
m_type = 1
if (!src.restrained() && !src.r_hand)
var/mob/M = null
if (param)
for (var/mob/A in view(1, src))
if (param == A.name)
M = A
break
if (M == src)
M = null
if (M)
if (M.canmove && !M.r_hand && !M.restrained())
message = "<B>[src]</B> shakes hands with [M]."
else
message = "<B>[src]</B> holds out \his hand to [M]."
if ("hug","hugs")
m_type = 1
if (!src.restrained())
var/M = null
if (param)
for (var/mob/A in view(1, src))
if (param == A.name)
M = A
break
if (M == src)
M = null
if (M)
message = "<B>[src]</B> hugs [M]."
else
message = "<B>[src]</B> hugs \himself."
if ("me")
if(silent)
return
if(jobban_isbanned(src, "emote"))
src << "You cannot send custom emotes (banned)"
return
if (src.client)
if (client.prefs.muted & MUTE_IC)
src << "<span class='danger'>You cannot send IC messages (muted).</span>"
return
if (src.client.handle_spam_prevention(message,MUTE_IC))
return
if (stat)
return
if(!(message))
return
if(copytext(message,1,5) == "says")
src << "<span class='danger'>Invalid emote.</span>"
return
else if(copytext(message,1,9) == "exclaims")
src << "<span class='danger'>Invalid emote.</span>"
return
else if(copytext(message,1,6) == "yells")
src << "<span class='danger'>Invalid emote.</span>"
return
else if(copytext(message,1,5) == "asks")
src << "<span class='danger'>Invalid emote.</span>"
return
else
message = "<B>[src]</B> [message]"
if ("moan","moans")
if(miming)
message = "<B>[src]</B> appears to moan!"
else
message = "<B>[src]</B> moans!"
m_type = 2
if ("mumble","mumbles")
message = "<B>[src]</B> mumbles!"
m_type = 2
if ("pale")
message = "<B>[src]</B> goes pale for a second."
m_type = 1
if ("raise")
if (!src.restrained())
message = "<B>[src]</B> raises a hand."
m_type = 1
if ("roar","roars")
if (miming)
message = "<B>[src]</B> appears to roar!"
else
if(!muzzled && has_dna())
m_type = 2
message = "<B>[src]</B> roars!"
switch(dna.species.id)
if("pred")
playsound(get_turf(src), "predroar", 50, 0, 5)
if("xeno")
playsound(get_turf(src), "alienscreech", 50, 0, 5)
else
..(act)
if ("salute","salutes")
if (!src.buckled)
var/M = null
if (param)
for (var/mob/A in view(1, src))
if (param == A.name)
M = A
break
if (!M)
param = null
if (param)
message = "<B>[src]</B> salutes to [param]."
else
message = "<B>[src]</b> salutes."
m_type = 1
if ("scream","screams")
if (miming)
message = "<B>[src]</B> acts out a scream!"
else
if(has_dna())
switch(dna.species.id) //Visit sound.dm to see and add more 'soundin' options. (alienscreech, malescream, femscream, etc)
if("xeno")
playsound(get_turf(src), "alienscreech", 50, 0, 5)
if("pred")
playsound(get_turf(src), "predroar", 50, 0, 5)
if("moth")
playsound(get_turf(src), "mothscream", 50, 1, 5)
if("lizard" || "drake")
playsound(get_turf(src), "drakescream", 50, 0, 5)
if("avian")
playsound(get_turf(src), "birdscream", 50, 0, 5)
else
if(gender == MALE)
playsound(get_turf(src), "malescream", 50, 0, 5)
if(gender == FEMALE)
playsound(get_turf(src), "femscream", 50, 0, 5)
..(act)
if ("shiver","shivers")
message = "<B>[src]</B> shivers."
m_type = 1
if ("shrug","shrugs")
message = "<B>[src]</B> shrugs."
m_type = 1
if ("sigh","sighs")
if(miming)
message = "<B>[src]</B> sighs."
else
..(act)
if ("signal","signals")
if (!src.restrained())
var/t1 = round(text2num(param))
if (isnum(t1))
if (t1 <= 5 && (!src.r_hand || !src.l_hand))
message = "<B>[src]</B> raises [t1] finger\s."
else if (t1 <= 10 && (!src.r_hand && !src.l_hand))
message = "<B>[src]</B> raises [t1] finger\s."
m_type = 1
if ("sneeze","sneezes")
if (miming)
message = "<B>[src]</B> sneezes."
else
..(act)
if ("sniff","sniffs")
message = "<B>[src]</B> sniffs."
m_type = 2
if ("snore","snores")
if (miming)
message = "<B>[src]</B> sleeps soundly."
else
..(act)
if ("whimper","whimpers")
if (miming)
message = "<B>[src]</B> appears hurt."
else
..(act)
if ("yawn","yawns")
if (!muzzled)
message = "<B>[src]</B> yawns."
m_type = 2
if("wag","wags")
if(dna && dna.species && (("tail_lizard" in dna.species.mutant_bodyparts) || ((dna.features["mam_tail"] != "None") && !("mam_waggingtail" in dna.species.mutant_bodyparts)) || ((dna.features["tail_human"] != "None") && !("waggingtail_human" in dna.species.mutant_bodyparts))))
message = "<B>[src]</B> wags \his tail."
startTailWag()
else if(dna && dna.species && (("waggingtail_lizard" in dna.species.mutant_bodyparts) || ("mam_waggingtail" in dna.species.mutant_bodyparts) || ("waggingtail_human" in dna.species.mutant_bodyparts)))
endTailWag()
else
src << "<span class='notice'>Unusable emote '[act]'. Say *help for a list.</span>"
if ("help") //This can stay at the bottom.
if(has_dna(src))
switch(dna.species.id)//Set lists of emotes for specific species. Not the best way to do this, but the easiest considering they'll share most emotes.
if("pred")
src << "Help for yautja emotes. You can use these emotes with say \"*emote\":\n\naflap, airguitar, blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, cry, custom, dance, dap, deathgasp, drool, eyebrow, faint, flap, frown, gasp, giggle, glare-(none)/mob, grin, groan, grumble, handshake, hug-(none)/mob, jump, laugh, look-(none)/mob, me, moan, mumble, nod, pale, point-(atom), raise, <b>roar</b>, salute, scream, shake, shiver, shrug, sigh, signal-#1-10, sit, smile, sneeze, sniff, snore, stare-(none)/mob, sulk, sway, tremble, twitch, twitch_s, wave, whimper, wink, wings, wag, yawn"
else
src << "Help for human emotes. You can use these emotes with say \"*emote\":\n\naflap, airguitar, blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, cry, custom, dance, dap, deathgasp, drool, eyebrow, faint, flap, frown, gasp, giggle, glare-(none)/mob, grin, groan, grumble, handshake, hug-(none)/mob, jump, laugh, look-(none)/mob, me, moan, mumble, nod, pale, point-(atom), raise, salute, scream, shake, shiver, shrug, sigh, signal-#1-10, sit, smile, sneeze, sniff, snore, stare-(none)/mob, sulk, sway, tremble, twitch, twitch_s, wave, whimper, wink, wings, wag, yawn"
/datum/emote/living/carbon/human/wing
key = "wing"
key_third_person = "wings"
message = "their wings."
/datum/emote/living/carbon/human/wing/run_emote(mob/user, params)
. = ..()
if(.)
var/mob/living/carbon/human/H = user
if(findtext(select_message_type(user), "open"))
H.OpenWings()
else
..(act)
if(miming)
m_type = 1
if (message)
log_emote("[name]/[key] : [message]")
//Hearing gasp and such every five seconds is not good emotes were not global for a reason.
// Maybe some people are okay with that.
for(var/mob/M in dead_mob_list)
if(!M.client || istype(M, /mob/new_player))
continue //skip monkeys, leavers and new players
if(M.stat == DEAD && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTSIGHT) && !(M in viewers(src,null)))
M.show_message(message)
if (m_type & 1)
visible_message(message)
else if (m_type & 2)
audible_message(message)
H.CloseWings()
/datum/emote/living/carbon/human/wing/select_message_type(mob/user)
. = ..()
var/mob/living/carbon/human/H = user
if("wings" in H.dna.species.mutant_bodyparts)
. = "opens " + message
else
. = "closes " + message
/datum/emote/living/carbon/human/wing/can_run_emote(mob/user)
if(!..())
return FALSE
var/mob/living/carbon/human/H = user
if(H.dna && H.dna.species && (H.dna.features["wings"] != "None"))
return TRUE
//Don't know where else to put this, it's basically an emote
/mob/living/carbon/human/proc/startTailWag()
@@ -422,9 +134,6 @@
if("tail_human" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "tail_human"
dna.species.mutant_bodyparts |= "waggingtail_human"
if("mam_tail" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "mam_tail"
dna.species.mutant_bodyparts |= "mam_waggingtail"
update_body()
@@ -439,9 +148,6 @@
if("waggingtail_human" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "waggingtail_human"
dna.species.mutant_bodyparts |= "tail_human"
if("mam_waggingtail" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "mam_waggingtail"
dna.species.mutant_bodyparts |= "mam_tail"
update_body()
/mob/living/carbon/human/proc/OpenWings()
@@ -460,9 +166,4 @@
dna.species.mutant_bodyparts |= "wings"
update_body()
/mob/living/carbon/human/verb/set_flavor()
set name = "Set Flavor Text"
set desc = "Sets an extended description of your character's features."
set category = "IC"
flavor_text = copytext(sanitize(input(usr, "Please enter your new flavor text.", "Flavor text", null) as text), 1)
//Ayy lmao
+66 -91
View File
@@ -1,36 +1,17 @@
/mob/living/carbon/human/examine(mob/user)
//this is very slightly better than it was because you can use it more places. still can't do \his[src] though.
var/t_He = p_they(TRUE)
var/t_His = p_their(TRUE)
var/t_his = p_their()
var/t_him = p_them()
var/t_has = p_have()
var/t_is = p_are()
var/msg = "<span class='info'>*---------*\nThis is <EM>[src.name]</EM>!\n"
var/list/obscured = check_obscured_slots()
var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
// crappy hacks because you can't do \his[src] etc. I'm sorry this proc is so unreadable, blame the text macros :<
var/t_He = "It" //capitalised for use at the start of each line.
var/t_his = "its"
var/t_him = "it"
var/t_has = "has"
var/t_is = "is"
var/msg = "<span class='info'>*---------*\nThis is "
if( (slot_w_uniform in obscured) && skipface ) //big suits/masks/helmets make it hard to tell their gender
t_He = "They"
t_his = "their"
t_him = "them"
t_has = "have"
t_is = "are"
else
switch(gender)
if(MALE)
t_He = "He"
t_his = "his"
t_him = "him"
if(FEMALE)
t_He = "She"
t_his = "her"
t_him = "her"
msg += "<EM>[src.name]</EM>!\n"
//uniform
if(w_uniform && !(slot_w_uniform in obscured))
//Ties
@@ -73,19 +54,13 @@
else
msg += "[t_He] [t_has] \icon[back] \a [back] on [t_his] back.\n"
//left hand
if(l_hand && !(l_hand.flags&ABSTRACT))
if(l_hand.blood_DNA)
msg += "<span class='warning'>[t_He] [t_is] holding \icon[l_hand] [l_hand.gender==PLURAL?"some":"a"] blood-stained [l_hand.name] in [t_his] left hand!</span>\n"
else
msg += "[t_He] [t_is] holding \icon[l_hand] \a [l_hand] in [t_his] left hand.\n"
//right hand
if(r_hand && !(r_hand.flags&ABSTRACT))
if(r_hand.blood_DNA)
msg += "<span class='warning'>[t_He] [t_is] holding \icon[r_hand] [r_hand.gender==PLURAL?"some":"a"] blood-stained [r_hand.name] in [t_his] right hand!</span>\n"
else
msg += "[t_He] [t_is] holding \icon[r_hand] \a [r_hand] in [t_his] right hand.\n"
//Hands
for(var/obj/item/I in held_items)
if(!(I.flags & ABSTRACT))
if(I.blood_DNA)
msg += "<span class='warning'>[t_He] [t_is] holding \icon[I] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in [t_his] [get_held_index_name(get_held_index_of_item(I))]!</span>\n"
else
msg += "[t_He] [t_is] holding \icon[I] \a [I] in [t_his] [get_held_index_name(get_held_index_of_item(I))].\n"
//gloves
if(gloves && !(slot_gloves in obscured))
@@ -128,6 +103,9 @@
else
msg += "[t_He] [t_has] \icon[wear_mask] \a [wear_mask] on [t_his] face.\n"
if (wear_neck && !(slot_neck in obscured))
msg += "[t_He] [t_is] wearing \icon[src.wear_neck] \a [src.wear_neck] around [t_his] neck.\n"
//eyes
if(glasses && !(slot_glasses in obscured))
if(glasses.blood_DNA)
@@ -141,16 +119,6 @@
//ID
if(wear_id)
/*var/id
if(istype(wear_id, /obj/item/device/pda))
var/obj/item/device/pda/pda = wear_id
id = pda.owner
else if(istype(wear_id, /obj/item/weapon/card/id)) //just in case something other than a PDA/ID card somehow gets in the ID slot :[
var/obj/item/weapon/card/id/idcard = wear_id
id = idcard.registered_name
if(id && (id != real_name) && (get_dist(src, user) <= 1) && prob(10))
msg += "<span class='warning'>[t_He] [t_is] wearing \icon[wear_id] \a [wear_id] yet something doesn't seem right...</span>\n"
else*/
msg += "[t_He] [t_is] wearing \icon[wear_id] \a [wear_id].\n"
//Jitters
@@ -162,20 +130,14 @@
if(100 to 200)
msg += "<span class='warning'>[t_He] [t_is] twitching ever so slightly.</span>\n"
if(gender_ambiguous) //someone fucked up a gender reassignment surgery
if (gender == MALE)
msg += "[t_He] has a strange feminine quality to [t_him].\n"
else
msg += "[t_He] has a strange masculine quality to [t_him].\n"
var/appears_dead = 0
if(stat == DEAD || (status_flags & FAKEDEATH))
appears_dead = 1
if(getorgan(/obj/item/organ/brain))//Only perform these checks if there is no brain
if(suiciding)
msg += "<span class='warning'>[t_He] appears to have commited suicide... there is no hope of recovery.</span>\n"
msg += "<span class='warning'>[t_He] appear[p_s()] to have commited suicide... there is no hope of recovery.</span>\n"
if(hellbound)
msg += "<span class='warning'>[t_his] soul seems to have been ripped out of [t_his] body. Revival is impossible.</span>\n"
msg += "<span class='warning'>[t_His] soul seems to have been ripped out of [t_his] body. Revival is impossible.</span>\n"
msg += "<span class='deadsay'>[t_He] [t_is] limp and unresponsive; there are no signs of life"
if(!key)
var/foundghost = 0
@@ -203,12 +165,27 @@
for(var/obj/item/I in BP.embedded_objects)
msg += "<B>[t_He] [t_has] \a \icon[I] [I] embedded in [t_his] [BP.name]!</B>\n"
//stores missing limbs
var/l_limbs_missing = 0
var/r_limbs_missing = 0
for(var/t in missing)
if(t=="head")
msg += "<span class='deadsay'><B>[capitalize(t_his)] [parse_zone(t)] is missing!</B><span class='warning'>\n"
msg += "<span class='deadsay'><B>[t_His] [parse_zone(t)] is missing!</B><span class='warning'>\n"
continue
if(t == "l_arm" || t == "l_leg")
l_limbs_missing++
else if(t == "r_arm" || t == "r_leg")
r_limbs_missing++
msg += "<B>[capitalize(t_his)] [parse_zone(t)] is missing!</B>\n"
if(l_limbs_missing >= 2 && r_limbs_missing == 0)
msg += "[t_He] looks all right now.\n"
else if(l_limbs_missing == 0 && r_limbs_missing >= 2)
msg += "[t_He] really keeps to the left.\n"
else if(l_limbs_missing >= 2 && r_limbs_missing >= 2)
msg += "[t_He] doesn't seem all there.\n"
if(temp)
if(temp < 30)
msg += "[t_He] [t_has] minor bruising.\n"
@@ -246,28 +223,13 @@
msg += "[t_He] [t_is] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n"
else
msg += "[t_He] [t_is] quite chubby.\n"
/*
if( (vore_womb_datum.has_people()||vore_stomach_datum.has_people()) && !(slot_w_uniform in obscured) )
msg += "It seems [t_his] belly is shifting around slighty.\n"
if( (vore_breast_datum.has_people()||vore_breast_datum.digestion_count) && !(slot_w_uniform in obscured) )
msg += "It seems [t_his] breasts are heavy with milk.\n"
if( !(slot_w_uniform in obscured) && (!w_uniform||!(w_uniform.body_parts_covered&GROIN)) )
if(vore_cock_datum.has_people()||vore_cock_datum.digestion_count)
msg += "It looks like [t_his] cock is full.\n"
if(vore_balls_datum.has_people()||vore_balls_datum.digestion_count)
msg += "It looks like [t_his] balls are full.\n"
if(vore_tail_datum.has_people())
msg += "[t_He] has a bulge in [t_his] tail."
if(vore_tail_datum.transfer_factor)
msg += " It moves slowly toward the base."
msg += "\n"
*/
if(blood_volume < BLOOD_VOLUME_SAFE)
msg += "[t_He] [t_has] pale skin.\n"
if(bleedsuppress)
msg += "[t_He] [t_is] bandaged with something.\n"
if(bleed_rate)
else if(bleed_rate)
if(reagents.has_reagent("heparin"))
msg += "<b>[t_He] [t_is] bleeding uncontrollably!</b>\n"
else
@@ -276,10 +238,12 @@
if(reagents.has_reagent("teslium"))
msg += "[t_He] is emitting a gentle blue glow!\n"
if(stun_absorption)
msg += "[t_He] is radiating with a soft yellow light!\n" //Used by Vanguard
if(islist(stun_absorption))
for(var/i in stun_absorption)
if(stun_absorption[i]["end_time"] > world.time && stun_absorption[i]["examine_message"])
msg += "[t_He] [t_is][stun_absorption[i]["examine_message"]]\n"
if(drunkenness && !skipface && stat != DEAD) //Drunkenness
if(drunkenness && !skipface && !appears_dead) //Drunkenness
switch(drunkenness)
if(11 to 21)
msg += "[t_He] [t_is] slightly flushed.\n"
@@ -292,7 +256,11 @@
if(61.01 to 91)
msg += "[t_He] looks like a drunken mess.\n"
if(91.01 to INFINITY)
msg += "[t_He] is a shitfaced, slobbering wreck.\n"
msg += "[t_He] [t_is] a shitfaced, slobbering wreck.\n"
for (var/I in src.vore_organs)
var/datum/belly/B = vore_organs[I]
msg += B.get_examine_msg()
msg += "</span>"
@@ -304,7 +272,13 @@
if(getorgan(/obj/item/organ/brain))
if(istype(src,/mob/living/carbon/human/interactive))
msg += "<span class='deadsay'>[t_He] [t_is] appears to be some sort of sick automaton, [t_his] eyes are glazed over and [t_his] mouth is slightly agape.</span>\n"
var/mob/living/carbon/human/interactive/auto = src
if(auto.showexaminetext)
msg += "<span class='deadsay'>[t_He] [t_is] appears to be some sort of sick automaton, [t_his] eyes are glazed over and [t_his] mouth is slightly agape.</span>\n"
if(auto.debugexamine)
var/dodebug = auto.doing2string(auto.doing)
var/interestdebug = auto.interest2string(auto.interest)
msg += "<span class='deadsay'>[t_He] [t_is] appears to be [interestdebug] and [dodebug].</span>\n"
else if(!key)
msg += "<span class='deadsay'>[t_He] [t_is] totally catatonic. The stresses of life in deep-space must have been too much for [t_him]. Any recovery is unlikely.</span>\n"
else if(!client)
@@ -313,7 +287,7 @@
if(digitalcamo)
msg += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly inhuman manner.\n"
if(istype(user, /mob/living/carbon/human))
if(ishuman(user))
var/mob/living/carbon/human/H = user
var/obj/item/organ/cyberimp/eyes/hud/CIH = H.getorgan(/obj/item/organ/cyberimp/eyes/hud)
if(istype(H.glasses, /obj/item/clothing/glasses/hud) || CIH)
@@ -325,18 +299,18 @@
msg += "<a href='?src=\ref[src];hud=1;photo_front=1'>\[Front photo\]</a> "
msg += "<a href='?src=\ref[src];hud=1;photo_side=1'>\[Side photo\]</a><br>"
if(istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(CIH,/obj/item/organ/cyberimp/eyes/hud/medical))
var/implant_detect
var/cyberimp_detect
for(var/obj/item/organ/cyberimp/CI in internal_organs)
if(CI.status == ORGAN_ROBOTIC)
implant_detect += "[name] is modified with a [CI.name].<br>"
if(implant_detect)
cyberimp_detect += "[name] is modified with a [CI.name].<br>"
if(cyberimp_detect)
msg += "Detected cybernetic modifications:<br>"
msg += implant_detect
msg += cyberimp_detect
if(R)
var/health = R.fields["p_stat"]
msg += "<a href='?src=\ref[src];hud=m;p_stat=1'>\[[health]\]</a>"
health = R.fields["m_stat"]
msg += "<a href='?src=\ref[src];hud=m;m_stat=1'>\[[health]\]</a><br>"
var/health_r = R.fields["p_stat"]
msg += "<a href='?src=\ref[src];hud=m;p_stat=1'>\[[health_r]\]</a>"
health_r = R.fields["m_stat"]
msg += "<a href='?src=\ref[src];hud=m;m_stat=1'>\[[health_r]\]</a><br>"
R = find_record("name", perpname, data_core.medical)
if(R)
msg += "<a href='?src=\ref[src];hud=m;evaluation=1'>\[Medical evaluation\]</a><br>"
@@ -357,6 +331,7 @@
msg += "<a href='?src=\ref[src];hud=s;view_comment=1'>\[View comment log\]</a> "
msg += "<a href='?src=\ref[src];hud=s;add_comment=1'>\[Add comment\]</a>\n"
if(print_flavor_text() && get_visible_name() != "Unknown")//Are we sure we know who this is? Don't show flavor text unless we can recognize them. Prevents certain metagaming with impersonation.
msg += "[print_flavor_text()]\n"
+127 -304
View File
@@ -3,7 +3,7 @@
real_name = "Unknown"
voice_name = "Unknown"
icon = 'icons/mob/human.dmi'
icon_state = "caucasian1_m_s"
icon_state = "caucasian_m"
@@ -18,11 +18,7 @@
verbs += /mob/living/proc/lay_down
//initialize limbs first
bodyparts = newlist(/obj/item/bodypart/chest, /obj/item/bodypart/head, /obj/item/bodypart/l_arm,
/obj/item/bodypart/r_arm, /obj/item/bodypart/r_leg, /obj/item/bodypart/l_leg)
for(var/X in bodyparts)
var/obj/item/bodypart/O = X
O.owner = src
create_bodyparts()
//initialize dna. for spawned humans; overwritten by other code
create_dna(src)
@@ -33,21 +29,7 @@
set_species(dna.species.type)
//initialise organs
if(!(NOHUNGER in dna.species.specflags))
internal_organs += new /obj/item/organ/appendix
if(!(NOBREATH in dna.species.specflags))
internal_organs += new /obj/item/organ/lungs
if(!(NOBLOOD in dna.species.specflags))
internal_organs += new /obj/item/organ/heart
internal_organs += new /obj/item/organ/brain
//Note: Additional organs are generated/replaced on the dna.species level
for(var/obj/item/organ/I in internal_organs)
I.Insert(src)
create_internal_organs()
martial_art = default_martial_art
@@ -55,6 +37,19 @@
..()
/mob/living/carbon/human/create_internal_organs()
if(!(NOHUNGER in dna.species.species_traits))
internal_organs += new /obj/item/organ/appendix
if(!(NOBREATH in dna.species.species_traits))
if(dna.species.mutantlungs)
internal_organs += new dna.species.mutantlungs()
else
internal_organs += new /obj/item/organ/lungs()
if(!(NOBLOOD in dna.species.species_traits))
internal_organs += new /obj/item/organ/heart
internal_organs += new /obj/item/organ/brain
..()
/mob/living/carbon/human/OpenCraftingMenu()
handcrafting.ui_interact(src)
@@ -81,6 +76,11 @@
stat("Internal Atmosphere Info", internal.name)
stat("Tank Pressure", internal.air_contents.return_pressure())
stat("Distribution Pressure", internal.distribute_pressure)
var/mob/living/simple_animal/borer/B = has_brain_worms()
if(B && B.controlling)
stat("Chemicals", B.chemicals)
if(mind)
if(mind.changeling)
stat("Chemical Storage", "[mind.changeling.chem_charges]/[mind.changeling.chem_storage]")
@@ -116,94 +116,17 @@
stat("*", "[D.name], Type: [D.spread_text], Stage: [D.stage]/[D.max_stages], Possible Cure: [D.cure_text]")
/mob/living/carbon/human/ex_act(severity, ex_target)
var/b_loss = null
var/f_loss = null
var/bomb_armor = getarmor(null, "bomb")
switch (severity)
if (1)
b_loss += 500
if (prob(bomb_armor))
shred_clothing(1,150)
var/atom/target = get_edge_target_turf(src, get_dir(src, get_step_away(src, src)))
throw_at(target, 200, 4)
else
gib()
return
if (2)
b_loss += 60
f_loss += 60
if (prob(bomb_armor))
b_loss = b_loss/1.5
f_loss = f_loss/1.5
shred_clothing(1,25)
else
shred_clothing(1,50)
if (!istype(ears, /obj/item/clothing/ears/earmuffs))
adjustEarDamage(30, 120)
if (prob(70))
Paralyse(10)
if(3)
b_loss += 30
if (prob(bomb_armor))
b_loss = b_loss/2
if (!istype(ears, /obj/item/clothing/ears/earmuffs))
adjustEarDamage(15,60)
if (prob(50))
Paralyse(10)
take_overall_damage(b_loss,f_loss)
//attempt to dismember bodyparts
if(severity <= 2 || !bomb_armor)
var/max_limb_loss = round(4/severity) //so you don't lose four limbs at severity 3.
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(prob(50/severity) && !prob(getarmor(BP, "bomb")) && BP.body_zone != "head" && BP.body_zone != "chest")
BP.brute_dam = BP.max_damage
BP.dismember()
max_limb_loss--
if(!max_limb_loss)
break
..()
/mob/living/carbon/human/blob_act(obj/effect/blob/B)
if(stat == DEAD)
return
show_message("<span class='userdanger'>The blob attacks you!</span>")
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
apply_damage(5, BRUTE, affecting, run_armor_check(affecting, "melee"))
return
/mob/living/carbon/human/bullet_act()
if(martial_art && martial_art.deflection_chance) //Some martial arts users can deflect projectiles!
if(!prob(martial_art.deflection_chance))
return ..()
if(!src.lying && dna && !dna.check_mutation(HULK)) //But only if they're not lying down, and hulks can't do it
src.visible_message("<span class='danger'>[src] deflects the projectile; they can't be hit with ranged weapons!</span>", "<span class='userdanger'>You deflect the projectile!</span>")
playsound(src, pick("sound/weapons/bulletflyby.ogg","sound/weapons/bulletflyby2.ogg","sound/weapons/bulletflyby3.ogg"), 75, 1)
return 0
..()
/mob/living/carbon/human/attack_ui(slot)
if(!get_bodypart(hand ? "l_arm" : "r_arm"))
return 0
return ..()
/mob/living/carbon/human/show_inv(mob/user)
user.set_machine(src)
var/has_breathable_mask = istype(wear_mask, /obj/item/clothing/mask)
var/list/obscured = check_obscured_slots()
var/list/dat = list()
var/dat = {"<table>
<tr><td><B>Left Hand:</B></td><td><A href='?src=\ref[src];item=[slot_l_hand]'>[(l_hand && !(l_hand.flags&ABSTRACT)) ? l_hand : "<font color=grey>Empty</font>"]</A></td></tr>
<tr><td><B>Right Hand:</B></td><td><A href='?src=\ref[src];item=[slot_r_hand]'>[(r_hand && !(r_hand.flags&ABSTRACT)) ? r_hand : "<font color=grey>Empty</font>"]</A></td></tr>
<tr><td>&nbsp;</td></tr>"}
dat += "<table>"
for(var/i in 1 to held_items.len)
var/obj/item/I = get_item_for_held_index(i)
dat += "<tr><td><B>[get_held_index_name(i)]:</B></td><td><A href='?src=\ref[src];item=[slot_hands];hand_index=[i]'>[(I && !(I.flags & ABSTRACT)) ? I : "<font color=grey>Empty</font>"]</a></td></tr>"
dat += "<tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Back:</B></td><td><A href='?src=\ref[src];item=[slot_back]'>[(back && !(back.flags&ABSTRACT)) ? back : "<font color=grey>Empty</font>"]</A>"
if(has_breathable_mask && istype(back, /obj/item/weapon/tank))
@@ -218,6 +141,11 @@
else
dat += "<tr><td><B>Mask:</B></td><td><A href='?src=\ref[src];item=[slot_wear_mask]'>[(wear_mask && !(wear_mask.flags&ABSTRACT)) ? wear_mask : "<font color=grey>Empty</font>"]</A></td></tr>"
if(slot_neck in obscured)
dat += "<tr><td><font color=grey><B>Neck:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Neck:</B></td><td><A href='?src=\ref[src];item=[slot_neck]'>[(wear_neck && !(wear_neck.flags&ABSTRACT)) ? wear_neck : "<font color=grey>Empty</font>"]</A></td></tr>"
if(slot_glasses in obscured)
dat += "<tr><td><font color=grey><B>Eyes:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
@@ -277,7 +205,7 @@
"}
var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 440, 510)
popup.set_content(dat)
popup.set_content(dat.Join())
popup.open()
// called when something steps onto a human
@@ -289,35 +217,6 @@
spreadFire(AM)
//Added a safety check in case you want to shock a human mob directly through electrocute_act.
/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0)
if(tesla_shock)
var/total_coeff = 1
if(gloves)
var/obj/item/clothing/gloves/G = gloves
if(G.siemens_coefficient <= 0)
total_coeff -= 0.5
if(wear_suit)
var/obj/item/clothing/suit/S = wear_suit
if(S.siemens_coefficient <= 0)
total_coeff -= 0.95
siemens_coeff = total_coeff
else if(!safety)
var/gloves_siemens_coeff = 1
if(gloves)
var/obj/item/clothing/gloves/G = gloves
gloves_siemens_coeff = G.siemens_coefficient
siemens_coeff = gloves_siemens_coeff
if(heart_attack)
if(shock_damage * siemens_coeff >= 1 && prob(25))
heart_attack = 0
if(stat == CONSCIOUS)
src << "<span class='notice'>You feel your heart beating again!</span>"
. = ..(shock_damage,source,siemens_coeff,safety,override,tesla_shock)
if(.)
electrocution_animation(40)
/mob/living/carbon/human/Topic(href, href_list)
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
@@ -333,8 +232,8 @@
if(!I || !L || I.loc != src || !(I in L.embedded_objects))
return
L.embedded_objects -= I
L.take_damage(I.embedded_unsafe_removal_pain_multiplier*I.w_class)//It hurts to rip it out, get surgery you dingus.
I.loc = get_turf(src)
L.receive_damage(I.embedded_unsafe_removal_pain_multiplier*I.w_class)//It hurts to rip it out, get surgery you dingus.
I.forceMove(get_turf(src))
usr.put_in_hands(I)
usr.emote("scream")
usr.visible_message("[usr] successfully rips [I] out of their [L.name]!","<span class='notice'>You successfully remove [I] from your [L.name].</span>")
@@ -352,14 +251,14 @@
var/pocket_side = href_list["pockets"]
var/pocket_id = (pocket_side == "right" ? slot_r_store : slot_l_store)
var/obj/item/pocket_item = (pocket_id == slot_r_store ? r_store : l_store)
var/obj/item/place_item = usr.get_active_hand() // Item to place in the pocket, if it's empty
var/obj/item/place_item = usr.get_active_held_item() // Item to place in the pocket, if it's empty
var/delay_denominator = 1
if(pocket_item && !(pocket_item.flags&ABSTRACT))
if(pocket_item.flags & NODROP)
usr << "<span class='warning'>You try to empty [src]'s [pocket_side] pocket, it seems to be stuck!</span>"
usr << "<span class='notice'>You try to empty [src]'s [pocket_side] pocket.</span>"
else if(place_item && place_item.mob_can_equip(src, pocket_id, 1) && !(place_item.flags&ABSTRACT))
else if(place_item && place_item.mob_can_equip(src, usr, pocket_id, 1) && !(place_item.flags&ABSTRACT))
usr << "<span class='notice'>You try to place [place_item] into [src]'s [pocket_side] pocket.</span>"
delay_denominator = 4
else
@@ -368,11 +267,13 @@
if(do_mob(usr, src, POCKET_STRIP_DELAY/delay_denominator)) //placing an item into the pocket is 4 times faster
if(pocket_item)
if(pocket_item == (pocket_id == slot_r_store ? r_store : l_store)) //item still in the pocket we search
unEquip(pocket_item)
dropItemToGround(pocket_item)
else
if(place_item)
usr.unEquip(place_item)
equip_to_slot_if_possible(place_item, pocket_id, 0, 1)
if(place_item.mob_can_equip(src, usr, pocket_id, FALSE, TRUE))
usr.temporarilyRemoveItemFromInventory(place_item, TRUE)
equip_to_slot(place_item, pocket_id, TRUE)
//do nothing otherwise
// Update strip window
if(usr.machine == src && in_range(src, usr))
@@ -381,23 +282,21 @@
// Display a warning if the user mocks up
src << "<span class='warning'>You feel your [pocket_side] pocket being fumbled with!</span>"
..()
else
..()
..()
///////HUDs///////
if(href_list["hud"])
if(istype(usr, /mob/living/carbon/human))
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
var/perpname = get_face_name(get_id_name(""))
if(istype(H.glasses, /obj/item/clothing/glasses/hud))
if(istype(H.glasses, /obj/item/clothing/glasses/hud) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud))
var/datum/data/record/R = find_record("name", perpname, data_core.general)
if(href_list["photo_front"] || href_list["photo_side"])
if(R)
if(!H.canUseHUD())
return
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud))
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical))
return
var/obj/item/weapon/photo/P = null
if(href_list["photo_front"])
@@ -408,26 +307,26 @@
P.show(H)
if(href_list["hud"] == "m")
if(istype(H.glasses, /obj/item/clothing/glasses/hud/health))
if(istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical))
if(href_list["p_stat"])
var/health = input(usr, "Specify a new physical status for this person.", "Medical HUD", R.fields["p_stat"]) in list("Active", "Physically Unfit", "*Unconscious*", "*Deceased*", "Cancel")
var/health_status = input(usr, "Specify a new physical status for this person.", "Medical HUD", R.fields["p_stat"]) in list("Active", "Physically Unfit", "*Unconscious*", "*Deceased*", "Cancel")
if(R)
if(!H.canUseHUD())
return
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/health))
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/health) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical))
return
if(health && health != "Cancel")
R.fields["p_stat"] = health
if(health_status && health_status != "Cancel")
R.fields["p_stat"] = health_status
return
if(href_list["m_stat"])
var/health = input(usr, "Specify a new mental status for this person.", "Medical HUD", R.fields["m_stat"]) in list("Stable", "*Watch*", "*Unstable*", "*Insane*", "Cancel")
var/health_status = input(usr, "Specify a new mental status for this person.", "Medical HUD", R.fields["m_stat"]) in list("Stable", "*Watch*", "*Unstable*", "*Insane*", "Cancel")
if(R)
if(!H.canUseHUD())
return
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/health))
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/health) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical))
return
if(health && health != "Cancel")
R.fields["m_stat"] = health
if(health_status && health_status != "Cancel")
R.fields["m_stat"] = health_status
return
if(href_list["evaluation"])
if(!getBruteLoss() && !getFireLoss() && !getOxyLoss() && getToxLoss() < 20)
@@ -473,7 +372,7 @@
usr << "<span class='danger'>Gathered data is inconsistent with the analysis, possible cause: poisoning.</span>"
if(href_list["hud"] == "s")
if(istype(H.glasses, /obj/item/clothing/glasses/hud/security))
if(istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
if(usr.stat || usr == src) //|| !usr.canmove || usr.restrained()) Fluff: Sechuds have eye-tracking technology and sets 'arrest' to people that the wearer looks and blinks at.
return //Non-fluff: This allows sec to set people to arrest as they get disarmed or beaten
// Checks the user has security clearence before allowing them to change arrest status via hud, comment out to enable all access
@@ -500,7 +399,7 @@
if(setcriminal != "Cancel")
if(R)
if(H.canUseHUD())
if(istype(H.glasses, /obj/item/clothing/glasses/hud/security))
if(istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
investigate_log("[src.key] has been set from [R.fields["criminal"]] to [setcriminal] by [usr.name] ([usr.key]).", "records")
R.fields["criminal"] = setcriminal
sec_hud_set_security_status()
@@ -510,7 +409,7 @@
if(R)
if(!H.canUseHUD())
return
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security))
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
return
usr << "<b>Name:</b> [R.fields["name"]] <b>Criminal Status:</b> [R.fields["criminal"]]"
usr << "<b>Minor Crimes:</b>"
@@ -539,7 +438,7 @@
return
else if(!H.canUseHUD())
return
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security))
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
return
var/crime = data_core.createCrimeEntry(t1, t2, allowed_access, worldtime2text())
data_core.addMinorCrime(R.fields["id"], crime)
@@ -554,7 +453,7 @@
return
else if (!H.canUseHUD())
return
else if (!istype(H.glasses, /obj/item/clothing/glasses/hud/security))
else if (!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
return
var/crime = data_core.createCrimeEntry(t1, t2, allowed_access, worldtime2text())
data_core.addMajorCrime(R.fields["id"], crime)
@@ -565,7 +464,7 @@
if(R)
if(!H.canUseHUD())
return
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security))
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
return
usr << "<b>Comments/Log:</b>"
var/counter = 1
@@ -583,12 +482,12 @@
return
else if(!H.canUseHUD())
return
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security))
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
return
var/counter = 1
while(R.fields[text("com_[]", counter)])
counter++
R.fields[text("com_[]", counter)] = text("Made by [] on [] [], []<BR>[]", allowed_access, worldtime2text(), time2text(world.realtime, "MMM DD"), year_integer+540, t1,)
R.fields[text("com_[]", counter)] = text("Made by [] on [] [], []<BR>[]", allowed_access, worldtime2text(), time2text(world.realtime, "MMM DD"), year_integer+540, t1)
usr << "<span class='notice'>Successfully added comment.</span>"
return
usr << "<span class='warning'>Unable to locate a data core entry for this person.</span>"
@@ -600,7 +499,7 @@
. = 1 // Default to returning true.
if(user && !target_zone)
target_zone = user.zone_selected
if(dna && (PIERCEIMMUNE in dna.species.specflags))
if(dna && (PIERCEIMMUNE in dna.species.species_traits))
. = 0
// If targeting the head, see if the head item is thin enough.
// If targeting anything else, see if the wear suit is thin enough.
@@ -612,7 +511,7 @@
. = 0
if(!. && error_msg && user)
// Might need re-wording.
user << "<span class='alert'>There is no exposed flesh or thin material [above_neck(target_zone) ? "on their head" : "on their body"].</span>"
user << "<span class='alert'>There is no exposed flesh or thin material [above_neck(target_zone) ? "on [p_their()] head" : "on [p_their()] body"].</span>"
/mob/living/carbon/human/proc/check_obscured_slots()
var/list/obscured = list()
@@ -637,7 +536,7 @@
if(wear_mask.flags_inv & HIDEEYES)
obscured |= slot_glasses
if(obscured.len > 0)
if(obscured.len)
return obscured
else
return null
@@ -653,7 +552,7 @@
if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve
if(istype(wear_suit, /obj/item/clothing/suit/redtag))
threatcount += 4
if((istype(r_hand,/obj/item/weapon/gun/energy/laser/redtag)) || (istype(l_hand,/obj/item/weapon/gun/energy/laser/redtag)))
if(is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/redtag))
threatcount += 4
if(istype(belt, /obj/item/weapon/gun/energy/laser/redtag))
threatcount += 2
@@ -661,7 +560,7 @@
if(lasercolor == "r")
if(istype(wear_suit, /obj/item/clothing/suit/bluetag))
threatcount += 4
if((istype(r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(l_hand,/obj/item/weapon/gun/energy/laser/bluetag)))
if(is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/bluetag))
threatcount += 4
if(istype(belt, /obj/item/weapon/gun/energy/laser/bluetag))
threatcount += 2
@@ -676,10 +575,9 @@
//Check for weapons
if(judgebot.weaponscheck)
if(!idcard || !(access_weapons in idcard.access))
if(judgebot.check_for_weapons(l_hand))
threatcount += 4
if(judgebot.check_for_weapons(r_hand))
threatcount += 4
for(var/obj/item/I in held_items)
if(judgebot.check_for_weapons(I))
threatcount += 4
if(judgebot.check_for_weapons(belt))
threatcount += 2
@@ -697,23 +595,22 @@
threatcount += 2
//Check for dresscode violations
if(istype(head, /obj/item/clothing/head/wizard) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/wizard) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/syndi) || istype(head, /obj/item/clothing/head/helmet/space/syndicate) || istype(head, /obj/item/clothing/head/culthood))
threatcount += 5
if(istype(head, /obj/item/clothing/head/wizard) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/wizard))
threatcount += 2
//Check for nonhuman scum
if(dna && dna.species.id && dna.species.id != "human")
threatcount += 0
threatcount += 1
//Loyalty implants imply trustworthyness
if(isloyal(src))
//mindshield implants imply trustworthyness
if(isloyal())
threatcount -= 1
//Agent cards lower threatlevel, but only just enough to avoid dresscode violations.
//Agent cards lower threatlevel.
if(istype(idcard, /obj/item/weapon/card/id/syndicate))
threatcount -= 2
threatcount -= 5
return threatcount
return threatcount
//Used for new human mobs created by cloning/goleming/podding
@@ -727,22 +624,10 @@
update_body()
update_hair()
/mob/living/carbon/human/singularity_act()
var/gain = 20
if(mind)
if((mind.assigned_role == "Station Engineer") || (mind.assigned_role == "Chief Engineer") )
gain = 100
if(mind.assigned_role == "Clown")
gain = rand(-300, 300)
investigate_log("([key_name(src)]) has been consumed by the singularity.","singulo") //Oh that's where the clown ended up!
gib()
return(gain)
/mob/living/carbon/human/singularity_pull(S, current_size)
if(current_size >= STAGE_THREE)
var/list/handlist = list(l_hand, r_hand)
for(var/obj/item/hand in handlist)
if(prob(current_size * 5) && hand.w_class >= ((11-current_size)/2) && unEquip(hand))
for(var/obj/item/hand in held_items)
if(prob(current_size * 5) && hand.w_class >= ((11-current_size)/2) && dropItemToGround(hand))
step_towards(hand, src)
src << "<span class='warning'>\The [S] pulls \the [hand] from your grip!</span>"
rad_act(current_size * 3)
@@ -750,71 +635,6 @@
return
..()
/mob/living/carbon/human/help_shake_act(mob/living/carbon/M)
if(!istype(M))
return
if(health >= 0)
if(src == M)
visible_message( \
"[src] examines \himself.", \
"<span class='notice'>You check yourself for injuries.</span>")
var/list/missing = list("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg")
for(var/X in bodyparts)
var/obj/item/bodypart/LB = X
missing -= LB.body_zone
var/status = ""
var/brutedamage = LB.brute_dam
var/burndamage = LB.burn_dam
if(hallucination)
if(prob(30))
brutedamage += rand(30,40)
if(prob(30))
burndamage += rand(30,40)
if(brutedamage > 0)
status = "bruised"
if(brutedamage > 20)
status = "battered"
if(brutedamage > 40)
status = "mangled"
if(brutedamage > 0 && burndamage > 0)
status += " and "
if(burndamage > 40)
status += "peeling away"
else if(burndamage > 10)
status += "blistered"
else if(burndamage > 0)
status += "numb"
if(status == "")
status = "OK"
src << "\t [status == "OK" ? "\blue" : "\red"] Your [LB.name] is [status]."
for(var/obj/item/I in LB.embedded_objects)
src << "\t <a href='byond://?src=\ref[src];embedded_object=\ref[I];embedded_limb=\ref[LB]'>\red There is \a [I] embedded in your [LB.name]!</a>"
for(var/t in missing)
src << "<span class='boldannounce'>Your [parse_zone(t)] is missing!</span>"
if(bleed_rate)
src << "<span class='danger'>You are bleeding!</span>"
if(staminaloss)
if(staminaloss > 30)
src << "<span class='info'>You're completely exhausted.</span>"
else
src << "<span class='info'>You feel fatigued.</span>"
else
if(wear_suit)
wear_suit.add_fingerprint(M)
else if(w_uniform)
w_uniform.add_fingerprint(M)
..()
/mob/living/carbon/human/proc/do_cpr(mob/living/carbon/C)
CHECK_DNA_AND_SPECIES(C)
@@ -825,7 +645,7 @@
src << "<span class='warning'>Remove your mask first!</span>"
return 0
if(C.is_mouth_covered())
src << "<span class='warning'>Remove their mask first!</span>"
src << "<span class='warning'>Remove [p_their()] mask first!</span>"
return 0
if(C.cpr_time < world.time + 30)
@@ -835,10 +655,10 @@
src << "<span class='warning'>You fail to perform CPR on [C]!</span>"
return 0
var/they_breathe = (!(NOBREATH in C.dna.species.specflags))
var/they_breathe = (!(NOBREATH in C.dna.species.species_traits))
var/they_lung = C.getorganslot("lungs")
if(C.health > config.health_threshold_crit)
if(C.health > HEALTH_THRESHOLD_CRIT)
return
src.visible_message("[src] performs CPR on [C.name]!", "<span class='notice'>You perform CPR on [C.name].</span>")
@@ -878,10 +698,10 @@
if(dna && dna.check_mutation(HULK))
say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ))
if(..(I, cuff_break = FAST_CUFFBREAK))
unEquip(I)
dropItemToGround(I)
else
if(..())
unEquip(I)
dropItemToGround(I)
/mob/living/carbon/human/clean_blood()
var/mob/living/carbon/human/H = src
@@ -907,17 +727,18 @@
/mob/living/carbon/human/proc/electrocution_animation(anim_duration)
//Handle mutant parts if possible
if(dna && dna.species)
add_overlay("electrocuted_base")
spawn(anim_duration)
if(src)
overlays -= "electrocuted_base"
add_atom_colour("#000000", TEMPORARY_COLOUR_PRIORITY)
var/static/image/electrocution_skeleton_anim = image(icon = icon, icon_state = "electrocuted_base")
electrocution_skeleton_anim.appearance_flags = RESET_COLOR
add_overlay(electrocution_skeleton_anim)
addtimer(CALLBACK(src, .proc/end_electrocution_animation, electrocution_skeleton_anim), anim_duration)
else //or just do a generic animation
var/list/viewing = list()
for(var/mob/M in viewers(src))
if(M.client)
viewing += M.client
flick_overlay(image(icon,src,"electrocuted_generic",ABOVE_MOB_LAYER), viewing, anim_duration)
flick_overlay_view(image(icon,src,"electrocuted_generic",ABOVE_MOB_LAYER), src, anim_duration)
/mob/living/carbon/human/proc/end_electrocution_animation(image/I)
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#000000")
overlays -= I
/mob/living/carbon/human/canUseTopic(atom/movable/M, be_close = 0)
if(incapacitated() || lying )
@@ -1004,32 +825,9 @@
hud_used.healthdoll.icon_state = "healthdoll_DEAD"
/mob/living/carbon/human/fully_heal(admin_revive = 0)
CHECK_DNA_AND_SPECIES(src)
if(admin_revive)
regenerate_limbs()
if(!(NOBREATH in dna.species.specflags) && !getorganslot("lungs"))
var/obj/item/organ/lungs/L = new()
L.Insert(src)
if(!(NOBLOOD in dna.species.specflags) && !getorganslot("heart"))
var/obj/item/organ/heart/H = new()
H.Insert(src)
if(!getorganslot("tongue"))
var/obj/item/organ/tongue/T
for(var/tongue_type in dna.species.mutant_organs)
if(ispath(tongue_type, /obj/item/organ/tongue))
T = new tongue_type()
T.Insert(src)
// if they have no mutant tongues, give them a regular one
if(!T)
T = new()
T.Insert(src)
regenerate_organs()
remove_all_embedded_objects()
drunkenness = 0
for(var/datum/mutation/human/HM in dna.mutations)
@@ -1063,12 +861,7 @@
O = new /datum/objective/sintouched/pride
ticker.mode.sintouched += src.mind
src.mind.objectives += O
var/obj_count = 1
src << "<span class='notice'>Your current objectives:</span>"
for(O in src.mind.objectives)
var/datum/objective/objective = O
src << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
obj_count++
src.mind.announce_objectives()
/mob/living/carbon/human/check_weakness(obj/item/weapon, mob/living/attacker)
. = ..()
@@ -1078,6 +871,36 @@
/mob/living/carbon/human/is_literate()
return 1
/mob/living/carbon/human/can_hold_items()
return TRUE
/mob/living/carbon/human/update_gravity(has_gravity,override = 0)
override = dna.species.override_float
..()
/mob/living/carbon/human/vomit(lost_nutrition = 10, blood = 0, stun = 1, distance = 0, message = 1, toxic = 0)
if(blood && (NOBLOOD in dna.species.species_traits))
if(message)
visible_message("<span class='warning'>[src] dry heaves!</span>", \
"<span class='userdanger'>You try to throw up, but there's nothing in your stomach!</span>")
if(stun)
Weaken(10)
return 1
..()
/mob/living/carbon/human/Bump(atom/A)
..()
var/crashdir = get_dir(src, A)
var/obj/item/device/flightpack/FP = get_flightpack()
if(FP)
FP.flight_impact(A, crashdir)
/mob/living/carbon/human/vv_get_dropdown()
. = ..()
. += "---"
.["Make monkey"] = "?_src_=vars;makemonkey=\ref[src]"
.["Set Species"] = "?_src_=vars;setspecies=\ref[src]"
.["Make cyborg"] = "?_src_=vars;makerobot=\ref[src]"
.["Make alien"] = "?_src_=vars;makealien=\ref[src]"
.["Make slime"] = "?_src_=vars;makeslime=\ref[src]"
.["Toggle Purrbation"] = "?_src_=vars;purrbation=\ref[src]"
@@ -1,49 +0,0 @@
/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M)
if(check_shields(0, M.name))
visible_message("<span class='danger'>[M] attempted to touch [src]!</span>")
return 0
if(..())
if(M.a_intent == "harm")
if (w_uniform)
w_uniform.add_fingerprint(M)
var/damage = prob(90) ? 20 : 0
if(!damage)
playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] has lunged at [src]!</span>", \
"<span class='userdanger'>[M] has lunged at [src]!</span>")
return 0
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
var/armor_block = run_armor_check(affecting, "melee","","",10)
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
"<span class='userdanger'>[M] has slashed at [src]!</span>")
apply_damage(damage, BRUTE, affecting, armor_block)
if (prob(30))
visible_message("<span class='danger'>[M] has wounded [src]!</span>", \
"<span class='userdanger'>[M] has wounded [src]!</span>")
apply_effect(4, WEAKEN, armor_block)
add_logs(M, src, "attacked")
updatehealth()
if(M.a_intent == "disarm")
var/randn = rand(1, 100)
if (randn <= 80)
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
Weaken(5)
add_logs(M, src, "tackled")
visible_message("<span class='danger'>[M] has tackled down [src]!</span>", \
"<span class='userdanger'>[M] has tackled down [src]!</span>")
else
if (randn <= 99)
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
drop_item()
visible_message("<span class='danger'>[M] disarmed [src]!</span>", \
"<span class='userdanger'>[M] disarmed [src]!</span>")
else
playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] has tried to disarm [src]!</span>", \
"<span class='userdanger'>[M] has tried to disarm [src]!</span>")
return
@@ -1,14 +0,0 @@
/mob/living/carbon/human/attack_hulk(mob/living/carbon/human/user)
if(user.a_intent == "harm")
..(user, 1)
playsound(loc, user.dna.species.attack_sound, 25, 1, -1)
var/hulk_verb = pick("smash","pummel")
visible_message("<span class='danger'>[user] has [hulk_verb]ed [src]!</span>", \
"<span class='userdanger'>[user] has [hulk_verb]ed [src]!</span>")
adjustBruteLoss(15)
return 1
/mob/living/carbon/human/attack_hand(mob/living/carbon/human/M)
if(..()) //to allow surgery to return properly.
return
dna.species.spec_attack_hand(M, src)
@@ -1,15 +0,0 @@
/mob/living/carbon/human/attack_paw(mob/living/carbon/monkey/M)
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(M.a_intent == "help")
..() //shaking
return 0
if(can_inject(M, 1, affecting))//Thick suits can stop monkey bites.
if(..()) //successful monkey bite, this handles disease contraction.
var/damage = rand(1, 3)
if(stat != DEAD)
apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee"))
updatehealth()
return 1
@@ -1,161 +0,0 @@
//Updates the mob's health from bodyparts and mob damage variables
/mob/living/carbon/human/updatehealth()
if(status_flags & GODMODE)
return
var/total_burn = 0
var/total_brute = 0
for(var/X in bodyparts) //hardcoded to streamline things a bit
var/obj/item/bodypart/BP = X
total_brute += BP.brute_dam
total_burn += BP.burn_dam
health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute
update_stat()
if(((maxHealth - total_burn) < config.health_threshold_dead) && stat == DEAD )
ChangeToHusk()
if(on_fire)
shred_clothing()
med_hud_set_health()
med_hud_set_status()
//These procs fetch a cumulative total damage from all bodyparts
/mob/living/carbon/human/getBruteLoss()
var/amount = 0
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
amount += BP.brute_dam
return amount
/mob/living/carbon/human/getFireLoss()
var/amount = 0
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
amount += BP.burn_dam
return amount
/mob/living/carbon/human/adjustBruteLoss(amount)
if(status_flags & GODMODE)
return 0
if(amount > 0)
take_overall_damage(amount, 0)
else
heal_overall_damage(-amount, 0)
/mob/living/carbon/human/adjustFireLoss(amount)
if(status_flags & GODMODE)
return 0
if(amount > 0)
take_overall_damage(0, amount)
else
heal_overall_damage(0, -amount)
/mob/living/carbon/human/proc/hat_fall_prob()
var/multiplier = 1
var/obj/item/clothing/head/H = head
var/loose = 40
if(stat || (status_flags & FAKEDEATH))
multiplier = 2
if(H.flags_cover & (HEADCOVERSEYES | HEADCOVERSMOUTH) || H.flags_inv & (HIDEEYES | HIDEFACE))
loose = 0
return loose * multiplier
////////////////////////////////////////////
//Returns a list of damaged bodyparts
/mob/living/carbon/human/proc/get_damaged_bodyparts(brute, burn)
var/list/obj/item/bodypart/parts = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if((brute && BP.brute_dam) || (burn && BP.burn_dam))
parts += BP
return parts
//Returns a list of damageable bodyparts
/mob/living/carbon/human/proc/get_damageable_bodyparts()
var/list/obj/item/bodypart/parts = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(BP.brute_dam + BP.burn_dam < BP.max_damage)
parts += BP
return parts
//Heals ONE external organ, organ gets randomly selected from damaged ones.
//It automatically updates damage overlays if necesary
//It automatically updates health status
/mob/living/carbon/human/heal_organ_damage(brute, burn)
var/list/obj/item/bodypart/parts = get_damaged_bodyparts(brute,burn)
if(!parts.len)
return
var/obj/item/bodypart/picked = pick(parts)
if(picked.heal_damage(brute,burn,0))
update_damage_overlays(0)
updatehealth()
//Damages ONE external organ, organ gets randomly selected from damagable ones.
//It automatically updates damage overlays if necesary
//It automatically updates health status
/mob/living/carbon/human/take_organ_damage(brute, burn)
var/list/obj/item/bodypart/parts = get_damageable_bodyparts()
if(!parts.len)
return
var/obj/item/bodypart/picked = pick(parts)
if(picked.take_damage(brute,burn))
update_damage_overlays(0)
updatehealth()
//Heal MANY bodyparts, in random order
/mob/living/carbon/human/heal_overall_damage(brute, burn, updating_health=1)
var/list/obj/item/bodypart/parts = get_damaged_bodyparts(brute,burn)
var/update = 0
while(parts.len && (brute>0 || burn>0) )
var/obj/item/bodypart/picked = pick(parts)
var/brute_was = picked.brute_dam
var/burn_was = picked.burn_dam
update |= picked.heal_damage(brute,burn,0)
brute -= (brute_was-picked.brute_dam)
burn -= (burn_was-picked.burn_dam)
parts -= picked
if(updating_health)
updatehealth()
if(update)
update_damage_overlays(0)
// damage MANY bodyparts, in random order
/mob/living/carbon/human/take_overall_damage(brute, burn)
if(status_flags & GODMODE)
return //godmode
var/list/obj/item/bodypart/parts = get_damageable_bodyparts()
var/update = 0
while(parts.len && (brute>0 || burn>0) )
var/obj/item/bodypart/picked = pick(parts)
var/brute_per_part = brute/parts.len
var/burn_per_part = burn/parts.len
var/brute_was = picked.brute_dam
var/burn_was = picked.burn_dam
update |= picked.take_damage(brute_per_part,burn_per_part)
brute -= (picked.brute_dam - brute_was)
burn -= (picked.burn_dam - burn_was)
parts -= picked
updatehealth()
if(update)
update_damage_overlays(0)
////////////////////////////////////////////
/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = 0)
// depending on the species, it will run the corresponding apply_damage code there
return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src)
@@ -17,8 +17,8 @@
return (armorval/max(organnum, 1))
/mob/living/carbon/human/proc/checkarmor(obj/item/bodypart/def_zone, type)
if(!type)
/mob/living/carbon/human/proc/checkarmor(obj/item/bodypart/def_zone, d_type)
if(!d_type)
return 0
var/protection = 0
var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, back, gloves, shoes, belt, s_store, glasses, ears, wear_id) //Everything but pockets. Pockets are l_store and r_store. (if pockets were allowed, putting something armored, gloves or hats for example, would double up on the armor)
@@ -28,13 +28,44 @@
if(bp && istype(bp ,/obj/item/clothing))
var/obj/item/clothing/C = bp
if(C.body_parts_covered & def_zone.body_part)
protection += C.armor[type]
protection += C.armor[d_type]
return protection
/mob/living/carbon/human/on_hit(proj_type)
dna.species.on_hit(proj_type, src)
///checkeyeprot()
///Returns a number between -1 to 2
/mob/living/carbon/human/get_eye_protection()
var/number = ..()
if(istype(src.head, /obj/item/clothing/head)) //are they wearing something on their head
var/obj/item/clothing/head/HFP = src.head //if yes gets the flash protection value from that item
number += HFP.flash_protect
if(istype(src.glasses, /obj/item/clothing/glasses)) //glasses
var/obj/item/clothing/glasses/GFP = src.glasses
number += GFP.flash_protect
if(istype(src.wear_mask, /obj/item/clothing/mask)) //mask
var/obj/item/clothing/mask/MFP = src.wear_mask
number += MFP.flash_protect
return number
/mob/living/carbon/human/get_ear_protection()
if((ears && (ears.flags & EARBANGPROTECT)) || (head && (head.flags & HEADBANGPROTECT)))
return 1
/mob/living/carbon/human/on_hit(obj/item/projectile/P)
dna.species.on_hit(P, src)
/mob/living/carbon/human/bullet_act(obj/item/projectile/P, def_zone)
var/spec_return = dna.species.bullet_act(P, src)
if(spec_return)
return spec_return
if(martial_art && martial_art.deflection_chance) //Some martial arts users can deflect projectiles!
if(prob(martial_art.deflection_chance))
if(!lying && dna && !dna.check_mutation(HULK)) //But only if they're not lying down, and hulks can't do it
visible_message("<span class='danger'>[src] deflects the projectile; [p_they()] can't be hit with ranged weapons!</span>", "<span class='userdanger'>You deflect the projectile!</span>")
playsound(src, pick("sound/weapons/bulletflyby.ogg","sound/weapons/bulletflyby2.ogg","sound/weapons/bulletflyby3.ogg"), 75, 1)
return 0
if(!(P.original == src && P.firer == src)) //can't block or reflect when shooting yourself
if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam))
if(check_reflect(def_zone)) // Checks if you've passed a reflection% check
@@ -60,31 +91,26 @@
if(check_shields(P.damage, "the [P.name]", P, PROJECTILE_ATTACK, P.armour_penetration))
P.on_hit(src, 100, def_zone)
return 2
return (..(P , def_zone))
/mob/living/carbon/human/proc/check_reflect(def_zone) //Reflection checks for anything in your l_hand, r_hand, or wear_suit based on the reflection chance of the object
if(wear_suit)
if(wear_suit.IsReflect(def_zone) == 1)
return 1
if(l_hand)
if(l_hand.IsReflect(def_zone) == 1)
return 1
if(r_hand)
if(r_hand.IsReflect(def_zone) == 1)
for(var/obj/item/I in held_items)
if(I.IsReflect(def_zone) == 1)
return 1
return 0
/mob/living/carbon/human/proc/check_shields(damage = 0, attack_text = "the attack", atom/movable/AM, attack_type = MELEE_ATTACK, armour_penetration = 0)
var/block_chance_modifier = round(damage / -3)
if(l_hand && !istype(l_hand, /obj/item/clothing))
var/final_block_chance = l_hand.block_chance - (Clamp((armour_penetration-l_hand.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
if(l_hand.hit_reaction(src, attack_text, final_block_chance, damage, attack_type))
return 1
if(r_hand && !istype(r_hand, /obj/item/clothing))
var/final_block_chance = r_hand.block_chance - (Clamp((armour_penetration-r_hand.armour_penetration)/2,0,100)) + block_chance_modifier //Need to reset the var so it doesn't carry over modifications between attempts
if(r_hand.hit_reaction(src, attack_text, final_block_chance, damage, attack_type))
return 1
for(var/obj/item/I in held_items)
if(!istype(I, /obj/item/clothing))
var/final_block_chance = I.block_chance - (Clamp((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
if(I.hit_reaction(src, attack_text, final_block_chance, damage, attack_type))
return 1
if(wear_suit)
var/final_block_chance = wear_suit.block_chance - (Clamp((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier
if(wear_suit.hit_reaction(src, attack_text, final_block_chance, damage, attack_type))
@@ -95,252 +121,17 @@
return 1
return 0
/mob/living/carbon/human/attacked_by(obj/item/I, mob/living/user)
if(!I || !user)
return 0
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(user.zone_selected))
var/target_area = parse_zone(check_zone(user.zone_selected))
feedback_add_details("item_used_for_combat","[I.type]|[I.force]")
feedback_add_details("zone_targeted","[target_area]")
// the attacked_by code varies among species
return dna.species.spec_attacked_by(I, user, affecting, a_intent, target_area, src)
/mob/living/carbon/human/emp_act(severity)
var/informed = 0
for(var/obj/item/bodypart/L in src.bodyparts)
if(L.status == ORGAN_ROBOTIC)
if(!informed)
src << "<span class='userdanger'>You feel a sharp pain as your robotic limbs overload.</span>"
informed = 1
switch(severity)
if(1)
L.take_damage(0,10)
src.Stun(10)
if(2)
L.take_damage(0,5)
src.Stun(5)
..()
/mob/living/carbon/human/acid_act(acidpwr, toxpwr, acid_volume)
var/list/damaged = list()
var/list/inventory_items_to_kill = list()
var/acidity = min(acidpwr*acid_volume/200, toxpwr)
var/acid_volume_left = acid_volume
var/acid_decay = 100/acidpwr // how much volume we lose per item we try to melt. 5 for fluoro, 10 for sulphuric
//HEAD//
var/obj/item/clothing/head_clothes = null
if(glasses)
head_clothes = glasses
if(wear_mask)
head_clothes = wear_mask
if(head)
head_clothes = head
if(head_clothes)
if(!head_clothes.unacidable)
head_clothes.acid_act(acidpwr, acid_volume_left)
acid_volume_left = max(acid_volume_left - acid_decay, 0) //We remove some of the acid volume.
update_inv_glasses()
update_inv_wear_mask()
update_inv_head()
else
src << "<span class='notice'>Your [head_clothes.name] protects your head and face from the acid!</span>"
else
. = get_bodypart("head")
if(.)
damaged += .
if(ears)
inventory_items_to_kill += ears
//CHEST//
var/obj/item/clothing/chest_clothes = null
if(w_uniform)
chest_clothes = w_uniform
if(wear_suit)
chest_clothes = wear_suit
if(chest_clothes)
if(!chest_clothes.unacidable)
chest_clothes.acid_act(acidpwr, acid_volume_left)
acid_volume_left = max(acid_volume_left - acid_decay, 0)
update_inv_w_uniform()
update_inv_wear_suit()
else
src << "<span class='notice'>Your [chest_clothes.name] protects your body from the acid!</span>"
else
. = get_bodypart("chest")
if(.)
damaged += .
if(wear_id)
inventory_items_to_kill += wear_id
if(r_store)
inventory_items_to_kill += r_store
if(l_store)
inventory_items_to_kill += l_store
if(s_store)
inventory_items_to_kill += s_store
//ARMS & HANDS//
var/obj/item/clothing/arm_clothes = null
if(gloves)
arm_clothes = gloves
if(w_uniform && (w_uniform.body_parts_covered & HANDS) || w_uniform && (w_uniform.body_parts_covered & ARMS))
arm_clothes = w_uniform
if(wear_suit && (wear_suit.body_parts_covered & HANDS) || wear_suit && (wear_suit.body_parts_covered & ARMS))
arm_clothes = wear_suit
if(arm_clothes)
if(!arm_clothes.unacidable)
arm_clothes.acid_act(acidpwr, acid_volume_left)
acid_volume_left = max(acid_volume_left - acid_decay, 0)
update_inv_gloves()
update_inv_w_uniform()
update_inv_wear_suit()
else
src << "<span class='notice'>Your [arm_clothes.name] protects your arms and hands from the acid!</span>"
else
. = get_bodypart("r_arm")
if(.)
damaged += .
. = get_bodypart("l_arm")
if(.)
damaged += .
//LEGS & FEET//
var/obj/item/clothing/leg_clothes = null
if(shoes)
leg_clothes = shoes
if(w_uniform && (w_uniform.body_parts_covered & FEET) || w_uniform && (w_uniform.body_parts_covered & LEGS))
leg_clothes = w_uniform
if(wear_suit && (wear_suit.body_parts_covered & FEET) || wear_suit && (wear_suit.body_parts_covered & LEGS))
leg_clothes = wear_suit
if(leg_clothes)
if(!leg_clothes.unacidable)
leg_clothes.acid_act(acidpwr, acid_volume_left)
acid_volume_left = max(acid_volume_left - acid_decay, 0)
update_inv_shoes()
update_inv_w_uniform()
update_inv_wear_suit()
else
src << "<span class='notice'>Your [leg_clothes.name] protects your legs and feet from the acid!</span>"
else
. = get_bodypart("r_leg")
if(.)
damaged += .
. = get_bodypart("l_leg")
if(.)
damaged += .
//DAMAGE//
for(var/obj/item/bodypart/affecting in damaged)
affecting.take_damage(acidity, 2*acidity)
if(affecting.name == "head")
if(prob(min(acidpwr*acid_volume/10, 90))) //Applies disfigurement
affecting.take_damage(acidity, 2*acidity)
emote("scream")
facial_hair_style = "Shaved"
hair_style = "Bald"
update_hair()
status_flags |= DISFIGURED
update_damage_overlays()
//MELTING INVENTORY ITEMS//
//these items are all outside of armour visually, so melt regardless.
if(back)
inventory_items_to_kill += back
if(belt)
inventory_items_to_kill += belt
if(r_hand)
inventory_items_to_kill += r_hand
if(l_hand)
inventory_items_to_kill += l_hand
for(var/obj/item/I in inventory_items_to_kill)
I.acid_act(acidpwr, acid_volume_left)
acid_volume_left = max(acid_volume_left - acid_decay, 0)
/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M)
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
if(check_shields(damage, "the [M.name]", null, MELEE_ATTACK, M.armour_penetration))
return 0
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
var/armor = run_armor_check(affecting, "melee")
apply_damage(damage, M.melee_damage_type, affecting, armor, "", "", M.armour_penetration)
updatehealth()
/mob/living/carbon/human/attack_larva(mob/living/carbon/alien/larva/L)
if(..()) //successful larva bite.
var/damage = rand(1, 3)
if(check_shields(damage, "the [L.name]"))
return 0
if(stat != DEAD)
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
updatehealth()
/mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
var/damage = rand(5, 25)
if(M.is_adult)
damage = rand(10, 35)
if(check_shields(damage, "the [M.name]"))
return 0
var/dam_zone = pick("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg", "groin")
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
/mob/living/carbon/human/mech_melee_attack(obj/mecha/M)
if(M.occupant.a_intent == "harm")
M.do_attack_animation(src)
if(M.damtype == "brute")
step_away(src,M,15)
var/obj/item/bodypart/temp = get_bodypart(pick("chest", "chest", "chest", "head"))
if(temp)
var/update = 0
switch(M.damtype)
if("brute")
if(M.force > 20)
Paralyse(1)
update |= temp.take_damage(rand(M.force/2, M.force), 0)
playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
if("fire")
update |= temp.take_damage(0, rand(M.force/2, M.force))
playsound(src, 'sound/items/Welder.ogg', 50, 1)
if("tox")
M.mech_toxin_damage(src)
else
return
if(update)
update_damage_overlays(0)
updatehealth()
visible_message("<span class='danger'>[M.name] has hit [src]!</span>", \
"<span class='userdanger'>[M.name] has hit [src]!</span>")
add_logs(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
else
..()
/mob/living/carbon/human/proc/check_block()
if(martial_art && martial_art.block_chance \
&& prob(martial_art.block_chance) && in_throw_mode \
&& !stat && !weakened && !stunned)
return TRUE
return FALSE
/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0)
var/spec_return = dna.species.spec_hitby(AM, src)
if(spec_return)
return spec_return
var/obj/item/I
var/throwpower = 30
if(istype(AM, /obj/item))
@@ -355,13 +146,13 @@
else if(I)
if(I.throw_speed >= EMBED_THROWSPEED_THRESHOLD)
if(can_embed(I))
if(prob(I.embed_chance) && !(dna && (PIERCEIMMUNE in dna.species.specflags)))
if(prob(I.embed_chance) && !(dna && (PIERCEIMMUNE in dna.species.species_traits)))
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
var/obj/item/bodypart/L = pick(bodyparts)
L.embedded_objects |= I
I.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
I.loc = src
L.take_damage(I.w_class*I.embedded_impact_pain_multiplier)
L.receive_damage(I.w_class*I.embedded_impact_pain_multiplier)
visible_message("<span class='danger'>\the [I.name] embeds itself in [src]'s [L.name]!</span>","<span class='userdanger'>\the [I.name] embeds itself in your [L.name]!</span>")
hitpush = 0
skipcatch = 1 //can't catch the now embedded item
@@ -379,6 +170,586 @@
w_uniform.add_fingerprint(user)
..()
/mob/living/carbon/human/Stun(amount, updating_canmove = 1)
amount = dna.species.spec_stun(src,amount)
..()
/mob/living/carbon/human/attacked_by(obj/item/I, mob/living/user)
if(!I || !user)
return 0
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(user.zone_selected)) //what we're actually ending up trying to hit.
var/target_area = parse_zone(check_zone(user.zone_selected)) //our intended target
feedback_add_details("item_used_for_combat","[I.type]|[I.force]")
feedback_add_details("zone_targeted","[target_area]")
// the attacked_by code varies among species
return dna.species.spec_attacked_by(I, user, affecting, a_intent, src)
/mob/living/carbon/human/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
if(user.a_intent == INTENT_HARM)
var/hulk_verb = pick("smash","pummel")
if(check_shields(15, "the [hulk_verb]ing"))
return
..(user, 1)
playsound(loc, user.dna.species.attack_sound, 25, 1, -1)
var/message = "[user] has [hulk_verb]ed [src]!"
visible_message("<span class='danger'>[message]</span>", \
"<span class='userdanger'>[message]</span>")
adjustBruteLoss(15)
damage_clothes(15, BRUTE, "melee")
return 1
/mob/living/carbon/human/attack_hand(mob/living/carbon/human/M)
if(..()) //to allow surgery to return properly.
return
dna.species.spec_attack_hand(M, src)
/mob/living/carbon/human/attack_paw(mob/living/carbon/monkey/M)
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
affecting = get_bodypart("chest")
if(M.a_intent == INTENT_HELP)
..() //shaking
return 0
if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stunned instead.
if(get_active_held_item() && drop_item())
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] disarmed [src]!</span>", \
"<span class='userdanger'>[M] disarmed [src]!</span>")
else if(!M.client || prob(5)) // only natural monkeys get to stun reliably, (they only do it occasionaly)
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
Weaken(5)
add_logs(M, src, "tackled")
visible_message("<span class='danger'>[M] has tackled down [src]!</span>", \
"<span class='userdanger'>[M] has tackled down [src]!</span>")
if(M.limb_destroyer)
dismembering_strike(M, affecting.body_zone)
if(can_inject(M, 1, affecting))//Thick suits can stop monkey bites.
if(..()) //successful monkey bite, this handles disease contraction.
var/damage = rand(1, 3)
if(check_shields(damage))
return 0
if(stat != DEAD)
apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee"))
damage_clothes(damage, BRUTE, "melee", affecting.body_zone)
return 1
/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M)
if(check_shields(0, M.name))
visible_message("<span class='danger'>[M] attempted to touch [src]!</span>")
return 0
if(..())
if(M.a_intent == INTENT_HARM)
if (w_uniform)
w_uniform.add_fingerprint(M)
var/damage = prob(90) ? 20 : 0
if(!damage)
playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] has lunged at [src]!</span>", \
"<span class='userdanger'>[M] has lunged at [src]!</span>")
return 0
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
if(!affecting)
affecting = get_bodypart("chest")
var/armor_block = run_armor_check(affecting, "melee","","",10)
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
"<span class='userdanger'>[M] has slashed at [src]!</span>")
add_logs(M, src, "attacked")
if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful
return 1
apply_damage(damage, BRUTE, affecting, armor_block)
damage_clothes(damage, BRUTE, "melee", affecting.body_zone)
if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stunned instead.
if(get_active_held_item() && drop_item())
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] disarmed [src]!</span>", \
"<span class='userdanger'>[M] disarmed [src]!</span>")
else
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
Weaken(5)
add_logs(M, src, "tackled")
visible_message("<span class='danger'>[M] has tackled down [src]!</span>", \
"<span class='userdanger'>[M] has tackled down [src]!</span>")
/mob/living/carbon/human/attack_larva(mob/living/carbon/alien/larva/L)
if(..()) //successful larva bite.
var/damage = rand(1, 3)
if(check_shields(damage, "the [L.name]"))
return 0
if(stat != DEAD)
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
if(!affecting)
affecting = get_bodypart("chest")
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
damage_clothes(damage, BRUTE, "melee", affecting.body_zone)
/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M)
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
if(check_shields(damage, "the [M.name]", null, MELEE_ATTACK, M.armour_penetration))
return 0
var/dam_zone = dismembering_strike(M, pick("chest", "l_hand", "r_hand", "l_leg", "r_leg"))
if(!dam_zone) //Dismemberment successful
return 1
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
affecting = get_bodypart("chest")
var/armor = run_armor_check(affecting, "melee", armour_penetration = M.armour_penetration)
apply_damage(damage, M.melee_damage_type, affecting, armor)
damage_clothes(damage, M.melee_damage_type, "melee", affecting.body_zone)
/mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
var/damage = rand(5, 25)
if(M.is_adult)
damage = rand(10, 35)
if(check_shields(damage, "the [M.name]"))
return 0
var/dam_zone = dismembering_strike(M, pick("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg"))
if(!dam_zone) //Dismemberment successful
return 1
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
affecting = get_bodypart("chest")
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
damage_clothes(damage, BRUTE, "melee", affecting.body_zone)
/mob/living/carbon/human/mech_melee_attack(obj/mecha/M)
if(M.occupant.a_intent == INTENT_HARM)
M.do_attack_animation(src)
if(M.damtype == "brute")
step_away(src,M,15)
var/obj/item/bodypart/temp = get_bodypart(pick("chest", "chest", "chest", "head"))
if(temp)
var/update = 0
var/dmg = rand(M.force/2, M.force)
switch(M.damtype)
if("brute")
if(M.force > 20)
Paralyse(1)
update |= temp.receive_damage(dmg, 0)
playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
damage_clothes(dmg, BRUTE, "melee", temp.body_zone)
if("fire")
update |= temp.receive_damage(0, dmg)
playsound(src, 'sound/items/Welder.ogg', 50, 1)
damage_clothes(dmg, BURN, "melee", temp.body_zone)
if("tox")
M.mech_toxin_damage(src)
else
return
if(update)
update_damage_overlays()
updatehealth()
visible_message("<span class='danger'>[M.name] has hit [src]!</span>", \
"<span class='userdanger'>[M.name] has hit [src]!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
else
..()
/mob/living/carbon/human/ex_act(severity, target, origin)
if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
return
..()
var/b_loss = 0
var/f_loss = 0
var/bomb_armor = getarmor(null, "bomb")
switch (severity)
if (1)
if(prob(bomb_armor))
b_loss = 500
var/atom/throw_target = get_edge_target_turf(src, get_dir(src, get_step_away(src, src)))
throw_at(throw_target, 200, 4)
damage_clothes(400 - bomb_armor, BRUTE, "bomb")
else
gib()
return
if (2)
b_loss = 60
f_loss = 60
if(bomb_armor)
b_loss = 30*(2 - round(bomb_armor*0.01, 0.05))
f_loss = b_loss
damage_clothes(200 - bomb_armor, BRUTE, "bomb")
if (!istype(ears, /obj/item/clothing/ears/earmuffs))
adjustEarDamage(30, 120)
if (prob(70))
Paralyse(10)
if(3)
b_loss = 30
if(bomb_armor)
b_loss = 15*(2 - round(bomb_armor*0.01, 0.05))
damage_clothes(max(50 - bomb_armor, 0), BRUTE, "bomb")
if (!istype(ears, /obj/item/clothing/ears/earmuffs))
adjustEarDamage(15,60)
if (prob(50))
Paralyse(8)
take_overall_damage(b_loss,f_loss)
//attempt to dismember bodyparts
if(severity <= 2 || !bomb_armor)
var/max_limb_loss = round(4/severity) //so you don't lose four limbs at severity 3.
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(prob(50/severity) && !prob(getarmor(BP, "bomb")) && BP.body_zone != "head" && BP.body_zone != "chest")
BP.brute_dam = BP.max_damage
BP.dismember()
max_limb_loss--
if(!max_limb_loss)
break
/mob/living/carbon/human/blob_act(obj/structure/blob/B)
if(stat == DEAD)
return
show_message("<span class='userdanger'>The blob attacks you!</span>")
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
apply_damage(5, BRUTE, affecting, run_armor_check(affecting, "melee"))
//Added a safety check in case you want to shock a human mob directly through electrocute_act.
/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0, illusion = 0)
if(tesla_shock)
var/total_coeff = 1
if(gloves)
var/obj/item/clothing/gloves/G = gloves
if(G.siemens_coefficient <= 0)
total_coeff -= 0.5
if(wear_suit)
var/obj/item/clothing/suit/S = wear_suit
if(S.siemens_coefficient <= 0)
total_coeff -= 0.95
siemens_coeff = total_coeff
else if(!safety)
var/gloves_siemens_coeff = 1
if(gloves)
var/obj/item/clothing/gloves/G = gloves
gloves_siemens_coeff = G.siemens_coefficient
siemens_coeff = gloves_siemens_coeff
if(heart_attack && !illusion)
if(shock_damage * siemens_coeff >= 1 && prob(25))
heart_attack = 0
if(stat == CONSCIOUS)
src << "<span class='notice'>You feel your heart beating again!</span>"
. = ..(shock_damage,source,siemens_coeff,safety,override,tesla_shock, illusion)
if(.)
electrocution_animation(40)
/mob/living/carbon/human/emp_act(severity)
var/informed = 0
for(var/obj/item/bodypart/L in src.bodyparts)
if(L.status == BODYPART_ROBOTIC)
if(!informed)
src << "<span class='userdanger'>You feel a sharp pain as your robotic limbs overload.</span>"
informed = 1
switch(severity)
if(1)
L.receive_damage(0,10)
src.Stun(10)
if(2)
L.receive_damage(0,5)
src.Stun(5)
..()
/mob/living/carbon/human/acid_act(acidpwr, acid_volume, bodyzone_hit)
var/list/damaged = list()
var/list/inventory_items_to_kill = list()
var/acidity = acidpwr * min(acid_volume*0.005, 0.1)
//HEAD//
if(!bodyzone_hit || bodyzone_hit == "head") //only if we didn't specify a zone or if that zone is the head.
var/obj/item/clothing/head_clothes = null
if(glasses)
head_clothes = glasses
if(wear_mask)
head_clothes = wear_mask
if(wear_neck)
head_clothes = wear_neck
if(head)
head_clothes = head
if(head_clothes)
if(!(head_clothes.resistance_flags & UNACIDABLE))
head_clothes.acid_act(acidpwr, acid_volume)
update_inv_glasses()
update_inv_wear_mask()
update_inv_neck()
update_inv_head()
else
src << "<span class='notice'>Your [head_clothes.name] protects your head and face from the acid!</span>"
else
. = get_bodypart("head")
if(.)
damaged += .
if(ears)
inventory_items_to_kill += ears
//CHEST//
if(!bodyzone_hit || bodyzone_hit == "chest")
var/obj/item/clothing/chest_clothes = null
if(w_uniform)
chest_clothes = w_uniform
if(wear_suit)
chest_clothes = wear_suit
if(chest_clothes)
if(!(chest_clothes.resistance_flags & UNACIDABLE))
chest_clothes.acid_act(acidpwr, acid_volume)
update_inv_w_uniform()
update_inv_wear_suit()
else
src << "<span class='notice'>Your [chest_clothes.name] protects your body from the acid!</span>"
else
. = get_bodypart("chest")
if(.)
damaged += .
if(wear_id)
inventory_items_to_kill += wear_id
if(r_store)
inventory_items_to_kill += r_store
if(l_store)
inventory_items_to_kill += l_store
if(s_store)
inventory_items_to_kill += s_store
//ARMS & HANDS//
if(!bodyzone_hit || bodyzone_hit == "l_arm" || bodyzone_hit == "r_arm")
var/obj/item/clothing/arm_clothes = null
if(gloves)
arm_clothes = gloves
if(w_uniform && ((w_uniform.body_parts_covered & HANDS) || (w_uniform.body_parts_covered & ARMS)))
arm_clothes = w_uniform
if(wear_suit && ((wear_suit.body_parts_covered & HANDS) || (wear_suit.body_parts_covered & ARMS)))
arm_clothes = wear_suit
if(arm_clothes)
if(!(arm_clothes.resistance_flags & UNACIDABLE))
arm_clothes.acid_act(acidpwr, acid_volume)
update_inv_gloves()
update_inv_w_uniform()
update_inv_wear_suit()
else
src << "<span class='notice'>Your [arm_clothes.name] protects your arms and hands from the acid!</span>"
else
. = get_bodypart("r_arm")
if(.)
damaged += .
. = get_bodypart("l_arm")
if(.)
damaged += .
//LEGS & FEET//
if(!bodyzone_hit || bodyzone_hit == "l_leg" || bodyzone_hit == "r_leg" || bodyzone_hit == "feet")
var/obj/item/clothing/leg_clothes = null
if(shoes)
leg_clothes = shoes
if(w_uniform && ((w_uniform.body_parts_covered & FEET) || (bodyzone_hit != "feet" && (w_uniform.body_parts_covered & LEGS))))
leg_clothes = w_uniform
if(wear_suit && ((wear_suit.body_parts_covered & FEET) || (bodyzone_hit != "feet" && (wear_suit.body_parts_covered & LEGS))))
leg_clothes = wear_suit
if(leg_clothes)
if(!(leg_clothes.resistance_flags & UNACIDABLE))
leg_clothes.acid_act(acidpwr, acid_volume)
update_inv_shoes()
update_inv_w_uniform()
update_inv_wear_suit()
else
src << "<span class='notice'>Your [leg_clothes.name] protects your legs and feet from the acid!</span>"
else
. = get_bodypart("r_leg")
if(.)
damaged += .
. = get_bodypart("l_leg")
if(.)
damaged += .
//DAMAGE//
for(var/obj/item/bodypart/affecting in damaged)
affecting.receive_damage(acidity, 2*acidity)
if(affecting.name == "head")
if(prob(min(acidpwr*acid_volume/10, 90))) //Applies disfigurement
affecting.receive_damage(acidity, 2*acidity)
emote("scream")
facial_hair_style = "Shaved"
hair_style = "Bald"
update_hair()
status_flags |= DISFIGURED
update_damage_overlays()
//MELTING INVENTORY ITEMS//
//these items are all outside of armour visually, so melt regardless.
if(!bodyzone_hit)
if(back)
inventory_items_to_kill += back
if(belt)
inventory_items_to_kill += belt
inventory_items_to_kill += held_items
for(var/obj/item/I in inventory_items_to_kill)
I.acid_act(acidpwr, acid_volume)
return 1
/mob/living/carbon/human/singularity_act()
var/gain = 20
if(mind)
if((mind.assigned_role == "Station Engineer") || (mind.assigned_role == "Chief Engineer") )
gain = 100
if(mind.assigned_role == "Clown")
gain = rand(-300, 300)
investigate_log("([key_name(src)]) has been consumed by the singularity.","singulo") //Oh that's where the clown ended up!
gib()
return(gain)
/mob/living/carbon/human/help_shake_act(mob/living/carbon/M)
if(!istype(M))
return
if(health >= 0)
if(src == M)
visible_message("[src] examines [p_them()]self.", \
"<span class='notice'>You check yourself for injuries.</span>")
var/list/missing = list("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg")
for(var/X in bodyparts)
var/obj/item/bodypart/LB = X
missing -= LB.body_zone
var/status = ""
var/brutedamage = LB.brute_dam
var/burndamage = LB.burn_dam
if(hallucination)
if(prob(30))
brutedamage += rand(30,40)
if(prob(30))
burndamage += rand(30,40)
if(brutedamage > 0)
status = "bruised"
if(brutedamage > 20)
status = "battered"
if(brutedamage > 40)
status = "mangled"
if(brutedamage > 0 && burndamage > 0)
status += " and "
if(burndamage > 40)
status += "peeling away"
else if(burndamage > 10)
status += "blistered"
else if(burndamage > 0)
status += "numb"
if(status == "")
status = "OK"
src << "\t [status == "OK" ? "\blue" : "\red"] Your [LB.name] is [status]."
for(var/obj/item/I in LB.embedded_objects)
src << "\t <a href='byond://?src=\ref[src];embedded_object=\ref[I];embedded_limb=\ref[LB]'>\red There is \a [I] embedded in your [LB.name]!</a>"
for(var/t in missing)
src << "<span class='boldannounce'>Your [parse_zone(t)] is missing!</span>"
if(bleed_rate)
src << "<span class='danger'>You are bleeding!</span>"
if(staminaloss)
if(staminaloss > 30)
src << "<span class='info'>You're completely exhausted.</span>"
else
src << "<span class='info'>You feel fatigued.</span>"
else
if(wear_suit)
wear_suit.add_fingerprint(M)
else if(w_uniform)
w_uniform.add_fingerprint(M)
..()
/mob/living/carbon/human/damage_clothes(damage_amount, damage_type = BRUTE, damage_flag = 0, def_zone)
if(damage_type != BRUTE && damage_type != BURN)
return
damage_amount *= 0.5 //0.5 multiplier for balance reason, we don't want clothes to be too easily destroyed
var/list/torn_items = list()
//HEAD//
if(!def_zone || def_zone == "head")
var/obj/item/clothing/head_clothes = null
if(glasses)
head_clothes = glasses
if(wear_mask)
head_clothes = wear_mask
if(wear_neck)
head_clothes = wear_neck
if(head)
head_clothes = head
if(head_clothes)
torn_items += head_clothes
else if(ears)
torn_items += ears
//CHEST//
if(!def_zone || def_zone == "chest")
var/obj/item/clothing/chest_clothes = null
if(w_uniform)
chest_clothes = w_uniform
if(wear_suit)
chest_clothes = wear_suit
if(chest_clothes)
torn_items += chest_clothes
//ARMS & HANDS//
if(!def_zone || def_zone == "l_arm" || def_zone == "r_arm")
var/obj/item/clothing/arm_clothes = null
if(gloves)
arm_clothes = gloves
if(w_uniform && ((w_uniform.body_parts_covered & HANDS) || (w_uniform.body_parts_covered & ARMS)))
arm_clothes = w_uniform
if(wear_suit && ((wear_suit.body_parts_covered & HANDS) || (wear_suit.body_parts_covered & ARMS)))
arm_clothes = wear_suit
if(arm_clothes)
torn_items += arm_clothes
//LEGS & FEET//
if(!def_zone || def_zone == "l_leg" || def_zone == "r_leg")
var/obj/item/clothing/leg_clothes = null
if(shoes)
leg_clothes = shoes
if(w_uniform && ((w_uniform.body_parts_covered & FEET) || (w_uniform.body_parts_covered & LEGS)))
leg_clothes = w_uniform
if(wear_suit && ((wear_suit.body_parts_covered & FEET) || (wear_suit.body_parts_covered & LEGS)))
leg_clothes = wear_suit
if(leg_clothes)
torn_items += leg_clothes
for(var/obj/item/I in torn_items)
I.take_damage(damage_amount, damage_type, damage_flag, 0)
@@ -3,6 +3,8 @@ var/global/default_martial_art = new/datum/martial_art
languages_spoken = HUMAN
languages_understood = HUMAN
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD,ANTAG_HUD)
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
pressure_resistance = 25
//Hair colour and style
var/hair_color = "000"
var/hair_style = "Bald"
@@ -29,11 +31,7 @@ var/global/default_martial_art = new/datum/martial_art
//Equipment slots
var/obj/item/wear_suit = null
var/obj/item/w_uniform = null
var/obj/item/shoes = null
var/obj/item/belt = null
var/obj/item/gloves = null
var/obj/item/clothing/glasses/glasses = null
var/obj/item/ears = null
var/obj/item/wear_id = null
var/obj/item/r_store = null
var/obj/item/l_store = null
@@ -41,8 +39,6 @@ var/global/default_martial_art = new/datum/martial_art
var/special_voice = "" // For changing our voice. Used by a symptom.
var/gender_ambiguous = 0 //if something goes wrong during gender reassignment this generates a line in examine
var/bleed_rate = 0 //how much are we bleeding
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
@@ -81,41 +81,23 @@
if(wear_id)
return wear_id.GetID()
///checkeyeprot()
///Returns a number between -1 to 2
/mob/living/carbon/human/check_eye_prot()
var/number = ..()
if(istype(src.head, /obj/item/clothing/head)) //are they wearing something on their head
var/obj/item/clothing/head/HFP = src.head //if yes gets the flash protection value from that item
number += HFP.flash_protect
if(istype(src.glasses, /obj/item/clothing/glasses)) //glasses
var/obj/item/clothing/glasses/GFP = src.glasses
number += GFP.flash_protect
if(istype(src.wear_mask, /obj/item/clothing/mask)) //mask
var/obj/item/clothing/mask/MFP = src.wear_mask
number += MFP.flash_protect
if(istype(src.dna.species, /datum/species/xeno)) //Xenos don't have eyes.
number += 2 //So give them protection from flashes.
return number
/mob/living/carbon/human/check_ear_prot()
if((ears && (ears.flags & EARBANGPROTECT)) || (head && (head.flags & HEADBANGPROTECT)))
return 1
/mob/living/carbon/human/abiotic(full_body = 0)
if(full_body && ((l_hand && !( src.l_hand.flags&ABSTRACT )) || (r_hand && !( src.r_hand.flags&ABSTRACT )) || (back && !(back.flags&ABSTRACT)) || (wear_mask && !(wear_mask.flags&ABSTRACT)) || (head && !(head.flags&ABSTRACT)) || (shoes && !(shoes.flags&ABSTRACT)) || (w_uniform && !(w_uniform.flags&ABSTRACT)) || (wear_suit && !(wear_suit.flags&ABSTRACT)) || (glasses && !(glasses.flags&ABSTRACT)) || (ears && !(ears.flags&ABSTRACT)) || (gloves && !(gloves.flags&ABSTRACT)) ) )
return 1
var/abiotic_hands = FALSE
for(var/obj/item/I in held_items)
if(!(I.flags & NODROP))
abiotic_hands = TRUE
break
if(full_body && abiotic_hands && ((back && !(back.flags&NODROP)) || (wear_mask && !(wear_mask.flags&NODROP)) || (head && !(head.flags&NODROP)) || (shoes && !(shoes.flags&NODROP)) || (w_uniform && !(w_uniform.flags&NODROP)) || (wear_suit && !(wear_suit.flags&NODROP)) || (glasses && !(glasses.flags&NODROP)) || (ears && !(ears.flags&NODROP)) || (gloves && !(gloves.flags&NODROP)) ) )
return TRUE
return abiotic_hands
if( (src.l_hand && !(src.l_hand.flags&ABSTRACT)) || (src.r_hand && !(src.r_hand.flags&ABSTRACT)) )
return 1
return 0
/mob/living/carbon/human/IsAdvancedToolUser()
return 1//Humans can use guns and such
/mob/living/carbon/human/InCritical()
return (health <= config.health_threshold_crit && stat == UNCONSCIOUS)
return (health <= HEALTH_THRESHOLD_CRIT && stat == UNCONSCIOUS)
/mob/living/carbon/human/reagent_check(datum/reagent/R)
return dna.species.handle_chemicals(R,src)
@@ -159,11 +141,11 @@
if(src.dna.check_mutation(HULK))
src << "<span class='warning'>Your meaty finger is much too large for the trigger guard!</span>"
return 0
if(NOGUNS in src.dna.species.specflags)
if(NOGUNS in src.dna.species.species_traits)
src << "<span class='warning'>Your fingers don't fit in the trigger guard!</span>"
return 0
if(martial_art && martial_art.name == "The Sleeping Carp") //great dishonor to famiry
if(martial_art && martial_art.no_guns) //great dishonor to famiry
src << "<span class='warning'>Use of ranged weaponry would bring dishonor to the clan.</span>"
return 0
@@ -1,8 +1,8 @@
/mob/living/carbon/human/movement_delay()
. += dna.species.movement_delay(src)
. = 0
. += ..()
. += config.human_delay
. += dna.species.movement_delay(src)
/mob/living/carbon/human/slip(s_amount, w_amount, obj/O, lube)
if(isobj(shoes) && (shoes.flags&NOSLIP) && !(lube&GALOSHES_DONT_HELP))
@@ -22,7 +22,7 @@
. = 1
/mob/living/carbon/human/mob_negates_gravity()
return ((shoes && shoes.negates_gravity()) || dna.species.negates_gravity())
return ((shoes && shoes.negates_gravity()) || dna.species.negates_gravity(src))
/mob/living/carbon/human/Move(NewLoc, direct)
. = ..()
@@ -60,4 +60,4 @@
/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) //Temporary laziness thing. Will change to handles by species reee.
if(..())
return 1
return dna.species.space_move()
return dna.species.space_move(src)
+55 -105
View File
@@ -1,16 +1,6 @@
/mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = 0)
return dna.species.can_equip(I, slot, disable_warning, src)
/mob/living/carbon/human/proc/equip_in_one_of_slots(obj/item/I, list/slots, qdel_on_fail = 1)
for(var/slot in slots)
if(equip_to_slot_if_possible(I, slots[slot], qdel_on_fail = 0))
return slot
if(qdel_on_fail)
qdel(I)
return null
// Return the item currently in the slot ID
/mob/living/carbon/human/get_item_by_slot(slot_id)
switch(slot_id)
@@ -18,14 +8,12 @@
return back
if(slot_wear_mask)
return wear_mask
if(slot_neck)
return wear_neck
if(slot_handcuffed)
return handcuffed
if(slot_legcuffed)
return legcuffed
if(slot_l_hand)
return l_hand
if(slot_r_hand)
return r_hand
if(slot_belt)
return belt
if(slot_wear_id)
@@ -52,11 +40,48 @@
return s_store
return null
/mob/living/carbon/human/proc/get_all_slots()
. = get_head_slots() | get_body_slots()
/mob/living/carbon/human/proc/get_body_slots()
return list(
back,
s_store,
handcuffed,
legcuffed,
wear_suit,
gloves,
shoes,
belt,
wear_id,
l_store,
r_store,
w_uniform
)
/mob/living/carbon/human/proc/get_head_slots()
return list(
head,
wear_mask,
glasses,
ears,
)
/mob/living/carbon/human/proc/get_storage_slots()
return list(
back,
belt,
l_store,
r_store,
s_store,
)
//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible()
/mob/living/carbon/human/equip_to_slot(obj/item/I, slot)
if(!..()) //a check failed or the item has already found its slot
return
var/not_handled = FALSE //Added in case we make this type path deeper one day
switch(slot)
if(slot_belt)
belt = I
@@ -71,6 +96,8 @@
if(slot_glasses)
glasses = I
var/obj/item/clothing/glasses/G = I
if(G.glass_colour_type)
update_glasses_color(G, 1)
if(G.tint)
update_tint()
if(G.vision_correction)
@@ -108,14 +135,20 @@
else
src << "<span class='danger'>You are trying to equip this item to an unsupported inventory slot. Report this to a coder!</span>"
/mob/living/carbon/human/unEquip(obj/item/I)
//Item is handled and in slot, valid to call callback, for this proc should always be true
if(!not_handled)
I.equipped(src, slot)
return not_handled //For future deeper overrides
/mob/living/carbon/human/doUnEquip(obj/item/I, force)
. = ..() //See mob.dm for an explanation on this and some rage about people copypasting instead of calling ..() like they should.
if(!. || !I)
return
if(I == wear_suit)
if(s_store)
unEquip(s_store, 1) //It makes no sense for your suit storage to stay on you if you drop your suit.
dropItemToGround(s_store, TRUE) //It makes no sense for your suit storage to stay on you if you drop your suit.
if(wear_suit.breakouttime) //when unequipping a straightjacket
update_action_buttons_icon() //certain action buttons may be usable again.
wear_suit = null
@@ -124,13 +157,13 @@
update_inv_wear_suit()
else if(I == w_uniform)
if(r_store)
unEquip(r_store, 1) //Again, makes sense for pockets to drop.
dropItemToGround(r_store, TRUE) //Again, makes sense for pockets to drop.
if(l_store)
unEquip(l_store, 1)
dropItemToGround(l_store, TRUE)
if(wear_id)
unEquip(wear_id)
dropItemToGround(wear_id)
if(belt)
unEquip(belt)
dropItemToGround(belt)
w_uniform = null
update_suit_sensors()
update_inv_w_uniform()
@@ -140,6 +173,8 @@
else if(I == glasses)
glasses = null
var/obj/item/clothing/glasses/G = I
if(G.glass_colour_type)
update_glasses_color(G, 0)
if(G.tint)
update_tint()
if(G.vision_correction)
@@ -192,91 +227,6 @@
sec_hud_set_security_status()
..()
//Cycles through all clothing slots and tests them for destruction
/mob/living/carbon/human/proc/shred_clothing(bomb,shock)
var/covered_parts = 0 //The body parts that are protected by exterior clothing/armor
var/head_absorbed = 0 //How much of the shock the headgear absorbs when it is shredded. -1=it survives
var/suit_absorbed = 0 //How much of the shock the exosuit absorbs when it is shredded. -1=it survives
//Backpacks can never be protected but are annoying as fuck to lose, so they get a lower chance to be shredded
if(back)
back.shred(bomb,shock-20,src)
if(head)
covered_parts |= head.flags_inv
head_absorbed = head.shred(bomb,shock,src)
if(wear_mask)
var/absorbed = ((covered_parts & HIDEMASK) ? head_absorbed : 0) //Check if clothing covering this part absorbed any of the shock
if(absorbed >= 0)
//Masks can be used to shield other parts, but are simplified to simply add their absorbsion to the head armor if it covers the face
var/mask_absorbed = wear_mask.shred(bomb,shock-absorbed,src)
if(wear_mask.flags_inv & HIDEFACE)
covered_parts |= wear_mask.flags_inv
if(mask_absorbed < 0) //If the mask didn't get shredded, everything else on the head is protected
head_absorbed = -1
else
head_absorbed += mask_absorbed
if(ears)
var/absorbed = ((covered_parts & HIDEEARS) ? head_absorbed : 0)
if(absorbed >= 0)
ears.shred(bomb,shock-absorbed,src)
if(glasses)
var/absorbed = ((covered_parts & HIDEEYES) ? head_absorbed : 0)
if(absorbed >= 0)
glasses.shred(bomb,shock-absorbed,src)
if(wear_suit)
covered_parts |= wear_suit.flags_inv
suit_absorbed = wear_suit.shred(bomb,shock,src)
if(gloves)
var/absorbed = ((covered_parts & HIDEGLOVES) ? suit_absorbed : 0)
if(absorbed >= 0)
gloves.shred(bomb,shock-absorbed,src)
if(shoes)
var/absorbed = ((covered_parts & HIDESHOES) ? suit_absorbed : 0)
if(absorbed >= 0)
shoes.shred(bomb,shock-absorbed,src)
if(w_uniform)
var/absorbed = ((covered_parts & HIDEJUMPSUIT) ? suit_absorbed : 0)
if(absorbed >= 0)
w_uniform.shred(bomb,shock-20-absorbed,src) //Uniforms are also annoying to get shredded
/obj/item/proc/shred(bomb,shock,mob/living/carbon/human/Human)
if(flags & ABSTRACT)
return -1
var/shredded
if(!bomb)
if(burn_state != -1)
shredded = 1 //No heat protection, it burns
else
shredded = -1 //Heat protection = Fireproof
else if(shock > 0)
if(prob(max(shock-armor["bomb"],0)))
shredded = armor["bomb"] + 10 //It gets shredded, but it also absorbs the shock the clothes underneath would recieve by this amount
else
shredded = -1 //It survives explosion
if(shredded > 0)
if(Human) //Unequip if equipped
Human.unEquip(src)
if(bomb)
empty_object_contents()
spawn(1) //so the shreds aren't instantly deleted by the explosion
var/obj/effect/decal/cleanable/shreds/Shreds = new(loc)
Shreds.desc = "The sad remains of what used to be [src.name]."
qdel(src)
else
burn()
return shredded
/mob/living/carbon/human/proc/equipOutfit(outfit, visualsOnly = FALSE)
var/datum/outfit/O = null
+58 -21
View File
@@ -1,4 +1,4 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
//NOTE: Breathing happens once per FOUR TICKS, unless the last breath fails. In which case it happens once per ONE TICK! So oxyloss healing is done once per 4 ticks while oxyloss damage is applied once per tick!
@@ -29,24 +29,32 @@
if (notransform)
return
if(..())
if(..()) //not dead
for(var/datum/mutation/human/HM in dna.mutations)
HM.on_life(src)
if(stat != DEAD)
//heart attack stuff
handle_heart()
if(stat != DEAD)
//Stuff jammed in your limbs hurts
handle_embedded_objects()
//Update our name based on whether our face is obscured/disfigured
name = get_visible_name()
dna.species.spec_life(src) // for mutantraces
if(stat != DEAD)
return 1
/mob/living/carbon/human/calculate_affecting_pressure(pressure)
if((wear_suit && (wear_suit.flags & STOPSPRESSUREDMAGE)) && (head && (head.flags & STOPSPRESSUREDMAGE)))
return ONE_ATMOSPHERE
if(ismob(loc))
return ONE_ATMOSPHERE //hopefully won't murderficate people in your guts by going for a spacewalk
else
return pressure
@@ -85,29 +93,54 @@
/mob/living/carbon/human/breathe()
if(!dna.species.breathe(src))
..()
#define HUMAN_MAX_OXYLOSS 3
#define HUMAN_CRIT_MAX_OXYLOSS (SSmob.wait/30)
/mob/living/carbon/human/check_breath(datum/gas_mixture/breath)
dna.species.check_breath(breath, src)
var/L = getorganslot("lungs")
if(!L)
if(health >= HEALTH_THRESHOLD_CRIT)
adjustOxyLoss(HUMAN_MAX_OXYLOSS + 1)
else if(!(NOCRITDAMAGE in dna.species.species_traits))
adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS)
failed_last_breath = 1
if(dna && dna.species)
var/datum/species/S = dna.species
if(S.breathid == "o2")
throw_alert("oxy", /obj/screen/alert/oxy)
else if(S.breathid == "tox")
throw_alert("not_enough_tox", /obj/screen/alert/not_enough_tox)
else if(S.breathid == "co2")
throw_alert("not_enough_co2", /obj/screen/alert/not_enough_co2)
return 0
else
if(istype(L,/obj/item/organ/lungs))
var/obj/item/organ/lungs/lun = L
lun.check_breath(breath,src)
#undef HUMAN_MAX_OXYLOSS
#undef HUMAN_CRIT_MAX_OXYLOSS
/mob/living/carbon/human/handle_environment(datum/gas_mixture/environment)
dna.species.handle_environment(environment, src)
///FIRE CODE
/mob/living/carbon/human/handle_fire()
if(!dna || !dna.species.handle_fire(src))
..()
if(on_fire)
var/thermal_protection = get_thermal_protection()
if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT)
return
if(thermal_protection >= FIRE_SUIT_MAX_TEMP_PROTECT)
bodytemperature += 11
else
bodytemperature += (BODYTEMP_HEATING_MAX + (fire_stacks * 12))
..()
if(dna)
dna.species.handle_fire(src)
/mob/living/carbon/human/proc/get_thermal_protection()
var/thermal_protection = 0 //Simple check to estimate how protected we are against multiple temperatures
if(ismob(loc))
thermal_protection = FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT //because lazy
if(wear_suit)
if(wear_suit.max_heat_protection_temperature >= FIRE_SUIT_MAX_TEMP_PROTECT)
thermal_protection += (wear_suit.max_heat_protection_temperature*0.7)
@@ -133,6 +166,7 @@
//This proc returns a number made up of the flags for body parts which you are protected on. (such as HEAD, CHEST, GROIN, etc. See setup.dm for the full list)
/mob/living/carbon/human/proc/get_heat_protection_flags(temperature) //Temperature is the temperature you're being exposed to.
var/thermal_protection_flags = 0
//Handle normal clothing
if(head)
if(head.max_heat_protection_temperature && head.max_heat_protection_temperature >= temperature)
@@ -217,9 +251,12 @@
if(dna.check_mutation(COLDRES))
return 1 //Fully protected from the cold.
if(dna && (RESISTTEMP in dna.species.specflags))
if(dna && (RESISTCOLD in dna.species.species_traits))
return 1
if(ismob(loc))
return 1 //because lazy
temperature = max(temperature, 2.7) //There is an occasional bug where the temperature is miscalculated in ares with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K.
var/thermal_protection_flags = get_cold_protection_flags(temperature)
@@ -277,7 +314,7 @@
if(head)
if(head.flags & BLOCK_GAS_SMOKE_EFFECT)
. = 1
if(NOBREATH in dna.species.specflags)
if(NOBREATH in dna.species.species_traits)
. = 1
return .
@@ -287,11 +324,11 @@
var/obj/item/bodypart/BP = X
for(var/obj/item/I in BP.embedded_objects)
if(prob(I.embedded_pain_chance))
BP.take_damage(I.w_class*I.embedded_pain_multiplier)
BP.receive_damage(I.w_class*I.embedded_pain_multiplier)
src << "<span class='userdanger'>\the [I] embedded in your [BP.name] hurts!</span>"
if(prob(I.embedded_fall_chance))
BP.take_damage(I.w_class*I.embedded_fall_pain_multiplier)
BP.receive_damage(I.w_class*I.embedded_fall_pain_multiplier)
BP.embedded_objects -= I
I.loc = get_turf(src)
visible_message("<span class='danger'>\the [I] falls out of [name]'s [BP.name]!</span>","<span class='userdanger'>\the [I] falls out of your [BP.name]!</span>")
@@ -301,8 +338,8 @@
/mob/living/carbon/human/proc/handle_heart()
CHECK_DNA_AND_SPECIES(src)
var/needs_heart = (!(NOBLOOD in dna.species.specflags))
var/we_breath = (!(NOBREATH in dna.species.specflags))
var/needs_heart = (!(NOBLOOD in dna.species.species_traits))
var/we_breath = (!(NOBREATH in dna.species.species_traits))
if(heart_attack)
if(!needs_heart)
+1 -1
View File
@@ -51,7 +51,7 @@
CHECK_DNA_AND_SPECIES(src)
// how do species that don't breathe talk? magic, that's what.
if(!(NOBREATH in dna.species.specflags) && !getorganslot("lungs"))
if(!(NOBREATH in dna.species.species_traits) && !getorganslot("lungs"))
return 0
if(mind)
return !mind.miming
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,11 @@
/datum/species/abductor
name = "Abductor"
id = "abductor"
darksight = 3
say_mod = "gibbers"
sexes = 0
species_traits = list(NOBLOOD,NOBREATH,VIRUSIMMUNE,NOGUNS)
mutant_organs = list(/obj/item/organ/tongue/abductor)
var/scientist = 0 // vars to not pollute spieces list with castes
var/agent = 0
var/team = 1
@@ -0,0 +1,21 @@
/datum/species/android
name = "Android"
id = "android"
say_mod = "states"
species_traits = list(NOBREATH,RESISTHOT,RESISTCOLD,RESISTPRESSURE,NOFIRE,NOBLOOD,VIRUSIMMUNE,PIERCEIMMUNE,NOHUNGER,EASYLIMBATTACHMENT)
meat = null
damage_overlay_type = "synth"
mutant_organs = list(/obj/item/organ/tongue/robot)
limbs_id = "synth"
/datum/species/android/on_species_gain(mob/living/carbon/C)
. = ..()
for(var/X in C.bodyparts)
var/obj/item/bodypart/O = X
O.change_bodypart_status(BODYPART_ROBOTIC)
/datum/species/android/on_species_loss(mob/living/carbon/C)
. = ..()
for(var/X in C.bodyparts)
var/obj/item/bodypart/O = X
O.change_bodypart_status(BODYPART_ORGANIC)
@@ -0,0 +1,139 @@
/datum/species/angel
name = "Angel"
id = "angel"
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS)
mutant_bodyparts = list("tail_human", "ears", "wings")
default_features = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "wings" = "Angel")
use_skintones = 1
no_equip = list(slot_back)
blacklisted = 1
limbs_id = "human"
skinned_type = /obj/item/stack/sheet/animalhide/human
var/datum/action/innate/flight/fly
/datum/species/angel/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
..()
if(H.dna && H.dna.species &&((H.dna.features["wings"] != "Angel") && ("wings" in H.dna.species.mutant_bodyparts)))
H.dna.features["wings"] = "Angel"
H.update_body()
if(ishuman(H)&& !fly)
fly = new
fly.Grant(H)
/datum/species/angel/on_species_loss(mob/living/carbon/human/H)
if(fly)
fly.Remove(H)
if(H.movement_type & FLYING)
H.movement_type &= ~FLYING
ToggleFlight(H,0)
if(H.dna && H.dna.species &&((H.dna.features["wings"] != "None") && ("wings" in H.dna.species.mutant_bodyparts)))
H.dna.features["wings"] = "None"
H.update_body()
..()
/datum/species/angel/spec_life(mob/living/carbon/human/H)
HandleFlight(H)
/datum/species/angel/proc/HandleFlight(mob/living/carbon/human/H)
if(H.movement_type & FLYING)
if(!CanFly(H))
ToggleFlight(H,0)
return 0
return 1
else
return 0
/datum/species/angel/proc/CanFly(mob/living/carbon/human/H)
if(H.stat || H.stunned || H.weakened)
return 0
if(H.wear_suit && ((H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)))) //Jumpsuits have tail holes, so it makes sense they have wing holes too
H << "Your suit blocks your wings from extending!"
return 0
var/turf/T = get_turf(H)
if(!T)
return 0
var/datum/gas_mixture/environment = T.return_air()
if(environment && !(environment.return_pressure() > 30))
H << "<span class='warning'>The atmosphere is too thin for you to fly!</span>"
return 0
else
return 1
/datum/action/innate/flight
name = "Toggle Flight"
check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_STUNNED
button_icon_state = "flight"
/datum/action/innate/flight/Activate()
var/mob/living/carbon/human/H = owner
var/datum/species/angel/A = H.dna.species
if(A.CanFly(H))
if(H.movement_type & FLYING)
H << "<span class='notice'>You settle gently back onto the ground...</span>"
A.ToggleFlight(H,0)
H.update_canmove()
else
H << "<span class='notice'>You beat your wings and begin to hover gently above the ground...</span>"
H.resting = 0
A.ToggleFlight(H,1)
H.update_canmove()
/datum/species/angel/proc/flyslip(mob/living/carbon/human/H)
var/obj/buckled_obj
if(H.buckled)
buckled_obj = H.buckled
H << "<span class='notice'>Your wings spazz out and launch you!</span>"
playsound(H.loc, 'sound/misc/slip.ogg', 50, 1, -3)
for(var/obj/item/I in H.held_items)
H.accident(I)
var/olddir = H.dir
H.stop_pulling()
if(buckled_obj)
buckled_obj.unbuckle_mob(H)
step(buckled_obj, olddir)
else
for(var/i=1, i<5, i++)
spawn (i)
step(H, olddir)
H.spin(1,1)
return 1
/datum/species/angel/spec_stun(mob/living/carbon/human/H,amount)
if(H.movement_type & FLYING)
ToggleFlight(H,0)
flyslip(H)
. = ..()
/datum/species/angel/negates_gravity(mob/living/carbon/human/H)
if(H.movement_type & FLYING)
return 1
/datum/species/angel/space_move(mob/living/carbon/human/H)
if(H.movement_type & FLYING)
return 1
/datum/species/angel/proc/ToggleFlight(mob/living/carbon/human/H,flight)
if(flight && CanFly(H))
stunmod = 2
speedmod = -1
H.movement_type |= FLYING
override_float = 1
H.pass_flags |= PASSTABLE
H.OpenWings()
else
stunmod = 1
speedmod = 0
H.movement_type &= ~FLYING
override_float = 0
H.pass_flags &= ~PASSTABLE
H.CloseWings()
@@ -0,0 +1,19 @@
/datum/species/corporate
name = "Corporate Agent"
id = "agent"
hair_alpha = 0
say_mod = "declares"
speedmod = -2//Fast
brutemod = 0.7//Tough against firearms
burnmod = 0.65//Tough against lasers
coldmod = 0
heatmod = 0.5//it's a little tough to burn them to death not as hard though.
punchdamagelow = 20
punchdamagehigh = 30//they are inhumanly strong
punchstunthreshold = 25
attack_verb = "smash"
attack_sound = "sound/weapons/resonator_blast.ogg"
blacklisted = 1
use_skintones = 0
species_traits = list(RADIMMUNE,VIRUSIMMUNE,NOBLOOD,PIERCEIMMUNE,EYECOLOR,NODISMEMBER,NOHUNGER)
sexes = 0
@@ -0,0 +1,29 @@
/datum/species/fly
name = "Flyperson"
id = "fly"
say_mod = "buzzes"
mutant_organs = list(/obj/item/organ/tongue/fly)
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/fly
/datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(chem.id == "pestkiller")
H.adjustToxLoss(3)
H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM)
return 1
/datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(istype(chem,/datum/reagent/consumable))
var/datum/reagent/consumable/nutri_check = chem
if(nutri_check.nutriment_factor > 0)
var/turf/pos = get_turf(H)
H.vomit(0, 0, 0, 1, 1)
playsound(pos, 'sound/effects/splat.ogg', 50, 1)
H.visible_message("<span class='danger'>[H] vomits on the floor!</span>", \
"<span class='userdanger'>You throw up on the floor!</span>")
..()
/datum/species/fly/check_weakness(obj/item/weapon, mob/living/attacker)
if(istype(weapon,/obj/item/weapon/melee/flyswatter))
return 29 //Flyswatters deal 30x damage to flypeople.
return 0
@@ -0,0 +1,214 @@
datum/species/canid
name = "Canid"
id = "canid"
default_color = "4B4B4B"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR)
// subspecies = list("fox")
mutant_bodyparts = list("mam_tail", "mam_ears", "mam_body_markings", "snout", "legs")
default_features = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "body_markings" = "None", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "None")
attack_verb = "claw"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
roundstart = 1
/datum/species/canid/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
H.endTailWag()
//FELID//
/datum/species/felid
name = "Felid"
id = "felid"
default_color = "BCAC9B"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR)
mutant_bodyparts = list("mam_body_markings", "mam_ears", "mam_tail", "snout", "legs")
default_features = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_body_markings" = "Belly", "mam_ears" = "Big Cat", "mam_tail" = "Big Cat")
attack_verb = "claw"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
roundstart = 1 //no sprites yet
/datum/species/tajaran/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
H.endTailWag()
//Mammal//
/datum/species/ailurus
name = "Ailurus"
id = "ailurus"
default_color = "BCAC9B"
species_traits = list(EYECOLOR,LIPS,HAIR)
mutant_bodyparts = list("mam_tail")
default_features = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF","mam_tail" = "ailurus")
attack_verb = "claw"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
roundstart = 1 //no sprites yet
//AVIAN//
/datum/species/avian
name = "Avian"
id = "avian"
default_color = "BCAC9B"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR)
mutant_bodyparts = list("beak", "wings", "avian_tail")
default_features = list("beak" = "None", "wings" = "None")
attack_verb = "peck"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
roundstart = 0 //no sprites yet
blacklisted = 1
//AQUATIC//
/datum/species/shark
name = "Shark"
id = "shark"
default_color = "BCAC9B"
species_traits = list(EYECOLOR,LIPS,HAIR)
mutant_bodyparts = list("mam_tail")
default_features = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF","mam_tail" = "shark")
attack_verb = "bite"
attack_sound = 'sound/weapons/bite.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
roundstart = 1 //no sprites yet
//INSECT//
/datum/species/moth
name = "Moth"
id = "moth"
default_color = "BCAC9B"
species_traits = list(EYECOLOR,LIPS,HAIR)
attack_verb = "flutter" //wat?
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
roundstart = 1 //no sprites yet
//HERBIVOROUS//
//EXOTIC//
//These races will likely include lots of downsides and upsides. Keep them relatively balanced.//
/datum/species/xeno
name = "Xenomorph"
id = "xeno"
say_mod = "hisses"
eyes = "none"
species_traits = list()
mutant_organs = list(/obj/item/organ/tongue/alien)
mutant_bodyparts = list("xenohead",
"xenodorsal",
"xenotail")
default_features = list("xenohead"="Hunter",
"xenodorsal"="Dorsal Tubes",
"xenotail"="Xenomorph Tail")
attack_verb = "slash"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
burnmod = 1.75
heatmod = 1.75
darksight = 4 //Just above slimes
exotic_blood = "xblood"
damage_overlay_type = "xeno"
no_equip = list(slot_glasses) //MY EYES, THEY'RE GONE
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno
skinned_type = /obj/item/stack/sheet/animalhide/xeno
// safe_toxins_max = 32 //Too much of anything is bad.
roundstart = 0
// whitelisted = 1
// whitelist = list("talkingcactus") //testing whitelisting
/datum/species/xeno/on_species_gain(mob/living/carbon/C, datum/species/old_species)
..()
var/obj/effect/decal/cleanable/xenoblood/xgibs/XG
if(istype(C.gib_type, XG))
return
else
C.gib_type = XG
/datum/species/xeno/on_species_loss(mob/living/carbon/C)
..()
var/obj/effect/decal/cleanable/xenoblood/xgibs/XG
var/obj/effect/decal/cleanable/blood/gibs/HG
if(istype(C.gib_type, XG))
C.gib_type = HG
else
return
/datum/reagent/toxin/acid/xenoblood
name = "acid blood"
id = "xblood"
description = "A highly corrosive substance, it is capable of burning through most natural or man-made materials in short order."
color = "#66CC00"
toxpwr = 0
acidpwr = 12
/*
/datum/species/yautja
name = "Yautja"
id = "pred"
say_mod = "clicks"
eyes = "predeyes"
mutant_organs = list(/obj/item/organ/tongue/yautja)
specflags = list(EYECOLOR)
lang_spoken = YAUTJA
lang_understood = HUMAN|YAUTJA|ALIEN
no_equip = list(slot_head)
punchdamagelow = 4
punchdamagehigh = 14
punchstunthreshold = 13
blacklisted = 1
roundstart = 0
whitelist = 1
whitelist = list("talkingcactus")
/datum/outfit/yautja_basic
name = "Yautja, Basic"
uniform = /obj/item/clothing/under/mesh
suit = /obj/item/clothing/suit/armor/yautja_fake
shoes = /obj/item/clothing/shoes/yautja_fake
mask = /obj/item/clothing/mask/gas/yautja_fake
/datum/species/yautja/before_equip_job(datum/job/J, mob/living/carbon/human/H, visualsOnly = FALSE)
var/datum/outfit/yautja_basic/O = new /datum/outfit/yautja_basic//Just basic gear. Doesn't include anything that gives any meaningful advantage.
H.equipOutfit(O, visualsOnly)
return 0*/
/datum/species/octopus
blacklisted = 1
/datum/species/carp
blacklisted = 1
/datum/species/horse
blacklisted = 1
///////////////////
//DONATOR SPECIES//
///////////////////
//ChronoFlux: Slimecoon
/*
/datum/species/jelly/slime/slimecoon
name = "Slime Raccoon"
id = "slimecoon"
limbs_id = "slime"
whitelisted = 1
whitelist = list("chronoflux")
blacklisted = 1
mutant_bodyparts = list("slimecoontail", "slimecoonears", "slimecoonsnout")
default_features = list("slimecoontail" = "Slimecoon Tail", "slimecoonears" = "Slimecoon Ears", "slimecoonsnout" = "Slimecoon Snout")*/
/datum/species/shark/datashark
name = "DataShark"
id = "datashark"
default_color = "BCAC9B"
species_traits = list(EYECOLOR,LIPS,HAIR)
mutant_bodyparts = list("mam_tail")
default_features = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF","mam_tail" = "datashark")
attack_verb = "bite"
attack_sound = 'sound/weapons/bite.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
roundstart = 1 //no sprites yet
whitelisted = 1
whitelist = list("rubyflamewing")
blacklisted = 0
@@ -0,0 +1,447 @@
/datum/species/golem
// Animated beings of stone. They have increased defenses, and do not need to breathe. They're also slow as fuuuck.
name = "Golem"
id = "iron"
species_traits = list(NOBREATH,RESISTHOT,RESISTCOLD,RESISTPRESSURE,NOFIRE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,MUTCOLORS)
speedmod = 2
armor = 55
siemens_coeff = 0
punchdamagelow = 5
punchdamagehigh = 14
punchstunthreshold = 11 //about 40% chance to stun
no_equip = list(slot_wear_mask, slot_wear_suit, slot_gloves, slot_shoes, slot_w_uniform)
nojumpsuit = 1
sexes = 1
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/golem
// To prevent golem subtypes from overwhelming the odds when random species
// changes, only the Random Golem type can be chosen
blacklisted = TRUE
dangerous_existence = TRUE
limbs_id = "golem"
fixed_mut_color = "aaa"
var/info_text = "As an <span class='danger'>Iron Golem</span>, you don't have any special traits."
/datum/species/golem/random
name = "Random Golem"
blacklisted = FALSE
dangerous_existence = FALSE
/datum/species/golem/random/on_species_gain(mob/living/carbon/C, datum/species/old_species)
..()
var/list/golem_types = typesof(/datum/species/golem) - src.type
var/datum/species/golem/golem_type = pick(golem_types)
var/mob/living/carbon/human/H = C
H.set_species(golem_type)
H << "[initial(golem_type.info_text)]"
/datum/species/golem/adamantine
name = "Adamantine Golem"
id = "adamantine"
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/golem/adamantine
fixed_mut_color = "4ed"
info_text = "As an <span class='danger'>Adamantine Golem</span>, you don't have any special traits."
//Explodes on death
/datum/species/golem/plasma
name = "Plasma Golem"
id = "plasma"
fixed_mut_color = "a3d"
meat = /obj/item/weapon/ore/plasma
//Can burn and takes damage from heat
species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,MUTCOLORS)
info_text = "As a <span class='danger'>Plasma Golem</span>, you explode on death!"
burnmod = 1.5
/datum/species/golem/plasma/spec_death(gibbed, mob/living/carbon/human/H)
explosion(get_turf(H),0,1,2,flame_range = 5)
if(H)
H.gib()
//Harder to hurt
/datum/species/golem/diamond
name = "Diamond Golem"
id = "diamond"
fixed_mut_color = "0ff"
armor = 70 //up from 55
meat = /obj/item/weapon/ore/diamond
info_text = "As a <span class='danger'>Diamond Golem</span>, you are more resistant than the average golem."
//Faster but softer and less armoured
/datum/species/golem/gold
name = "Gold Golem"
id = "gold"
fixed_mut_color = "cc0"
speedmod = 1
armor = 25 //down from 55
meat = /obj/item/weapon/ore/gold
info_text = "As a <span class='danger'>Gold Golem</span>, you are faster but less resistant than the average golem."
//Heavier, thus higher chance of stunning when punching
/datum/species/golem/silver
name = "Silver Golem"
id = "silver"
fixed_mut_color = "ddd"
punchstunthreshold = 9 //60% chance, from 40%
meat = /obj/item/weapon/ore/silver
info_text = "As a <span class='danger'>Silver Golem</span>, your attacks are heavier and have a higher chance of stunning."
//Harder to stun, deals more damage, but it's even slower
/datum/species/golem/plasteel
name = "Plasteel Golem"
id = "plasteel"
fixed_mut_color = "bbb"
stunmod = 0.40
punchdamagelow = 12
punchdamagehigh = 21
punchstunthreshold = 18 //still 40% stun chance
speedmod = 4 //pretty fucking slow
meat = /obj/item/weapon/ore/iron
info_text = "As a <span class='danger'>Plasteel Golem</span>, you are slower, but harder to stun, and hit very hard when punching."
attack_verb = "smash"
attack_sound = "sound/effects/meteorimpact.ogg" //hits pretty hard
//Immune to ash storms
/datum/species/golem/titanium
name = "Titanium Golem"
id = "titanium"
fixed_mut_color = "fff"
meat = /obj/item/weapon/ore/titanium
info_text = "As a <span class='danger'>Titanium Golem</span>, you are immune to ash storms, and slightly more resistant to burn damage."
burnmod = 0.9
/datum/species/golem/titanium/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
C.weather_immunities |= "ash"
/datum/species/golem/titanium/on_species_loss(mob/living/carbon/C)
. = ..()
C.weather_immunities -= "ash"
//Immune to ash storms and lava
/datum/species/golem/plastitanium
name = "Plastitanium Golem"
id = "plastitanium"
fixed_mut_color = "888"
meat = /obj/item/weapon/ore/titanium
info_text = "As a <span class='danger'>Plastitanium Golem</span>, you are immune to both ash storms and lava, and slightly more resistant to burn damage."
burnmod = 0.8
/datum/species/golem/plastitanium/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
C.weather_immunities |= "lava"
C.weather_immunities |= "ash"
/datum/species/golem/plastitanium/on_species_loss(mob/living/carbon/C)
. = ..()
C.weather_immunities -= "ash"
C.weather_immunities -= "lava"
//Fast and regenerates... but can only speak like an abductor
/datum/species/golem/alloy
name = "Alien Alloy Golem"
id = "alloy"
fixed_mut_color = "333"
meat = /obj/item/stack/sheet/mineral/abductor
mutant_organs = list(/obj/item/organ/tongue/abductor) //abductor tongue
speedmod = 1 //faster
info_text = "As an <span class='danger'>Alloy Golem</span>, you are made of advanced alien materials: you are faster and regenerate over time. You are, however, only able to be heard by other alloy golems."
//Regenerates because self-repairing super-advanced alien tech
/datum/species/golem/alloy/spec_life(mob/living/carbon/human/H)
if(H.stat == DEAD)
return
H.heal_overall_damage(2,2)
H.adjustToxLoss(-2)
H.adjustOxyLoss(-2)
//Since this will usually be created from a collaboration between podpeople and free golems, wood golems are a mix between the two races
/datum/species/golem/wood
name = "Wood Golem"
id = "wood"
fixed_mut_color = "49311c"
meat = /obj/item/stack/sheet/mineral/wood
//Can burn and take damage from heat
species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,MUTCOLORS)
armor = 30
burnmod = 1.25
heatmod = 1.5
info_text = "As a <span class='danger'>Wooden Golem</span>, you have plant-like traits: you take damage from extreme temperatures, can be set on fire, and have lower armor than a normal golem. You regenerate when in the light and wither in the darkness."
/datum/species/golem/wood/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
C.faction |= "plants"
C.faction |= "vines"
/datum/species/golem/wood/on_species_loss(mob/living/carbon/C)
. = ..()
C.faction -= "plants"
C.faction -= "vines"
/datum/species/golem/wood/spec_life(mob/living/carbon/human/H)
if(H.stat == DEAD)
return
var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing
if(isturf(H.loc)) //else, there's considered to be no light
var/turf/T = H.loc
light_amount = min(10,T.get_lumcount()) - 5
H.nutrition += light_amount
if(H.nutrition > NUTRITION_LEVEL_FULL)
H.nutrition = NUTRITION_LEVEL_FULL
if(light_amount > 2) //if there's enough light, heal
H.heal_overall_damage(1,1)
H.adjustToxLoss(-1)
H.adjustOxyLoss(-1)
if(H.nutrition < NUTRITION_LEVEL_STARVING + 50)
H.take_overall_damage(2,0)
/datum/species/golem/wood/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(chem.id == "plantbgone")
H.adjustToxLoss(3)
H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM)
return 1
//Radioactive
/datum/species/golem/uranium
name = "Uranium Golem"
id = "uranium"
fixed_mut_color = "7f0"
meat = /obj/item/weapon/ore/uranium
info_text = "As an <span class='danger'>Uranium Golem</span>, you emit radiation pulses every once in a while. It won't harm fellow golems, but organic lifeforms will be affected."
var/last_event = 0
var/active = null
/datum/species/golem/uranium/spec_life(mob/living/carbon/human/H)
if(!active)
if(world.time > last_event+30)
active = 1
radiation_pulse(get_turf(H), 3, 3, 5, 0)
last_event = world.time
active = null
..()
//Immune to physical bullets and resistant to brute, but very vulnerable to burn damage. Dusts on death.
/datum/species/golem/sand
name = "Sand Golem"
id = "sand"
fixed_mut_color = "ffdc8f"
meat = /obj/item/weapon/ore/glass //this is sand
armor = 0
burnmod = 3 //melts easily
brutemod = 0.25
info_text = "As a <span class='danger'>Sand Golem</span>, you are immune to physical bullets and take very little brute damage, but are extremely vulnerable to burn damage. You will also turn to sand when dying, preventing any form of recovery."
attack_sound = "sound/effects/shovel_dig.ogg"
/datum/species/golem/sand/spec_death(gibbed, mob/living/carbon/human/H)
H.visible_message("<span class='danger'>[H] turns into a pile of sand!</span>")
for(var/obj/item/W in H)
H.dropItemToGround(W)
for(var/i=1, i <= rand(3,5), i++)
new /obj/item/weapon/ore/glass(get_turf(H))
qdel(H)
/datum/species/golem/sand/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H)
if(!(P.original == H && P.firer == H))
if(P.flag == "bullet" || P.flag == "bomb")
playsound(H, "sound/effects/shovel_dig.ogg", 70, 1)
H.visible_message("<span class='danger'>The [P.name] sinks harmlessly in [H]'s sandy body!</span>", \
"<span class='userdanger'>The [P.name] sinks harmlessly in [H]'s sandy body!</span>")
return 2
return 0
//Reflects lasers and resistant to burn damage, but very vulnerable to brute damage. Shatters on death.
/datum/species/golem/glass
name = "Glass Golem"
id = "glass"
fixed_mut_color = "5a96b4aa" //transparent body
meat = /obj/item/weapon/shard
armor = 0
brutemod = 3 //very fragile
burnmod = 0.25
info_text = "As a <span class='danger'>Glass Golem</span>, you reflect lasers and energy weapons, and are very resistant to burn damage, but you are extremely vulnerable to brute damage. On death, you'll shatter beyond any hope of recovery."
attack_sound = "sound/effects/Glassbr2.ogg"
/datum/species/golem/glass/spec_death(gibbed, mob/living/carbon/human/H)
playsound(H, "shatter", 70, 1)
H.visible_message("<span class='danger'>[H] shatters!</span>")
for(var/obj/item/W in H)
H.dropItemToGround(W)
for(var/i=1, i <= rand(3,5), i++)
new /obj/item/weapon/shard(get_turf(H))
qdel(H)
/datum/species/golem/glass/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H)
if(!(P.original == H && P.firer == H)) //self-shots don't reflect
if(P.flag == "laser" || P.flag == "energy")
H.visible_message("<span class='danger'>The [P.name] gets reflected by [H]'s glass skin!</span>", \
"<span class='userdanger'>The [P.name] gets reflected by [H]'s glass skin!</span>")
if(P.starting)
var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/turf/curloc = get_turf(H)
// redirect the projectile
P.original = locate(new_x, new_y, P.z)
P.starting = curloc
P.current = curloc
P.firer = H
P.yo = new_y - curloc.y
P.xo = new_x - curloc.x
P.Angle = null
return -1
return 0
//Teleports when hit or when it wants to
/datum/species/golem/bluespace
name = "Bluespace Golem"
id = "bluespace"
fixed_mut_color = "33f"
meat = /obj/item/weapon/ore/bluespace_crystal
info_text = "As a <span class='danger'>Bluespace Golem</span>, are spatially unstable: you will teleport when hit, and you can teleport manually at a long distance."
attack_verb = "bluespace punch"
attack_sound = "sound/effects/phasein.ogg"
var/datum/action/innate/unstable_teleport/unstable_teleport
var/teleport_cooldown = 100
var/last_teleport = 0
/datum/species/golem/bluespace/proc/reactive_teleport(mob/living/carbon/human/H)
H.visible_message("<span class='warning'>[H] teleports!</span>", "<span class='danger'>You destabilize and teleport!</span>")
new /obj/effect/particle_effect/sparks(get_turf(H))
playsound(get_turf(H), "sparks", 50, 1)
do_teleport(H, get_turf(H), 6, asoundin = 'sound/weapons/emitter2.ogg')
last_teleport = world.time
/datum/species/golem/bluespace/spec_hitby(atom/movable/AM, mob/living/carbon/human/H)
..()
var/obj/item/I
if(istype(AM, /obj/item))
I = AM
if(I.thrownby == H) //No throwing stuff at yourself to trigger the teleport
return 0
else
reactive_teleport(H)
/datum/species/golem/bluespace/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style = M.martial_art)
..()
if(world.time > last_teleport + teleport_cooldown && M != H && M.a_intent != INTENT_HELP)
reactive_teleport(H)
/datum/species/golem/bluespace/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
..()
if(world.time > last_teleport + teleport_cooldown && user != H)
reactive_teleport(H)
/datum/species/golem/bluespace/on_hit(obj/item/projectile/P, mob/living/carbon/human/H)
..()
if(world.time > last_teleport + teleport_cooldown)
reactive_teleport(H)
/datum/species/golem/bluespace/on_species_gain(mob/living/carbon/C, datum/species/old_species)
..()
if(ishuman(C))
unstable_teleport = new
unstable_teleport.Grant(C)
/datum/species/golem/bluespace/on_species_loss(mob/living/carbon/C)
if(unstable_teleport)
unstable_teleport.Remove(C)
..()
/datum/action/innate/unstable_teleport
name = "Unstable Teleport"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "jaunt"
var/cooldown = 150
var/last_teleport = 0
/datum/action/innate/unstable_teleport/IsAvailable()
if(..())
if(world.time > last_teleport + cooldown)
return 1
return 0
/datum/action/innate/unstable_teleport/Activate()
var/mob/living/carbon/human/H = owner
H.visible_message("<span class='warning'>[H] starts vibrating!</span>", "<span class='danger'>You start charging your bluespace core...</span>")
playsound(get_turf(H), 'sound/weapons/flash.ogg', 25, 1)
addtimer(CALLBACK(src, .proc/teleport, H), 15)
/datum/action/innate/unstable_teleport/proc/teleport(mob/living/carbon/human/H)
H.visible_message("<span class='warning'>[H] disappears in a shower of sparks!</span>", "<span class='danger'>You teleport!</span>")
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread
spark_system.set_up(10, 0, src)
spark_system.attach(H)
spark_system.start()
do_teleport(H, get_turf(H), 12, asoundin = 'sound/weapons/emitter2.ogg')
last_teleport = world.time
UpdateButtonIcon() //action icon looks unavailable
sleep(cooldown + 5)
UpdateButtonIcon() //action icon looks available again
//honk
/datum/species/golem/bananium
name = "Bananium Golem"
id = "bananium"
fixed_mut_color = "ff0"
say_mod = "honks"
punchdamagelow = 0
punchdamagehigh = 1
punchstunthreshold = 2 //Harmless and can't stun
meat = /obj/item/weapon/ore/bananium
info_text = "As a <span class='danger'>Bananium Golem</span>, you are made for pranking. Your body emits natural honks, and you cannot hurt people when punching them. Your skin also emits bananas when damaged."
attack_verb = "honk"
attack_sound = "sound/items/AirHorn2.ogg"
var/last_honk = 0
var/honkooldown = 0
var/last_banana = 0
var/banana_cooldown = 100
var/active = null
/datum/species/golem/bananium/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style = M.martial_art)
..()
if(world.time > last_banana + banana_cooldown && M != H && M.a_intent != INTENT_HELP)
new/obj/item/weapon/grown/bananapeel/specialpeel(get_turf(H))
last_banana = world.time
/datum/species/golem/bananium/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
..()
if(world.time > last_banana + banana_cooldown && user != H)
new/obj/item/weapon/grown/bananapeel/specialpeel(get_turf(H))
last_banana = world.time
/datum/species/golem/bananium/on_hit(obj/item/projectile/P, mob/living/carbon/human/H)
..()
if(world.time > last_banana + banana_cooldown)
new/obj/item/weapon/grown/bananapeel/specialpeel(get_turf(H))
last_banana = world.time
/datum/species/golem/bananium/spec_hitby(atom/movable/AM, mob/living/carbon/human/H)
..()
var/obj/item/I
if(istype(AM, /obj/item))
I = AM
if(I.thrownby == H) //No throwing stuff at yourself to make bananas
return 0
else
new/obj/item/weapon/grown/bananapeel/specialpeel(get_turf(H))
last_banana = world.time
/datum/species/golem/bananium/spec_life(mob/living/carbon/human/H)
if(!active)
if(world.time > last_honk + honkooldown)
active = 1
playsound(get_turf(H), 'sound/items/bikehorn.ogg', 50, 1)
last_honk = world.time
honkooldown = rand(20, 80)
active = null
..()
/datum/species/golem/bananium/spec_death(gibbed, mob/living/carbon/human/H)
playsound(get_turf(H), 'sound/misc/sadtrombone.ogg', 70, 0)
/datum/species/golem/bananium/get_spans()
return list(SPAN_CLOWN)
@@ -0,0 +1,25 @@
/datum/species/human
name = "Human"
id = "human"
default_color = "FFFFFF"
species_traits = list(MUTCOLORS_PARTSONLY,EYECOLOR,HAIR,FACEHAIR,LIPS)
mutant_bodyparts = list("tail_human", "ears")
default_features = list("tail_human" = "None", "ears" = "None")
use_skintones = 1
skinned_type = /obj/item/stack/sheet/animalhide/human
/datum/species/human/qualifies_for_rank(rank, list/features)
if((!features["tail_human"] || features["tail_human"] == "None") && (!features["ears"] || features["ears"] == "None"))
return TRUE //Pure humans are always allowed in all roles.
return ..()
//Curiosity killed the cat's wagging tail.
/datum/species/human/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
H.endTailWag()
/datum/species/human/space_move(mob/living/carbon/human/H)
var/obj/item/device/flightpack/F = H.get_flightpack()
if(istype(F) && (F.flight) && F.allow_thrust(0.01, src))
return TRUE
@@ -0,0 +1,331 @@
/datum/species/jelly
// Entirely alien beings that seem to be made entirely out of gel. They have three eyes and a skeleton visible within them.
name = "Xenobiological Jelly Entity"
id = "jelly"
default_color = "00FF90"
say_mod = "chirps"
eyes = "jelleyes"
species_traits = list(MUTCOLORS,EYECOLOR,NOBLOOD,VIRUSIMMUNE,TOXINLOVER)
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/slime
exotic_blood = "slimejelly"
var/datum/action/innate/regenerate_limbs/regenerate_limbs
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
if(regenerate_limbs)
regenerate_limbs.Remove(C)
..()
/datum/species/jelly/on_species_gain(mob/living/carbon/C, datum/species/old_species)
..()
if(ishuman(C))
regenerate_limbs = new
regenerate_limbs.Grant(C)
/datum/species/jelly/spec_life(mob/living/carbon/human/H)
if(H.stat == DEAD) //can't farm slime jelly from a dead slime/jelly person indefinitely
return
if(!H.blood_volume)
H.blood_volume += 5
H.adjustBruteLoss(5)
H << "<span class='danger'>You feel empty!</span>"
if(H.blood_volume < BLOOD_VOLUME_NORMAL)
if(H.nutrition >= NUTRITION_LEVEL_STARVING)
H.blood_volume += 3
H.nutrition -= 2.5
if(H.blood_volume < BLOOD_VOLUME_OKAY)
if(prob(5))
H << "<span class='danger'>You feel drained!</span>"
if(H.blood_volume < BLOOD_VOLUME_BAD)
Cannibalize_Body(H)
H.update_action_buttons_icon()
/datum/species/jelly/proc/Cannibalize_Body(mob/living/carbon/human/H)
var/list/limbs_to_consume = list("r_arm", "l_arm", "r_leg", "l_leg") - H.get_missing_limbs()
var/obj/item/bodypart/consumed_limb
if(!limbs_to_consume.len)
H.losebreath++
return
if(H.get_num_legs()) //Legs go before arms
limbs_to_consume -= list("r_arm", "l_arm")
consumed_limb = H.get_bodypart(pick(limbs_to_consume))
consumed_limb.drop_limb()
H << "<span class='userdanger'>Your [consumed_limb] is drawn back into your body, unable to maintain its shape!</span>"
qdel(consumed_limb)
H.blood_volume += 20
/datum/action/innate/regenerate_limbs
name = "Regenerate Limbs"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "slimeheal"
background_icon_state = "bg_alien"
/datum/action/innate/regenerate_limbs/IsAvailable()
if(..())
var/mob/living/carbon/human/H = owner
var/list/limbs_to_heal = H.get_missing_limbs()
if(limbs_to_heal.len < 1)
return 0
if(H.blood_volume >= BLOOD_VOLUME_OKAY+40)
return 1
return 0
/datum/action/innate/regenerate_limbs/Activate()
var/mob/living/carbon/human/H = owner
var/list/limbs_to_heal = H.get_missing_limbs()
if(limbs_to_heal.len < 1)
H << "<span class='notice'>You feel intact enough as it is.</span>"
return
H << "<span class='notice'>You focus intently on your missing [limbs_to_heal.len >= 2 ? "limbs" : "limb"]...</span>"
if(H.blood_volume >= 40*limbs_to_heal.len+BLOOD_VOLUME_OKAY)
H.regenerate_limbs()
H.blood_volume -= 40*limbs_to_heal.len
H << "<span class='notice'>...and after a moment you finish reforming!</span>"
return
else if(H.blood_volume >= 40)//We can partially heal some limbs
while(H.blood_volume >= BLOOD_VOLUME_OKAY+40)
var/healed_limb = pick(limbs_to_heal)
H.regenerate_limb(healed_limb)
limbs_to_heal -= healed_limb
H.blood_volume -= 40
H << "<span class='warning'>...but there is not enough of you to fix everything! You must attain more mass to heal completely!</span>"
return
H << "<span class='warning'>...but there is not enough of you to go around! You must attain more mass to heal!</span>"
////////////////////////////////////////////////////////SLIME PEOPLE///////////////////////////////////////////////////////////////////
/datum/species/jelly/slime
// Humans mutated by slime mutagen, produced from green slimes. They are not targetted by slimes.
name = "Slimeperson"
id = "slime"
default_color = "00FFFF"
darksight = 3
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,NOBLOOD,VIRUSIMMUNE, TOXINLOVER)
say_mod = "says"
eyes = "eyes"
hair_color = "mutcolor"
hair_alpha = 150
ignored_by = list(/mob/living/simple_animal/slime)
burnmod = 0.5
coldmod = 2
heatmod = 0.5
var/datum/action/innate/split_body/slime_split
var/list/mob/living/carbon/bodies
var/datum/action/innate/swap_body/swap_body
/datum/species/jelly/slime/on_species_loss(mob/living/carbon/C)
if(slime_split)
slime_split.Remove(C)
if(swap_body)
swap_body.Remove(C)
bodies -= C // This means that the other bodies maintain a link
// so if someone mindswapped into them, they'd still be shared.
bodies = null
C.faction -= "slime"
C.blood_volume = min(C.blood_volume, BLOOD_VOLUME_NORMAL)
..()
/datum/species/jelly/slime/on_species_gain(mob/living/carbon/C, datum/species/old_species)
..()
if(ishuman(C))
/* slime_split = new
slime_split.Grant(C)
swap_body = new
swap_body.Grant(C) */
if(!bodies || !bodies.len)
bodies = list(C)
else
bodies |= C
C.faction |= "slime"
/datum/species/jelly/slime/spec_life(mob/living/carbon/human/H)
if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT)
if(prob(5))
H << "<span class='notice'>You feel very bloated!</span>"
else if(H.nutrition >= NUTRITION_LEVEL_WELL_FED)
H.blood_volume += 3
H.nutrition -= 2.5
..()
/datum/action/innate/split_body
name = "Split Body"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "slimesplit"
background_icon_state = "bg_alien"
/datum/action/innate/split_body/IsAvailable()
if(..())
var/mob/living/carbon/human/H = owner
if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT)
return 1
return 0
/datum/action/innate/split_body/Activate()
var/mob/living/carbon/human/H = owner
if(!isslimeperson(H))
return
CHECK_DNA_AND_SPECIES(H)
H.visible_message("<span class='notice'>[owner] gains a look of \
concentration while standing perfectly still.</span>",
"<span class='notice'>You focus intently on moving your body while \
standing perfectly still...</span>")
H.notransform = TRUE
if(do_after(owner, delay=60, needhand=FALSE, target=owner, progress=TRUE))
if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT)
make_dupe()
else
H << "<span class='warning'>...but there is not enough of you to \
go around! You must attain more mass to split!</span>"
else
H << "<span class='warning'>...but fail to stand perfectly still!\
</span>"
H.notransform = FALSE
/datum/action/innate/split_body/proc/make_dupe()
var/mob/living/carbon/human/H = owner
CHECK_DNA_AND_SPECIES(H)
var/mob/living/carbon/human/spare = new /mob/living/carbon/human(H.loc)
spare.underwear = "Nude"
H.dna.transfer_identity(spare, transfer_SE=1)
spare.dna.features["mcolor"] = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F")
spare.real_name = spare.dna.real_name
spare.name = spare.dna.real_name
spare.updateappearance(mutcolor_update=1)
spare.domutcheck()
spare.Move(get_step(H.loc, pick(NORTH,SOUTH,EAST,WEST)))
H.blood_volume = BLOOD_VOLUME_SAFE
H.notransform = 0
var/datum/species/jelly/slime/origin_datum = H.dna.species
origin_datum.bodies |= spare
var/datum/species/jelly/slime/spare_datum = spare.dna.species
spare_datum.bodies = origin_datum.bodies
H.mind.transfer_to(spare)
spare.visible_message("<span class='warning'>[H] distorts as a new body \
\"steps out\" of them.</span>",
"<span class='notice'>...and after a moment of disorentation, \
you're besides yourself!</span>")
/datum/action/innate/swap_body
name = "Swap Body"
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "slimeswap"
background_icon_state = "bg_alien"
/datum/action/innate/swap_body/Activate()
if(!isslimeperson(owner))
owner << "<span class='warning'>You are not a slimeperson.</span>"
Remove(owner)
else
ui_interact(owner)
/datum/action/innate/swap_body/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = conscious_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "slime_swap_body", name, 400, 400, master_ui, state)
ui.open()
/datum/action/innate/swap_body/ui_data(mob/user)
var/mob/living/carbon/human/H = owner
if(!isslimeperson(H))
return
var/datum/species/jelly/slime/SS = H.dna.species
var/list/data = list()
data["bodies"] = list()
for(var/b in SS.bodies)
if(!b || qdeleted(b) || !isslimeperson(b))
SS.bodies -= b
continue
var/mob/living/carbon/human/body = b
var/list/L = list()
// HTML colors need a # prefix
L["htmlcolor"] = "#[body.dna.features["mcolor"]]"
var/area/A = get_area(body)
L["area"] = A.name
var/stat = "error"
switch(body.stat)
if(CONSCIOUS)
stat = "Conscious"
if(UNCONSCIOUS)
stat = "Unconscious"
if(DEAD)
stat = "Dead"
var/current = body.mind
var/is_conscious = (body.stat == CONSCIOUS)
L["status"] = stat
L["exoticblood"] = body.blood_volume
L["name"] = body.name
L["ref"] = "\ref[body]"
L["is_current"] = current
var/button
if(current)
button = "selected"
else if(is_conscious)
button = null
else
button = "disabled"
L["swap_button_state"] = button
L["swappable"] = !current && is_conscious
data["bodies"] += list(L)
return data
/datum/action/innate/swap_body/ui_act(action, params)
if(..())
return
var/mob/living/carbon/human/H = owner
if(!isslimeperson(owner))
return
var/datum/species/jelly/slime/SS = H.dna.species
var/datum/mind/M
for(var/mob/living/L in SS.bodies)
if(L.mind && L.mind.active)
M = L.mind
if(!M)
return
if(!isslimeperson(M.current))
return
switch(action)
if("swap")
var/mob/living/carbon/human/selected = locate(params["ref"])
if(!(selected in SS.bodies))
return
if(!selected || qdeleted(selected) || !isslimeperson(selected))
SS.bodies -= selected
return
if(M.current == selected)
return
if(selected.stat != CONSCIOUS)
return
swap_to_dupe(M, selected)
/datum/action/innate/swap_body/proc/swap_to_dupe(datum/mind/M, mob/living/carbon/human/dupe)
M.current.visible_message("<span class='notice'>[M.current] \
stops moving and starts staring vacantly into space.</span>",
"<span class='notice'>You stop moving this body...</span>")
M.transfer_to(dupe)
dupe.visible_message("<span class='notice'>[dupe] blinks and looks \
around.</span>",
"<span class='notice'>...and move this one instead.</span>")
@@ -0,0 +1,41 @@
/datum/species/lizard
// Reptilian humanoids with scaled skin and tails.
name = "Lizardperson"
id = "lizard"
say_mod = "hisses"
default_color = "00FF00"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR,FACEHAIR)
mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings", "legs")
mutant_organs = list(/obj/item/organ/tongue/lizard)
default_features = list("mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0", "tail" = "Smooth", "snout" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None", "legs" = "Normal Legs")
attack_verb = "slash"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/lizard
skinned_type = /obj/item/stack/sheet/animalhide/lizard
exotic_bloodtype = "L"
/datum/species/lizard/random_name(gender,unique,lastname)
if(unique)
return random_unique_lizard_name(gender)
var/randname = lizard_name(gender)
if(lastname)
randname += " [lastname]"
return randname
//I wag in death
/datum/species/lizard/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
H.endTailWag()
/*
Lizard subspecies: ASHWALKERS
*/
/datum/species/lizard/ashwalker
name = "Ash Walker"
id = "ashlizard"
limbs_id = "lizard"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,NOBREATH,NOGUNS,DIGITIGRADE)
@@ -0,0 +1,70 @@
var/global/image/plasmaman_on_fire = image("icon"='icons/mob/OnFire.dmi', "icon_state"="plasmaman")
/datum/species/plasmaman
name = "Plasmaman"
id = "plasmaman"
say_mod = "rattles"
sexes = 0
meat = /obj/item/stack/sheet/mineral/plasma
species_traits = list(NOBLOOD,RESISTCOLD,RADIMMUNE,NOTRANSSTING,VIRUSIMMUNE,NOHUNGER)
mutantlungs = /obj/item/organ/lungs/plasmaman
dangerous_existence = 1 //So so much
blacklisted = 1 //See above
burnmod = 2
heatmod = 2
breathid = "tox"
speedmod = 1
damage_overlay_type = ""//let's not show bloody wounds or burns over bones.
var/internal_fire = FALSE //If the bones themselves are burning clothes won't help you much
/datum/species/plasmaman/spec_life(mob/living/carbon/human/H)
var/datum/gas_mixture/environment = H.loc.return_air()
var/atmos_sealed = (H.wear_suit && (H.wear_suit.flags & STOPSPRESSUREDMAGE)) && (H.head && (H.head.flags & STOPSPRESSUREDMAGE))
if((!istype(H.w_uniform, /obj/item/clothing/under/plasmaman) || !istype(H.head, /obj/item/clothing/head/helmet/space/plasmaman)) && !atmos_sealed)
if(environment)
if(environment.total_moles())
if(environment.gases["o2"] && (environment.gases["o2"][MOLES]) >= 1) //Same threshhold that extinguishes fire
H.adjust_fire_stacks(0.5)
if(!H.on_fire && H.fire_stacks > 0)
H.visible_message("<span class='danger'>[H]'s body reacts with the atmosphere and bursts into flames!</span>","<span class='userdanger'>Your body reacts with the atmosphere and bursts into flame!</span>")
H.IgniteMob()
internal_fire = TRUE
else
if(H.fire_stacks)
var/obj/item/clothing/under/plasmaman/P = H.w_uniform
if(istype(P))
P.Extinguish(H)
internal_fire = FALSE
else
internal_fire = FALSE
H.update_fire()
/datum/species/plasmaman/handle_fire(mob/living/carbon/human/H, no_protection)
if(internal_fire)
no_protection = TRUE
..()
/datum/species/plasmaman/before_equip_job(datum/job/J, mob/living/carbon/human/H, visualsOnly = FALSE)
var/datum/outfit/plasmaman/O = new /datum/outfit/plasmaman
H.equipOutfit(O, visualsOnly)
H.internal = H.get_item_for_held_index(2)
H.update_internals_hud_icon(1)
return 0
/datum/species/plasmaman/qualifies_for_rank(rank, list/features)
if(rank in security_positions)
return 0
if(rank == "Clown" || rank == "Mime")//No funny bussiness
return 0
return ..()
/datum/species/plasmaman/random_name(gender,unique,lastname)
if(unique)
return random_unique_plasmaman_name()
var/randname = plasmaman_name()
if(lastname)
randname += " [lastname]"
return randname
@@ -0,0 +1,64 @@
/datum/species/pod
// A mutation caused by a human being ressurected in a revival pod. These regain health in light, and begin to wither in darkness.
name = "Podperson"
id = "pod"
default_color = "59CE00"
species_traits = list(MUTCOLORS,EYECOLOR)
attack_verb = "slash"
attack_sound = 'sound/weapons/slice.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
burnmod = 1.25
heatmod = 1.5
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/plant
/datum/species/pod/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
C.faction |= "plants"
C.faction |= "vines"
/datum/species/pod/on_species_loss(mob/living/carbon/C)
. = ..()
C.faction -= "plants"
C.faction -= "vines"
/datum/species/pod/spec_life(mob/living/carbon/human/H)
if(H.stat == DEAD)
return
var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing
if(isturf(H.loc)) //else, there's considered to be no light
var/turf/T = H.loc
light_amount = min(10,T.get_lumcount()) - 5
H.nutrition += light_amount
if(H.nutrition > NUTRITION_LEVEL_FULL)
H.nutrition = NUTRITION_LEVEL_FULL
if(light_amount > 2) //if there's enough light, heal
H.heal_overall_damage(1,1)
H.adjustToxLoss(-1)
H.adjustOxyLoss(-1)
if(H.nutrition < NUTRITION_LEVEL_STARVING + 50)
H.take_overall_damage(2,0)
/datum/species/pod/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(chem.id == "plantbgone")
H.adjustToxLoss(3)
H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM)
return 1
/datum/species/pod/on_hit(obj/item/projectile/P, mob/living/carbon/human/H)
switch(P.type)
if(/obj/item/projectile/energy/floramut)
if(prob(15))
H.rad_act(rand(30,80))
H.Weaken(5)
H.visible_message("<span class='warning'>[H] writhes in pain as [H.p_their()] vacuoles boil.</span>", "<span class='userdanger'>You writhe in pain as your vacuoles boil!</span>", "<span class='italics'>You hear the crunching of leaves.</span>")
if(prob(80))
H.randmutb()
else
H.randmutg()
H.domutcheck()
else
H.adjustFireLoss(rand(5,15))
H.show_message("<span class='userdanger'>The radiation beam singes you!</span>")
if(/obj/item/projectile/energy/florayield)
H.nutrition = min(H.nutrition+30, NUTRITION_LEVEL_FULL)
@@ -0,0 +1,51 @@
/datum/species/shadow
// Humans cursed to stay in the darkness, lest their life forces drain. They regain health in shadow and die in light.
name = "???"
id = "shadow"
darksight = 8
invis_sight = SEE_INVISIBLE_MINIMUM
sexes = 0
blacklisted = 1
ignored_by = list(/mob/living/simple_animal/hostile/faithless)
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/shadow
species_traits = list(NOBREATH,NOBLOOD,RADIMMUNE,VIRUSIMMUNE)
dangerous_existence = 1
var/datum/action/innate/shadow/darkvision/vision_toggle
/datum/action/innate/shadow/darkvision //Darkvision toggle so shadowpeople can actually see where darkness is
name = "Toggle Darkvision"
check_flags = AB_CHECK_CONSCIOUS
background_icon_state = "bg_default"
button_icon_state = "blind"
/datum/action/innate/shadow/darkvision/Activate()
var/mob/living/carbon/human/H = owner
if(H.see_in_dark < 8)
H.see_in_dark = 8
H.see_invisible = SEE_INVISIBLE_MINIMUM
H << "<span class='notice'>You adjust your vision to pierce the darkness.</span>"
else
H.see_in_dark = 2
H.see_invisible = SEE_INVISIBLE_LIVING
H << "<span class='notice'>You adjust your vision to recognize the shadows.</span>"
/datum/species/shadow/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
vision_toggle = new
vision_toggle.Grant(C)
/datum/species/shadow/on_species_loss(mob/living/carbon/C)
. = ..()
if(vision_toggle)
vision_toggle.Remove(C)
/datum/species/shadow/spec_life(mob/living/carbon/human/H)
var/light_amount = 0
if(isturf(H.loc))
var/turf/T = H.loc
light_amount = T.get_lumcount()
if(light_amount > 2) //if there's enough light, start dying
H.take_overall_damage(1,1)
else if (light_amount < 2) //heal in the dark
H.heal_overall_damage(1,1)
@@ -0,0 +1,11 @@
/datum/species/skeleton
// 2spooky
name = "Spooky Scary Skeleton"
id = "skeleton"
say_mod = "rattles"
blacklisted = 1
sexes = 0
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton
species_traits = list(NOBREATH,RESISTHOT,RESISTCOLD,RESISTPRESSURE,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NOHUNGER,EASYDISMEMBER,EASYLIMBATTACHMENT)
mutant_organs = list(/obj/item/organ/tongue/bone)
damage_overlay_type = ""//let's not show bloody wounds or burns over bones.
@@ -0,0 +1,121 @@
/datum/species/synth
name = "Synth" //inherited from the real species, for health scanners and things
id = "synth"
say_mod = "beep boops" //inherited from a user's real species
sexes = 0
species_traits = list(NOTRANSSTING,NOBREATH,VIRUSIMMUNE,NODISMEMBER,NOHUNGER) //all of these + whatever we inherit from the real species
dangerous_existence = 1
blacklisted = 1
meat = null
damage_overlay_type = "synth"
limbs_id = "synth"
var/list/initial_species_traits = list(NOTRANSSTING,NOBREATH,VIRUSIMMUNE,NODISMEMBER,NOHUNGER) //for getting these values back for assume_disguise()
var/disguise_fail_health = 75 //When their health gets to this level their synthflesh partially falls off
var/datum/species/fake_species = null //a species to do most of our work for us, unless we're damaged
/datum/species/synth/military
name = "Military Synth"
id = "military_synth"
armor = 25
punchdamagelow = 10
punchdamagehigh = 19
punchstunthreshold = 14 //about 50% chance to stun
disguise_fail_health = 50
/datum/species/synth/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
..()
assume_disguise(old_species, H)
/datum/species/synth/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(chem.id == "synthflesh")
chem.reaction_mob(H, TOUCH, 2 ,0) //heal a little
H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM)
return 1
else
return ..()
/datum/species/synth/proc/assume_disguise(datum/species/S, mob/living/carbon/human/H)
if(S && !istype(S, type))
name = S.name
say_mod = S.say_mod
sexes = S.sexes
species_traits = initial_species_traits.Copy()
species_traits.Add(S.species_traits)
attack_verb = S.attack_verb
attack_sound = S.attack_sound
miss_sound = S.miss_sound
meat = S.meat
mutant_bodyparts = S.mutant_bodyparts.Copy()
mutant_organs = S.mutant_organs.Copy()
default_features = S.default_features.Copy()
nojumpsuit = S.nojumpsuit
no_equip = S.no_equip.Copy()
limbs_id = S.limbs_id
use_skintones = S.use_skintones
fixed_mut_color = S.fixed_mut_color
hair_color = S.hair_color
fake_species = new S.type
else
name = initial(name)
say_mod = initial(say_mod)
species_traits = initial_species_traits.Copy()
attack_verb = initial(attack_verb)
attack_sound = initial(attack_sound)
miss_sound = initial(miss_sound)
mutant_bodyparts = list()
default_features = list()
nojumpsuit = initial(nojumpsuit)
no_equip = list()
qdel(fake_species)
fake_species = null
meat = initial(meat)
limbs_id = "synth"
use_skintones = 0
sexes = 0
fixed_mut_color = ""
hair_color = ""
for(var/X in H.bodyparts) //propagates the damage_overlay changes
var/obj/item/bodypart/BP = X
BP.update_limb()
H.update_body_parts() //to update limb icon cache with the new damage overlays
//Proc redirects:
//Passing procs onto the fake_species, to ensure we look as much like them as possible
/datum/species/synth/handle_hair(mob/living/carbon/human/H, forced_colour)
if(fake_species)
fake_species.handle_hair(H, forced_colour)
else
return ..()
/datum/species/synth/handle_body(mob/living/carbon/human/H)
if(fake_species)
fake_species.handle_body(H)
else
return ..()
/datum/species/synth/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour)
if(fake_species)
fake_species.handle_body(H,forced_colour)
else
return ..()
/datum/species/synth/get_spans()
if(fake_species)
return fake_species.get_spans()
return list()
/datum/species/synth/handle_speech(message, mob/living/carbon/human/H)
if(H.health > disguise_fail_health)
if(fake_species)
return fake_species.handle_speech(message,H)
else
return ..()
else
return ..()
@@ -0,0 +1,62 @@
/datum/species/zombie
// 1spooky
name = "High Functioning Zombie"
id = "zombie"
say_mod = "moans"
sexes = 0
blacklisted = 1
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOBLOOD,RADIMMUNE,NOZOMBIE,EASYDISMEMBER,EASYLIMBATTACHMENT)
mutant_organs = list(/obj/item/organ/tongue/zombie)
/datum/species/zombie/infectious
name = "Infectious Zombie"
id = "memezombies"
limbs_id = "zombie"
no_equip = list(slot_wear_mask, slot_head)
armor = 20 // 120 damage to KO a zombie, which kills it
speedmod = 2
/datum/species/zombie/infectious/spec_life(mob/living/carbon/C)
. = ..()
C.a_intent = INTENT_HARM // THE SUFFERING MUST FLOW
if(C.InCritical())
C.death()
// Zombies only move around when not in crit, they instantly
// succumb otherwise, and will standup again soon
/datum/species/zombie/infectious/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
// Drop items in hands
// If you're a zombie lucky enough to have a NODROP item, then it stays.
for(var/V in C.held_items)
var/obj/item/I = V
if(istype(I))
if(C.dropItemToGround(I))
var/obj/item/zombie_hand/zh = new /obj/item/zombie_hand()
C.put_in_hands(zh)
else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand
var/obj/item/zombie_hand/zh = new /obj/item/zombie_hand()
C.put_in_hands(zh)
// Next, deal with the source of this zombie corruption
var/obj/item/organ/zombie_infection/infection
infection = C.getorganslot("zombie_infection")
if(!infection)
infection = new(C)
/datum/species/zombie/infectious/on_species_loss(mob/living/carbon/C)
. = ..()
for(var/obj/item/I in C.held_items)
if(istype(I, /obj/item/zombie_hand))
qdel(I)
// Your skin falls off
/datum/species/krokodil_addict
name = "Human"
id = "goofzombies"
limbs_id = "zombie" //They look like zombies
sexes = 0
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
mutant_organs = list(/obj/item/organ/tongue/zombie)
@@ -0,0 +1,18 @@
/mob/living/carbon/human/Stun(amount, updating = 1, ignore_canstun = 0)
amount = dna.species.spec_stun(src,amount)
..()
/mob/living/carbon/human/Weaken(amount, updating = 1, ignore_canstun = 0)
amount = dna.species.spec_stun(src,amount)
..()
/mob/living/carbon/human/cure_husk()
. = ..()
if(.)
update_hair()
/mob/living/carbon/human/become_husk()
. = ..()
if(.)
update_hair()
@@ -4,8 +4,10 @@
/* Keep these comments up-to-date if you -insist- on hurting my code-baby ;_;
This system allows you to update individual mob-overlays, without regenerating them all each time.
When we generate overlays we generate the standing version and then rotate the mob as necessary..
As of the time of writing there are 20 layers within this list. Please try to keep this from increasing. //22 and counting, good job guys
var/overlays_standing[20] //For the standing stance
Most of the time we only wish to update one overlay:
e.g. - we dropped the fireaxe out of our left hand and need to remove its icon from our mob
e.g.2 - our hair colour has changed, so we need to update our hair icons on our mob
@@ -13,21 +15,28 @@ In these cases, instead of updating every overlay using the old behaviour (regen
the appropriate update_X proc.
e.g. - update_l_hand()
e.g.2 - update_hair()
Note: Recent changes by aranclanos+carn:
update_icons() no longer needs to be called.
the system is easier to use. update_icons() should not be called unless you absolutely -know- you need it.
IN ALL OTHER CASES it's better to just call the specific update_X procs.
Note: The defines for layer numbers is now kept exclusvely in __DEFINES/misc.dm instead of being defined there,
then redefined and undefiend everywhere else. If you need to change the layering of sprites (or add a new layer)
that's where you should start.
All of this means that this code is more maintainable, faster and still fairly easy to use.
There are several things that need to be remembered:
> Whenever we do something that should cause an overlay to update (which doesn't use standard procs
( i.e. you do something like l_hand = /obj/item/something new(src), rather than using the helper procs)
You will need to call the relevant update_inv_* proc
All of these are named after the variable they update from. They are defined at the mob/ level like
update_clothing was, so you won't cause undefined proc runtimes with usr.update_inv_wear_id() if the usr is a
slime etc. Instead, it'll just return without doing any work. So no harm in calling it for slimes and such.
> There are also these special cases:
update_damage_overlays() //handles damage overlays for brute/burn damage
update_body() //Handles updating your mob's body layer and mutant bodyparts
@@ -35,30 +44,10 @@ There are several things that need to be remembered:
//NOTE: update_mutantrace() is now merged into this!
update_hair() //Handles updating your hair overlay (used to be update_face, but mouth and
eyes were merged into update_body())
*/
//DAMAGE OVERLAYS
//constructs damage icon for each organ from mask * damage field and saves it in our overlays_ lists
/mob/living/carbon/human/update_damage_overlays()
remove_overlay(DAMAGE_LAYER)
var/image/standing = image("icon"='icons/mob/dam_human.dmi', "icon_state"="blank", "layer"=-DAMAGE_LAYER)
overlays_standing[DAMAGE_LAYER] = standing
var/dmgoverlaytype = ""
if(dna.species.exotic_damage_overlay)
dmgoverlaytype = dna.species.exotic_damage_overlay + "_"
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(BP.brutestate)
standing.overlays += "[dmgoverlaytype][BP.body_zone]_[BP.brutestate]0" //we're adding icon_states of the base image as overlays
if(BP.burnstate)
standing.overlays += "[dmgoverlaytype][BP.body_zone]_0[BP.burnstate]"
apply_overlay(DAMAGE_LAYER)
//HAIR OVERLAY
/mob/living/carbon/human/update_hair()
dna.species.handle_hair(src)
@@ -68,47 +57,14 @@ There are several things that need to be remembered:
dna.species.handle_mutant_bodyparts(src)
/mob/living/carbon/human/proc/update_body()
/mob/living/carbon/human/update_body()
remove_overlay(BODY_LAYER)
dna.species.handle_body(src)
update_body_parts()
..()
/mob/living/carbon/human/update_fire()
..("Standing")
/mob/living/carbon/human/proc/update_body_parts()
//CHECK FOR UPDATE
var/oldkey = icon_render_key
icon_render_key = generate_icon_render_key()
if(oldkey == icon_render_key)
return
remove_overlay(BODYPARTS_LAYER)
//LOAD ICONS
if(limb_icon_cache[icon_render_key])
load_limb_from_cache()
update_damage_overlays()
update_mutant_bodyparts()
update_hair()
return
//GENERATE NEW LIMBS
var/list/new_limbs = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(!BP.no_update)
BP.update_limb()
var/image/temp = BP.get_limb_icon()
if(temp)
new_limbs += temp
if(new_limbs.len)
overlays_standing[BODYPARTS_LAYER] = new_limbs
limb_icon_cache[icon_render_key] = new_limbs
apply_overlay(BODYPARTS_LAYER)
update_damage_overlays()
/* --------------------------------------- */
//For legacy support.
@@ -130,6 +86,7 @@ There are several things that need to be remembered:
update_inv_back()
update_inv_wear_suit()
update_inv_pockets()
update_inv_neck()
update_transform()
//mutations
update_mutations_overlay()
@@ -148,10 +105,11 @@ There are several things that need to be remembered:
if(istype(w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/U = w_uniform
U.screen_loc = ui_iclothing
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open ...
U.screen_loc = ui_iclothing //...draw the item in the inventory screen
client.screen += w_uniform //Either way, add the item to the HUD
if(hud_used.inventory_shown)
client.screen += w_uniform
update_observer_view(w_uniform,1)
if(wear_suit && (wear_suit.flags_inv & HIDEJUMPSUIT))
return
@@ -160,27 +118,30 @@ There are several things that need to be remembered:
var/t_color = U.item_color
if(!t_color)
t_color = U.icon_state
if(U.adjusted)
if(U.adjusted == ALT_STYLE)
t_color = "[t_color]_d"
else if(U.adjusted == DIGITIGRADE_STYLE)
t_color = "[t_color]_l"
var/image/standing
if(dna && dna.species.sexes)
var/G = (gender == FEMALE) ? "f" : "m"
if(G == "f" && U.fitted != NO_FEMALE_UNIFORM)
standing = U.build_worn_icon(state = "[t_color]_s", default_layer = UNIFORM_LAYER, default_icon_file = 'icons/mob/uniform.dmi', isinhands = FALSE, femaleuniform = U.fitted)
standing = U.build_worn_icon(state = "[t_color]", default_layer = UNIFORM_LAYER, default_icon_file = 'icons/mob/uniform.dmi', isinhands = FALSE, femaleuniform = U.fitted)
if(!standing)
standing = U.build_worn_icon(state = "[t_color]_s", default_layer = UNIFORM_LAYER, default_icon_file = 'icons/mob/uniform.dmi', isinhands = FALSE)
standing = U.build_worn_icon(state = "[t_color]", default_layer = UNIFORM_LAYER, default_icon_file = 'icons/mob/uniform.dmi', isinhands = FALSE)
overlays_standing[UNIFORM_LAYER] = standing
else
else if(!(dna && dna.species.nojumpsuit))
// Automatically drop anything in store / id / belt if you're not wearing a uniform. //CHECK IF NECESARRY
for(var/obj/item/thing in list(r_store, l_store, wear_id, belt)) //
unEquip(thing)
for(var/obj/item/thing in list(r_store, l_store, wear_id, belt))
dropItemToGround(thing)
apply_overlay(UNIFORM_LAYER)
update_mutant_bodyparts()
/mob/living/carbon/human/update_inv_wear_id()
@@ -191,9 +152,10 @@ There are several things that need to be remembered:
inv.update_icon()
if(wear_id)
wear_id.screen_loc = ui_id
if(client && hud_used && hud_used.hud_shown)
wear_id.screen_loc = ui_id
client.screen += wear_id
update_observer_view(wear_id)
//TODO: add an icon file for ID slot stuff, so it's less snowflakey
var/image/standing = wear_id.build_worn_icon(state = wear_id.item_state, default_layer = ID_LAYER, default_icon_file = 'icons/mob/mob.dmi')
@@ -206,18 +168,25 @@ There are several things that need to be remembered:
remove_overlay(GLOVES_LAYER)
if(get_num_arms() <2)
if(!gloves && blood_DNA)
if(has_left_hand())
overlays_standing[GLOVES_LAYER] = image("icon"='icons/effects/blood.dmi', "icon_state"="bloodyhands_left", "layer"=-GLOVES_LAYER)
apply_overlay(GLOVES_LAYER)
else if(has_right_hand())
overlays_standing[GLOVES_LAYER] = image("icon"='icons/effects/blood.dmi', "icon_state"="bloodyhands_right", "layer"=-GLOVES_LAYER)
apply_overlay(GLOVES_LAYER)
return
if(client && hud_used)
if(client && hud_used && hud_used.inv_slots[slot_gloves])
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_gloves]
inv.update_icon()
if(gloves)
gloves.screen_loc = ui_gloves
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open ...
gloves.screen_loc = ui_gloves //...draw the item in the inventory screen
client.screen += gloves //Either way, add the item to the HUD
if(hud_used.inventory_shown)
client.screen += gloves
update_observer_view(gloves,1)
var/t_state = gloves.item_state
if(!t_state)
t_state = gloves.icon_state
@@ -233,7 +202,6 @@ There are several things that need to be remembered:
apply_overlay(GLOVES_LAYER)
/mob/living/carbon/human/update_inv_glasses()
remove_overlay(GLASSES_LAYER)
@@ -245,11 +213,11 @@ There are several things that need to be remembered:
inv.update_icon()
if(glasses)
glasses.screen_loc = ui_glasses //...draw the item in the inventory screen
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open ...
glasses.screen_loc = ui_glasses //...draw the item in the inventory screen
client.screen += glasses //Either way, add the item to the HUD
client.screen += glasses //Either way, add the item to the HUD
update_observer_view(glasses,1)
if(!(head && (head.flags_inv & HIDEEYES)) && !(wear_mask && (wear_mask.flags_inv & HIDEEYES)))
var/image/standing = glasses.build_worn_icon(state = glasses.icon_state, default_layer = GLASSES_LAYER, default_icon_file = 'icons/mob/eyes.dmi')
@@ -269,10 +237,11 @@ There are several things that need to be remembered:
inv.update_icon()
if(ears)
ears.screen_loc = ui_ears //move the item to the appropriate screen loc
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open ...
ears.screen_loc = ui_ears //...draw the item in the inventory screen
client.screen += ears //Either way, add the item to the HUD
if(hud_used.inventory_shown) //if the inventory is open
client.screen += ears //add it to the client's screen
update_observer_view(ears,1)
var/image/standing = ears.build_worn_icon(state = ears.icon_state, default_layer = EARS_LAYER, default_icon_file = 'icons/mob/ears.dmi')
overlays_standing[EARS_LAYER] = standing
@@ -291,11 +260,11 @@ There are several things that need to be remembered:
inv.update_icon()
if(shoes)
shoes.screen_loc = ui_shoes //move the item to the appropriate screen loc
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open ...
shoes.screen_loc = ui_shoes //...draw the item in the inventory screen
client.screen += shoes //Either way, add the item to the HUD
if(hud_used.inventory_shown) //if the inventory is open
client.screen += shoes //add it to client's screen
update_observer_view(shoes,1)
var/image/standing = shoes.build_worn_icon(state = shoes.icon_state, default_layer = SHOES_LAYER, default_icon_file = 'icons/mob/feet.dmi')
overlays_standing[SHOES_LAYER] = standing
@@ -310,10 +279,10 @@ There are several things that need to be remembered:
inv.update_icon()
if(s_store)
s_store.screen_loc = ui_sstore1
if(client && hud_used && hud_used.hud_shown)
s_store.screen_loc = ui_sstore1
client.screen += s_store
update_observer_view(s_store)
var/t_state = s_store.item_state
if(!t_state)
t_state = s_store.icon_state
@@ -322,19 +291,10 @@ There are several things that need to be remembered:
apply_overlay(SUIT_STORE_LAYER)
/mob/living/carbon/human/update_inv_head()
remove_overlay(HEAD_LAYER)
if(!get_bodypart("head")) //Decapitated
return
..()
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_head]
inv.update_icon()
update_mutant_bodyparts()
/mob/living/carbon/human/update_inv_belt()
remove_overlay(BELT_LAYER)
@@ -342,11 +302,12 @@ There are several things that need to be remembered:
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_belt]
inv.update_icon()
if(hud_used.hud_shown && belt)
client.screen += belt
belt.screen_loc = ui_belt
if(belt)
belt.screen_loc = ui_belt
if(client && hud_used && hud_used.hud_shown)
client.screen += belt
update_observer_view(belt)
var/t_state = belt.item_state
if(!t_state)
t_state = belt.icon_state
@@ -367,17 +328,17 @@ There are several things that need to be remembered:
inv.update_icon()
if(istype(wear_suit, /obj/item/clothing/suit))
wear_suit.screen_loc = ui_oclothing
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown) //if the inventory is open ...
wear_suit.screen_loc = ui_oclothing //TODO //...draw the item in the inventory screen
client.screen += wear_suit //Either way, add the item to the HUD
if(hud_used.inventory_shown)
client.screen += wear_suit
update_observer_view(wear_suit,1)
var/image/standing = wear_suit.build_worn_icon(state = wear_suit.icon_state, default_layer = SUIT_LAYER, default_icon_file = 'icons/mob/suit.dmi')
overlays_standing[SUIT_LAYER] = standing
if(istype(wear_suit, /obj/item/clothing/suit/straight_jacket))
drop_l_hand()
drop_r_hand()
if(wear_suit.breakouttime) //suit is restraining
drop_all_held_items()
update_hair()
update_mutant_bodyparts()
@@ -395,31 +356,23 @@ There are several things that need to be remembered:
inv = hud_used.inv_slots[slot_r_store]
inv.update_icon()
if(hud_used.hud_shown)
if(l_store)
if(l_store)
l_store.screen_loc = ui_storage1
if(hud_used.hud_shown)
client.screen += l_store
l_store.screen_loc = ui_storage1
update_observer_view(l_store)
if(r_store)
if(r_store)
r_store.screen_loc = ui_storage2
if(hud_used.hud_shown)
client.screen += r_store
r_store.screen_loc = ui_storage2
update_observer_view(r_store)
/mob/living/carbon/human/update_inv_wear_mask()
remove_overlay(FACEMASK_LAYER)
if(!get_bodypart("head")) //Decapitated
return
..()
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_mask]
inv.update_icon()
update_mutant_bodyparts()
update_mutant_bodyparts() //e.g. upgate needed because mask now hides lizard snout
/mob/living/carbon/human/update_inv_handcuffed()
remove_overlay(HANDCUFF_LAYER)
if(handcuffed)
overlays_standing[HANDCUFF_LAYER] = image("icon"='icons/mob/mob.dmi', "icon_state"="handcuff1", "layer"=-HANDCUFF_LAYER)
apply_overlay(HANDCUFF_LAYER)
/mob/living/carbon/human/update_inv_legcuffed()
remove_overlay(LEGCUFF_LAYER)
@@ -439,7 +392,7 @@ There are several things that need to be remembered:
/mob/living/carbon/human/proc/get_overlays_copy(list/unwantedLayers)
var/list/out = new
for(var/i=1;i<=TOTAL_LAYERS;i++)
for(var/i in 1 to TOTAL_LAYERS)
if(overlays_standing[i])
if(i in unwantedLayers)
continue
@@ -451,23 +404,36 @@ There are several things that need to be remembered:
//update whether our head item appears on our hud.
/mob/living/carbon/human/update_hud_head(obj/item/I)
I.screen_loc = ui_head
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
I.screen_loc = ui_head
client.screen += I
client.screen += I
update_observer_view(I,1)
//update whether our mask item appears on our hud.
/mob/living/carbon/human/update_hud_wear_mask(obj/item/I)
I.screen_loc = ui_mask
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
I.screen_loc = ui_mask
client.screen += I
client.screen += I
update_observer_view(I,1)
//update whether our neck item appears on our hud.
/mob/living/carbon/human/update_hud_neck(obj/item/I)
I.screen_loc = ui_neck
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
client.screen += I
update_observer_view(I,1)
//update whether our back item appears on our hud.
/mob/living/carbon/human/update_hud_back(obj/item/I)
I.screen_loc = ui_back
if(client && hud_used && hud_used.hud_shown)
I.screen_loc = ui_back
client.screen += I
update_observer_view(I)
/*
@@ -477,15 +443,23 @@ covers:
centering large images
layering images on custom layers
building images from custom icon files
By Remie Richards (yes I'm taking credit because this just removed 90% of the copypaste in update_icons())
state: A string to use as the state, this is FAR too complex to solve in this proc thanks to shitty old code
so it's specified as an argument instead.
default_layer: The layer to draw this on if no other layer is specified
default_icon_file: The icon file to draw states from if no other icon file is specified
isinhands: If true then alternate_worn_icon is skipped so that default_icon_file is used,
in this situation default_icon_file is expected to match either the lefthand_ or righthand_ file var
femalueuniform: A value matching a uniform item's fitted var, if this is anything but NO_FEMALE_UNIFORM, we
generate/load female uniform sprites matching all previously decided variables
*/
/obj/item/proc/build_worn_icon(var/state = "", var/default_layer = 0, var/default_icon_file = null, var/isinhands = FALSE, var/femaleuniform = NO_FEMALE_UNIFORM)
@@ -517,41 +491,42 @@ generate/load female uniform sprites matching all previously decided variables
standing = center_image(standing, isinhands ? inhand_x_dimension : worn_x_dimension, isinhands ? inhand_y_dimension : worn_y_dimension)
//Handle held offsets
var/mob/M = loc
if(istype(M))
var/list/L = get_held_offsets()
if(L)
standing.pixel_x += L["x"] //+= because of center()ing
standing.pixel_y += L["y"]
standing.alpha = alpha
standing.color = color
return standing
/obj/item/proc/get_held_offsets()
var/list/L
if(ismob(loc))
var/mob/M = loc
L = M.get_item_offsets_for_index(M.get_held_index_of_item(src))
return L
//Can't think of a better way to do this, sadly
/mob/proc/get_item_offsets_for_index(i)
switch(i)
if(3) //odd = left hands
return list("x" = 0, "y" = 16)
if(4) //even = right hands
return list("x" = 0, "y" = 16)
else //No offsets or Unwritten number of hands
return list("x" = 0, "y" = 0)
/////////////////////
// Limb Icon Cache //
/////////////////////
/*
Called from update_body_parts() these procs handle the limb icon cache.
the limb icon cache adds an icon_render_key to a human mob, it represents:
- skin_tone (if applicable)
- gender
- limbs (stores as the limb name and whether it is removed/fine, organic/robotic)
These procs only store limbs as to increase the number of matching icon_render_keys
This cache exists because drawing 6/7 icons for humans constantly is quite a waste
See RemieRichards on irc.rizon.net #coderbus
*/
var/global/list/limb_icon_cache = list()
/mob/living/carbon/human
var/icon_render_key = ""
//produces a key based on the human's limbs
/mob/living/carbon/human/proc/generate_icon_render_key()
/mob/living/carbon/human/generate_icon_render_key()
. = "[dna.species.limbs_id]"
if(dna.check_mutation(HULK))
@@ -562,8 +537,6 @@ var/global/list/limb_icon_cache = list()
. += "-coloured-[dna.species.fixed_mut_color]"
else if(dna.features["mcolor"])
. += "-coloured-[dna.features["mcolor"]]"
else if(dna.features["mcolor"] && dna.species.use_skintones)
. += "-coloured-[skin_tone]"
else
. += "-not_coloured"
@@ -572,18 +545,35 @@ var/global/list/limb_icon_cache = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
. += "-[BP.body_zone]"
if(BP.status == ORGAN_ORGANIC)
if(BP.status == BODYPART_ORGANIC)
. += "-organic"
else
. += "-robotic"
if(BP.use_digitigrade)
. += "-digitigrade[BP.use_digitigrade]"
if(BP.dmg_overlay_type)
. += "-[BP.dmg_overlay_type]"
if(disabilities & HUSK)
. += "-husk"
/mob/living/carbon/human/load_limb_from_cache()
..()
update_hair()
//change the human's icon to the one matching it's key
/mob/living/carbon/human/proc/load_limb_from_cache()
if(limb_icon_cache[icon_render_key])
remove_overlay(BODYPARTS_LAYER)
overlays_standing[BODYPARTS_LAYER] = limb_icon_cache[icon_render_key]
apply_overlay(BODYPARTS_LAYER)
/mob/living/carbon/human/proc/update_observer_view(obj/item/I, inventory)
if(observers && observers.len)
for(var/M in observers)
var/mob/dead/observe = M
if(observe.client && observe.client.eye == src)
if(observe.hud_used)
if(inventory && !observe.hud_used.inventory_shown)
continue
observe.client.screen += I
else
observers -= observe
if(!observers.len)
observers = null
break
@@ -37,12 +37,11 @@
// If whispering your last words, limit the whisper based on how close you are to death.
if(critical)
var/health_diff = round(-config.health_threshold_dead + health)
var/health_diff = round(-HEALTH_THRESHOLD_DEAD + health)
// If we cut our message short, abruptly end it with a-..
var/message_len = length(message)
message = copytext(message, 1, health_diff) + "[message_len > health_diff ? "-.." : "..."]"
message = Ellipsis(message, 10, 1)
whispers = "whispers in their final breath"
message = treat_message(message)
@@ -60,12 +59,13 @@
watching -= eavesdropping
var/rendered
rendered = "<span class='game say'><span class='name'>[src.name]</span> [whispers] something.</span>"
whispers = critical ? "whispers something in [p_their()] final breath." : "whispers something."
rendered = "<span class='game say'><span class='name'>[src.name]</span> [whispers]</span>"
for(var/mob/M in watching)
M.show_message(rendered, 2)
var/spans = list(SPAN_ITALICS)
whispers = critical ? "whispers in [p_their()] final breath" : "whispers"
rendered = "<span class='game say'><span class='name'>[GetVoice()]</span>[alt_name] [whispers], <span class='message'>\"[attach_spans(message, spans)]\"</span></span>"
for(var/atom/movable/AM in listening)
+48 -22
View File
@@ -4,18 +4,23 @@
return back
if(slot_wear_mask)
return wear_mask
if(slot_neck)
return wear_neck
if(slot_head)
return head
if(slot_handcuffed)
return handcuffed
if(slot_legcuffed)
return legcuffed
if(slot_l_hand)
return l_hand
if(slot_r_hand)
return r_hand
return null
/mob/living/carbon/proc/equip_in_one_of_slots(obj/item/I, list/slots, qdel_on_fail = 1)
for(var/slot in slots)
if(equip_to_slot_if_possible(I, slots[slot], qdel_on_fail = 0, disable_warning = TRUE))
return slot
if(qdel_on_fail)
qdel(I)
return null
//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible()
/mob/living/carbon/equip_to_slot(obj/item/I, slot)
@@ -24,19 +29,26 @@
if(!istype(I))
return
if(I == l_hand)
l_hand = null
else if(I == r_hand)
r_hand = null
var/index = get_held_index_of_item(I)
if(index)
held_items[index] = null
if(I.pulledby)
I.pulledby.stop_pulling()
I.screen_loc = null // will get moved if inventory is visible
I.screen_loc = null
if(client)
client.screen -= I
if(observers && observers.len)
for(var/M in observers)
var/mob/dead/observe = M
if(observe.client)
observe.client.screen -= I
I.loc = src
I.equipped(src, slot)
I.layer = ABOVE_HUD_LAYER
I.plane = ABOVE_HUD_PLANE
I.appearance_flags |= NO_CLIENT_COLOR
var/not_handled = FALSE
switch(slot)
if(slot_back)
back = I
@@ -47,27 +59,36 @@
if(slot_head)
head = I
head_update(I)
if(slot_neck)
wear_neck = I
update_inv_neck(I)
if(slot_handcuffed)
handcuffed = I
update_handcuffed()
if(slot_legcuffed)
legcuffed = I
update_inv_legcuffed()
if(slot_l_hand)
l_hand = I
update_inv_l_hand()
if(slot_r_hand)
r_hand = I
update_inv_r_hand()
if(slot_hands)
put_in_hands(I)
update_inv_hands()
if(slot_in_backpack)
if(I == get_active_hand())
unEquip(I)
I.loc = back
var/obj/item/weapon/storage/B = back
var/prev_jimmies = B.rustle_jimmies
B.rustle_jimmies = FALSE //don't conspicously rustle
B.handle_item_insertion(I, 1, src)
B.rustle_jimmies = prev_jimmies
else
return 1
not_handled = TRUE
//Item has been handled at this point and equipped callback can be safely called
//We cannot call it for items that have not been handled as they are not yet correctly
//in a slot (handled further down inheritance chain, probably living/carbon/human/equip_to_slot
if(!not_handled)
I.equipped(src, slot)
/mob/living/carbon/unEquip(obj/item/I)
return not_handled
/mob/living/carbon/doUnEquip(obj/item/I)
. = ..() //Sets the default return value to what the parent returns.
if(!. || !I) //We don't want to set anything to null if the parent returned 0.
return
@@ -81,6 +102,9 @@
else if(I == wear_mask)
wear_mask = null
wear_mask_update(I, toggle_off = 1)
if(I == wear_neck)
wear_neck = null
update_inv_neck(I)
else if(I == handcuffed)
handcuffed = null
if(buckled && buckled.buckle_requires_restraints)
@@ -105,6 +129,8 @@
var/obj/item/clothing/C = I
if(C.tint || initial(C.tint))
update_tint()
update_sight()
if(I.flags_inv & HIDEMASK || forced)
update_inv_wear_mask()
update_inv_head()
+11 -15
View File
@@ -4,24 +4,25 @@
if (notransform)
return
if(!loc)
return
if(damageoverlaytemp)
damageoverlaytemp = 0
update_damage_hud()
if(..())
. = 1
if(..()) //not dead
handle_blood()
for(var/obj/item/organ/O in internal_organs)
if(stat != DEAD)
for(var/V in internal_organs)
var/obj/item/organ/O = V
O.on_life()
//Updates the number of stored chemicals for powers
handle_changeling()
if(stat != DEAD)
return 1
///////////////
// BREATHING //
///////////////
@@ -50,7 +51,7 @@
var/datum/gas_mixture/breath
if(health <= config.health_threshold_crit || (pulledby && pulledby.grab_state >= GRAB_KILL && !getorganslot("breathing_tube")))
if(health <= HEALTH_THRESHOLD_CRIT || (pulledby && pulledby.grab_state >= GRAB_KILL && !getorganslot("breathing_tube")))
losebreath++
//Suffocate
@@ -259,7 +260,7 @@
dna.temporary_mutations.Remove(mut)
if(radiation)
radiation = Clamp(radiation, 0, 100)
switch(radiation)
if(0 to 50)
radiation = max(radiation-1,0)
@@ -275,8 +276,6 @@
if(75 to 100)
radiation = max(radiation-3,0)
adjustToxLoss(3)
else
radiation = Clamp(radiation, 0, 100)
/mob/living/carbon/handle_chemicals_in_body()
if(reagents)
@@ -284,7 +283,6 @@
/mob/living/carbon/handle_stomach()
/*
set waitfor = 0
for(var/mob/living/M in stomach_contents)
if(M.loc != src)
@@ -300,7 +298,7 @@
if(!(M.status_flags & GODMODE))
M.adjustBruteLoss(5)
nutrition += 10
*/
//this updates all special effects: stunned, sleeping, weakened, druggy, stuttering, etc..
/mob/living/carbon/handle_status_effects()
..()
@@ -314,7 +312,7 @@
if(sleeping)
handle_dreams()
AdjustSleeping(-1)
if(prob(10) && health>config.health_threshold_crit)
if(prob(10) && health>HEALTH_THRESHOLD_CRIT)
emote("snore")
var/restingpwr = 1 + 4 * resting
@@ -389,8 +387,6 @@
var/body_temperature_difference = 310.15 - bodytemperature
switch(bodytemperature)
if(-INFINITY to 260.15) //260.15 is 310.15 - 50, the temperature where you start to feel effects.
if(nutrition >= 2) //If we are very, very cold we'll use up quite a bit of nutriment to heat us up.
nutrition -= 2
bodytemperature += max((body_temperature_difference * metabolism_efficiency / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM)
if(260.15 to 310.15)
bodytemperature += max(body_temperature_difference * metabolism_efficiency / BODYTEMP_AUTORECOVERY_DIVISOR, min(body_temperature_difference, BODYTEMP_AUTORECOVERY_MINIMUM/4))
@@ -0,0 +1,458 @@
/mob/living/carbon/monkey
var/aggressive=0 // set to 1 using VV for an angry monkey
var/frustration=0
var/pickupTimer=0
var/list/enemies = list()
var/mob/living/target
var/obj/item/pickupTarget
var/mode = MONKEY_IDLE
var/list/myPath = list()
var/list/blacklistItems = list()
var/maxStepsTick = 6
var/best_force = 0
var/martial_art = new/datum/martial_art
var/resisting = FALSE
var/pickpocketing = FALSE
var/disposing_body = FALSE
var/obj/machinery/disposal/bodyDisposal = null
/mob/living/carbon/monkey/proc/IsStandingStill()
return resisting || pickpocketing || disposing_body
// blocks
// taken from /mob/living/carbon/human/interactive/
/mob/living/carbon/monkey/proc/walk2derpless(target)
if(!target || IsStandingStill())
return 0
if(myPath.len <= 0)
myPath = get_path_to(src, get_turf(target), /turf/proc/Distance, MAX_RANGE_FIND + 1, 250,1)
if(myPath)
if(myPath.len > 0)
for(var/i = 0; i < maxStepsTick; ++i)
if(!IsDeadOrIncap())
if(myPath.len >= 1)
walk_to(src,myPath[1],0,5)
myPath -= myPath[1]
return 1
// failed to path correctly so just try to head straight for a bit
walk_to(src,get_turf(target),0,5)
sleep(1)
walk_to(src,0)
return 0
// taken from /mob/living/carbon/human/interactive/
/mob/living/carbon/monkey/proc/IsDeadOrIncap(checkDead = TRUE)
if(!canmove)
return 1
if(health <= 0 && checkDead)
return 1
if(paralysis)
return 1
if(stunned)
return 1
if(stat)
return 1
return 0
/mob/living/carbon/monkey/proc/equip_item(var/obj/item/I)
if(I.loc == src)
return TRUE
if(I.anchored)
blacklistItems[I] ++
return FALSE
// WEAPONS
if(istype(I, /obj/item/weapon))
var/obj/item/weapon/W = I
if(W.force >= best_force)
put_in_hands(W)
best_force = W.force
return TRUE
// CLOTHING
else if(istype(I,/obj/item/clothing))
var/obj/item/clothing/C = I
monkeyDrop(C)
addtimer(CALLBACK(src, .proc/pickup_and_wear, C), 5)
return TRUE
// EVERYTHING ELSE
else
if(!get_item_for_held_index(1) || !get_item_for_held_index(2))
put_in_hands(I)
return TRUE
blacklistItems[I] ++
return FALSE
/mob/living/carbon/monkey/proc/pickup_and_wear(var/obj/item/clothing/C)
if(!equip_to_appropriate_slot(C))
monkeyDrop(get_item_by_slot(C)) // remove the existing item if worn
sleep(5)
equip_to_appropriate_slot(C)
/mob/living/carbon/monkey/resist_restraints()
var/obj/item/I = null
if(handcuffed)
I = handcuffed
else if(legcuffed)
I = legcuffed
if(I)
changeNext_move(CLICK_CD_BREAKOUT)
last_special = world.time + CLICK_CD_BREAKOUT
cuff_resist(I)
/mob/living/carbon/monkey/proc/should_target(var/mob/living/L)
if(L == src)
return 0
if(enemies[L])
return 1
// target non-monkey mobs when aggressive, with a small probability of monkey v monkey
if(aggressive && (!istype(L, /mob/living/carbon/monkey/) || prob(MONKEY_AGGRESSIVE_MVM_PROB)))
return 1
return 0
/mob/living/carbon/monkey/proc/handle_combat()
if(on_fire || buckled || restrained())
if(!resisting && prob(MONKEY_RESIST_PROB))
resisting = TRUE
walk_to(src,0)
resist()
else
resisting = FALSE
if(IsDeadOrIncap())
return TRUE
// have we been disarmed
if(!locate(/obj/item/weapon) in held_items)
best_force = 0
if(restrained() || blacklistItems[pickupTarget] || (pickupTarget && (pickupTarget.flags & NODROP)))
pickupTarget = null
if(!resisting && pickupTarget)
pickupTimer++
// next to target
if(Adjacent(pickupTarget) || Adjacent(pickupTarget.loc))
INVOKE_ASYNC(src, .proc/walk2derpless, pickupTarget.loc)
// who cares about these items, i want that one!
drop_all_held_items()
// on floor
if(isturf(pickupTarget.loc))
equip_item(pickupTarget)
pickupTarget = null
pickupTimer = 0
// in someones hand
else if(ismob(pickupTarget.loc))
var/mob/M = pickupTarget.loc
if(!pickpocketing)
pickpocketing = TRUE
M.visible_message("[src] starts trying to take [pickupTarget] from [M]", "[src] tries to take [pickupTarget]!")
INVOKE_ASYNC(src, .proc/pickpocket, M)
else
if(pickupTimer >= 8)
blacklistItems[pickupTarget] ++
pickupTarget = null
pickupTimer = 0
else
INVOKE_ASYNC(src, .proc/walk2derpless, pickupTarget.loc)
return TRUE
// nuh uh you don't pull me!
if(pulledby && (mode != MONKEY_IDLE || prob(MONKEY_PULL_AGGRO_PROB)))
if(Adjacent(pulledby))
a_intent = INTENT_DISARM
monkey_attack(pulledby)
retaliate(pulledby)
return TRUE
switch(mode)
if(MONKEY_IDLE) // idle
var/list/around = view(src, MONKEY_ENEMY_VISION)
bodyDisposal = locate(/obj/machinery/disposal/) in around
// scan for enemies
for(var/mob/living/L in around)
if( should_target(L) )
if(L.stat == CONSCIOUS)
emote(pick("roar","screech"))
retaliate(L)
return TRUE
else if(bodyDisposal)
target = L
mode = MONKEY_DISPOSE
return TRUE
// pickup any nearby objects
if(!pickupTarget && prob(MONKEY_PICKUP_PROB))
var/obj/item/I = locate(/obj/item/) in oview(5,src)
if(I && !blacklistItems[I])
pickupTarget = I
// I WANNA STEAL
if(!pickupTarget && prob(MONKEY_STEAL_PROB))
var/mob/living/carbon/human/H = locate(/mob/living/carbon/human/) in oview(5,src)
if(H)
pickupTarget = pick(H.held_items)
// clear any combat walking
if(!resisting)
walk_to(src,0)
return IsStandingStill()
if(MONKEY_HUNT) // hunting for attacker
if(health < MONKEY_FLEE_HEALTH)
mode = MONKEY_FLEE
return TRUE
if(target != null)
INVOKE_ASYNC(src, .proc/walk2derpless, target)
// pickup any nearby weapon
if(!pickupTarget && prob(MONKEY_WEAPON_PROB))
var/obj/item/weapon/W = locate(/obj/item/weapon/) in oview(2,src)
if(W && !blacklistItems[W] && W.force > best_force)
pickupTarget = W
// recruit other monkies
var/list/around = view(src, MONKEY_ENEMY_VISION)
for(var/mob/living/carbon/monkey/M in around)
if(M.mode == MONKEY_IDLE && prob(MONKEY_RECRUIT_PROB))
M.emote(pick("roar","screech"))
M.target = target
M.mode = MONKEY_HUNT
// switch targets
for(var/mob/living/L in around)
if(L != target && should_target(L) && L.stat == CONSCIOUS && prob(MONKEY_SWITCH_TARGET_PROB))
target = L
return TRUE
// if can't reach target for long enough, go idle
if(frustration >= MONKEY_HUNT_FRUSTRATION_LIMIT)
back_to_idle()
return TRUE
if(target && target.stat == CONSCIOUS) // make sure target exists
if(Adjacent(target) && isturf(target.loc)) // if right next to perp
// check if target has a weapon
var/obj/item/weapon/W = locate(/obj/item/weapon) in target.held_items
// if the target has a weapon, chance to disarm them
if(W && prob(MONKEY_ATTACK_DISARM_PROB))
pickupTarget = W
a_intent = INTENT_DISARM
monkey_attack(target)
else
a_intent = INTENT_HARM
monkey_attack(target)
return TRUE
else // not next to perp
var/turf/olddist = get_dist(src, target)
if((get_dist(src, target)) >= (olddist))
frustration++
else
frustration = 0
else
back_to_idle()
if(MONKEY_FLEE)
var/list/around = view(src, MONKEY_FLEE_VISION)
target = null
// flee from anyone who attacked us and we didn't beat down
for(var/mob/living/L in around)
if( enemies[L] && L.stat == CONSCIOUS )
target = L
if(target != null)
walk_away(src, target, MONKEY_ENEMY_VISION, 5)
else
back_to_idle()
return TRUE
if(MONKEY_DISPOSE)
// if can't dispose of body go back to idle
if(!target || !bodyDisposal || frustration >= MONKEY_DISPOSE_FRUSTRATION_LIMIT)
back_to_idle()
return TRUE
if(target.pulledby != src && !istype(target.pulledby, /mob/living/carbon/monkey/))
INVOKE_ASYNC(src, .proc/walk2derpless, target.loc)
if(Adjacent(target) && isturf(target.loc))
a_intent = INTENT_GRAB
target.grabbedby(src)
else
var/turf/olddist = get_dist(src, target)
if((get_dist(src, target)) >= (olddist))
frustration++
else
frustration = 0
else if(!disposing_body)
INVOKE_ASYNC(src, .proc/walk2derpless, bodyDisposal.loc)
if(Adjacent(bodyDisposal))
disposing_body = TRUE
addtimer(CALLBACK(src, .proc/stuff_mob_in), 5)
else
var/turf/olddist = get_dist(src, bodyDisposal)
if((get_dist(src, bodyDisposal)) >= (olddist))
frustration++
else
frustration = 0
return TRUE
return IsStandingStill()
/mob/living/carbon/monkey/proc/pickpocket(var/mob/M)
if(do_mob(src, M, MONKEY_ITEM_SNATCH_DELAY) && pickupTarget)
for(var/obj/item/I in M.held_items)
if(I == pickupTarget)
M.visible_message("<span class='danger'>[src] snatches [pickupTarget] from [M].</span>", "<span class='userdanger'>[src] snatched [pickupTarget]!</span>")
if(M.temporarilyRemoveItemFromInventory(pickupTarget) && !qdeleted(pickupTarget))
equip_item(pickupTarget)
else
M.visible_message("<span class='danger'>[src] tried to snatch [pickupTarget] from [M], but failed!</span>", "<span class='userdanger'>[src] tried to grab [pickupTarget]!</span>")
pickpocketing = FALSE
pickupTarget = null
pickupTimer = 0
/mob/living/carbon/monkey/proc/stuff_mob_in()
if(bodyDisposal && target && Adjacent(bodyDisposal))
bodyDisposal.stuff_mob_in(target, src)
disposing_body = FALSE
back_to_idle()
/mob/living/carbon/monkey/proc/back_to_idle()
if(pulling)
stop_pulling()
mode = MONKEY_IDLE
target = null
a_intent = INTENT_HELP
frustration = 0
walk_to(src,0)
// attack using a held weapon otherwise bite the enemy, then if we are angry there is a chance we might calm down a little
/mob/living/carbon/monkey/proc/monkey_attack(mob/living/L)
var/obj/item/weapon/Weapon = locate(/obj/item/weapon) in held_items
// attack with weapon if we have one
if(Weapon)
L.attackby(Weapon, src)
else
L.attack_paw(src)
// no de-aggro
if(aggressive)
return
// if we arn't enemies, we were likely recruited to attack this target, jobs done if we calm down so go back to idle
if(!enemies[L])
if( target == L && prob(MONKEY_HATRED_REDUCTION_PROB) )
back_to_idle()
return // already de-aggroed
if(prob(MONKEY_HATRED_REDUCTION_PROB))
enemies[L] --
// if we are not angry at our target, go back to idle
if(enemies[L] <= 0)
enemies.Remove(L)
if( target == L )
back_to_idle()
// get angry are a mob
/mob/living/carbon/monkey/proc/retaliate(mob/living/L)
mode = MONKEY_HUNT
target = L
enemies[L] += MONKEY_HATRED_AMOUNT
if(a_intent != INTENT_HARM)
emote(pick("roar","screech"))
a_intent = INTENT_HARM
/mob/living/carbon/monkey/attack_hand(mob/living/L)
if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
retaliate(L)
else if(L.a_intent == INTENT_DISARM && prob(MONKEY_RETALIATE_DISARM_PROB))
retaliate(L)
return ..()
/mob/living/carbon/monkey/attack_paw(mob/living/L)
if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
retaliate(L)
else if(L.a_intent == INTENT_DISARM && prob(MONKEY_RETALIATE_DISARM_PROB))
retaliate(L)
return ..()
/mob/living/carbon/monkey/attackby(obj/item/weapon/W, mob/user, params)
..()
if((W.force) && (!target) && (W.damtype != STAMINA) )
retaliate(user)
/mob/living/carbon/monkey/bullet_act(obj/item/projectile/Proj)
if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet))
if((Proj.damage_type == BURN) || (Proj.damage_type == BRUTE))
if(!Proj.nodamage && Proj.damage < src.health)
retaliate(Proj.firer)
..()
/mob/living/carbon/monkey/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0)
if(istype(AM, /obj/item))
var/obj/item/I = AM
if(I.throwforce < src.health && I.thrownby && ishuman(I.thrownby))
var/mob/living/carbon/human/H = I.thrownby
retaliate(H)
..()
/mob/living/carbon/monkey/Crossed(atom/movable/AM)
if(!IsDeadOrIncap() && ismob(AM) && target)
var/mob/living/carbon/monkey/M = AM
if(!istype(M) || !M)
return
knockOver(M)
return
..()
/mob/living/carbon/monkey/proc/monkeyDrop(var/obj/item/A)
if(A)
dropItemToGround(A, TRUE)
update_icons()
+2 -16
View File
@@ -1,19 +1,5 @@
/mob/living/carbon/monkey/gib_animation()
PoolOrNew(/obj/effect/overlay/temp/gib_animation, list(loc, "gibbed-m"))
new /obj/effect/overlay/temp/gib_animation(loc, "gibbed-m")
/mob/living/carbon/monkey/dust_animation()
PoolOrNew(/obj/effect/overlay/temp/dust_animation, list(loc, "dust-m"))
/mob/living/carbon/monkey/death(gibbed)
if(stat == DEAD)
return
stat = DEAD
if(!gibbed)
emote("deathgasp")
if(ticker && ticker.mode)
ticker.mode.check_win()
return ..(gibbed)
new /obj/effect/overlay/temp/dust_animation(loc, "dust-m")
@@ -1,82 +0,0 @@
/mob/living/carbon/monkey/emote(act,m_type=1,message = null)
if(stat == DEAD && (act != "deathgasp") || (status_flags & FAKEDEATH)) //if we're faking, don't emote at all
return
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)
var/muzzled = is_muzzled()
switch(act) //Ooh ooh ah ah keep this alphabetical ooh ooh ah ah!
if ("deathgasp","deathgasps")
message = "<b>[src]</b> lets out a faint chimper as it collapses and stops moving..."
m_type = 1
if ("gnarl","gnarls")
if (!muzzled)
message = "<B>[src]</B> gnarls and shows its teeth.."
m_type = 2
if ("me")
..()
return
if ("moan","moans")
message = "<B>[src]</B> moans!"
m_type = 2
if ("paw")
if (!src.restrained())
message = "<B>[src]</B> flails its paw."
m_type = 1
if ("roar","roars")
if (!muzzled)
message = "<B>[src]</B> roars."
m_type = 2
if ("roll","rolls")
if (!src.restrained())
message = "<B>[src]</B> rolls."
m_type = 1
if ("scratch","scratches")
if (!src.restrained())
message = "<B>[src]</B> scratches."
m_type = 1
if ("screech","screeches")
if (!muzzled)
message = "<B>[src]</B> screeches."
m_type = 2
if ("shiver","shivers")
message = "<B>[src]</B> shivers."
m_type = 2
if ("sign","signs")
if (!src.restrained())
message = text("<B>[src]</B> signs[].", (text2num(param) ? text(" the number []", text2num(param)) : null))
m_type = 1
if ("tail")
message = "<B>[src]</B> waves its tail."
m_type = 1
if ("help") //Ooh ah ooh ooh this is an exception to alphabetical ooh ooh.
src << "Help for monkey emotes. You can use these emotes with say \"*emote\":\n\naflap, airguitar, blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, dance, deathgasp, drool, flap, frown, gasp, gnarl, giggle, glare-(none)/mob, grin, jump, laugh, look, me, moan, nod, paw, point-(atom), roar, roll, scream, scratch, screech, shake, shiver, sigh, sign-#, sit, smile, sneeze, sniff, snore, stare-(none)/mob, sulk, sway, tail, tremble, twitch, twitch_s, wave whimper, wink, yawn"
else
..()
if ((message && src.stat == 0))
if(src.client)
log_emote("[name]/[key] : [message]")
if (m_type & 1)
visible_message(message)
else
audible_message(message)
return
@@ -1,32 +1,34 @@
/mob/living/carbon/monkey/can_equip(obj/item/I, slot, disable_warning = 0)
switch(slot)
if(slot_l_hand)
if(l_hand)
return 0
return 1
if(slot_r_hand)
if(r_hand)
return 0
return 1
if(slot_hands)
if(get_empty_held_indexes())
return TRUE
return FALSE
if(slot_wear_mask)
if(wear_mask)
return 0
return FALSE
if( !(I.slot_flags & SLOT_MASK) )
return 0
return 1
return FALSE
return TRUE
if(slot_neck)
if(wear_neck)
return FALSE
if( !(I.slot_flags & SLOT_NECK) )
return FALSE
return TRUE
if(slot_head)
if(head)
return 0
return FALSE
if( !(I.slot_flags & SLOT_HEAD) )
return 0
return 1
return FALSE
return TRUE
if(slot_back)
if(back)
return 0
return FALSE
if( !(I.slot_flags & SLOT_BACK) )
return 0
return 1
return 0 //Unsupported slot
return FALSE
return TRUE
return FALSE //Unsupported slot
+49 -21
View File
@@ -1,4 +1,4 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
/mob/living/carbon/monkey
@@ -10,34 +10,40 @@
if (notransform)
return
..()
if(..())
if(!client && stat == CONSCIOUS)
if(prob(33) && canmove && isturf(loc) && !pulledby)
step(src, pick(cardinal))
if(prob(1))
emote(pick("scratch","jump","roll","tail"))
if(!client)
if(stat == CONSCIOUS)
if(!handle_combat())
if(prob(33) && canmove && isturf(loc) && !pulledby)
step(src, pick(cardinal))
if(prob(1))
emote(pick("scratch","jump","roll","tail"))
else
walk_to(src,0)
/mob/living/carbon/monkey/handle_mutations_and_radiation()
if (radiation)
if (radiation > 100)
if(!weakened)
emote("collapse")
Weaken(10)
src << "<span class='danger'>You feel weak.</span>"
emote("collapse")
switch(radiation)
if(50 to 75)
if(prob(5))
if(!weakened)
emote("collapse")
Weaken(3)
src << "<span class='danger'>You feel weak.</span>"
emote("collapse")
if(75 to 100)
if(prob(1))
src << "<span class='danger'>You mutate!</span>"
randmutb(src)
randmutb()
emote("gasp")
domutcheck()
..()
@@ -81,29 +87,29 @@
switch(bodytemperature)
if(360 to 400)
throw_alert("temp", /obj/screen/alert/hot, 1)
adjustFireLoss(2)
apply_damage(HEAT_DAMAGE_LEVEL_1, BURN)
if(400 to 460)
throw_alert("temp", /obj/screen/alert/hot, 2)
adjustFireLoss(3)
apply_damage(HEAT_DAMAGE_LEVEL_2, BURN)
if(460 to INFINITY)
throw_alert("temp", /obj/screen/alert/hot, 3)
if(on_fire)
adjustFireLoss(8)
apply_damage(HEAT_DAMAGE_LEVEL_3, BURN)
else
adjustFireLoss(3)
apply_damage(HEAT_DAMAGE_LEVEL_2, BURN)
else if(bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT)
if(!istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell))
switch(bodytemperature)
if(200 to 260)
throw_alert("temp", /obj/screen/alert/cold, 1)
adjustFireLoss(0.5)
apply_damage(COLD_DAMAGE_LEVEL_1, BURN)
if(120 to 200)
throw_alert("temp", /obj/screen/alert/cold, 2)
adjustFireLoss(1.5)
apply_damage(COLD_DAMAGE_LEVEL_2, BURN)
if(-INFINITY to 120)
throw_alert("temp", /obj/screen/alert/cold, 3)
adjustFireLoss(3)
apply_damage(COLD_DAMAGE_LEVEL_3, BURN)
else
clear_alert("temp")
@@ -140,7 +146,29 @@
return 1
/mob/living/carbon/monkey/handle_fire()
if(..())
return
bodytemperature += BODYTEMP_HEATING_MAX
return
. = ..()
if(on_fire)
//the fire tries to damage the exposed clothes and items
var/list/burning_items = list()
//HEAD//
var/obj/item/clothing/head_clothes = null
if(wear_mask)
head_clothes = wear_mask
if(wear_neck)
head_clothes = wear_neck
if(head)
head_clothes = head
if(head_clothes)
burning_items += head_clothes
if(back)
burning_items += back
for(var/X in burning_items)
var/obj/item/I = X
if(!(I.resistance_flags & FIRE_PROOF))
I.take_damage(fire_stacks, BURN, "fire", 0)
bodytemperature += BODYTEMP_HEATING_MAX
+24 -195
View File
@@ -3,16 +3,21 @@
voice_name = "monkey"
verb_say = "chimpers"
icon = 'icons/mob/monkey.dmi'
icon_state = "monkey1"
icon_state = ""
gender = NEUTER
pass_flags = PASSTABLE
languages_spoken = MONKEY
languages_understood = MONKEY
ventcrawler = 1
ventcrawler = VENTCRAWLER_NUDE
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1)
type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey
gib_type = /obj/effect/decal/cleanable/blood/gibs
unique_name = 1
devourable = 1
bodyparts = list(/obj/item/bodypart/chest/monkey, /obj/item/bodypart/head/monkey, /obj/item/bodypart/l_arm/monkey,
/obj/item/bodypart/r_arm/monkey, /obj/item/bodypart/r_leg/monkey, /obj/item/bodypart/l_leg/monkey)
/mob/living/carbon/monkey/New()
verbs += /mob/living/proc/mob_sleep
@@ -22,31 +27,26 @@
gender = pick(MALE, FEMALE)
real_name = name
//initialize limbs, currently only used to handle cavity implant surgery, no dismemberment.
bodyparts = newlist(/obj/item/bodypart/chest, /obj/item/bodypart/head, /obj/item/bodypart/l_arm,
/obj/item/bodypart/r_arm, /obj/item/bodypart/r_leg, /obj/item/bodypart/l_leg)
for(var/X in bodyparts)
var/obj/item/bodypart/O = X
O.owner = src
//initialize limbs
create_bodyparts()
if(good_mutations.len) //genetic mutations have been set up.
initialize()
create_internal_organs()
..()
/mob/living/carbon/monkey/Initialize()
..()
create_dna(src)
dna.initialize_dna(random_blood_type())
/mob/living/carbon/monkey/create_internal_organs()
internal_organs += new /obj/item/organ/appendix
internal_organs += new /obj/item/organ/lungs
internal_organs += new /obj/item/organ/heart
internal_organs += new /obj/item/organ/brain
internal_organs += new /obj/item/organ/tongue
for(var/obj/item/organ/I in internal_organs)
I.Insert(src)
..()
/mob/living/carbon/monkey/initialize()
create_dna(src)
dna.initialize_dna(random_blood_type())
/mob/living/carbon/monkey/movement_delay()
if(reagents)
if(reagents.has_reagent("morphine"))
@@ -64,133 +64,6 @@
. += (283.222 - bodytemperature) / 10 * 1.75
return . + config.monkey_delay
/mob/living/carbon/monkey/attack_paw(mob/living/M)
if(..()) //successful monkey bite.
var/damage = rand(1, 5)
if (stat != DEAD)
adjustBruteLoss(damage)
updatehealth()
return
/mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L)
if(..()) //successful larva bite.
var/damage = rand(1, 3)
if(stat != DEAD)
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
adjustBruteLoss(damage)
updatehealth()
/mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M)
if(..()) //To allow surgery to return properly.
return
switch(M.a_intent)
if("help")
help_shake_act(M)
if("grab")
grabbedby(M)
if("harm")
M.do_attack_animation(src)
if (prob(75))
visible_message("<span class='danger'>[M] has punched [name]!</span>", \
"<span class='userdanger'>[M] has punched [name]!</span>")
playsound(loc, "punch", 25, 1, -1)
var/damage = rand(5, 10)
if (prob(40))
damage = rand(10, 15)
if ( (paralysis < 5) && (health > 0) )
Paralyse(rand(10, 15))
visible_message("<span class='danger'>[M] has knocked out [name]!</span>", \
"<span class='userdanger'>[M] has knocked out [name]!</span>")
adjustBruteLoss(damage)
add_logs(M, src, "attacked")
updatehealth()
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to punch [name]!</span>", \
"<span class='userdanger'>[M] has attempted to punch [name]!</span>")
if("disarm")
if (!( paralysis ))
M.do_attack_animation(src)
if (prob(25))
Paralyse(2)
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
add_logs(M, src, "pushed")
visible_message("<span class='danger'>[M] has pushed down [src]!</span>", \
"<span class='userdanger'>[M] has pushed down [src]!</span>")
else
if(drop_item())
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] has disarmed [src]!</span>", \
"<span class='userdanger'>[M] has disarmed [src]!</span>")
/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M)
if(..()) //if harm or disarm intent.
if (M.a_intent == "harm")
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))
visible_message("<span class='danger'>[M] has wounded [name]!</span>", \
"<span class='userdanger'>[M] has wounded [name]!</span>")
else
visible_message("<span class='danger'>[M] has slashed [name]!</span>", \
"<span class='userdanger'>[M] has slashed [name]!</span>")
if (stat != DEAD)
adjustBruteLoss(damage)
updatehealth()
add_logs(M, src, "attacked")
else
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to lunge at [name]!</span>", \
"<span class='userdanger'>[M] has attempted to lunge at [name]!</span>")
if (M.a_intent == "disarm")
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
if(prob(95))
Weaken(10)
visible_message("<span class='danger'>[M] has tackled down [name]!</span>", \
"<span class='userdanger'>[M] has tackled down [name]!</span>")
else
if(drop_item())
visible_message("<span class='danger'>[M] has disarmed [name]!</span>", \
"<span class='userdanger'>[M] has disarmed [name]!</span>")
add_logs(M, src, "disarmed")
updatehealth()
return
/mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M)
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
switch(M.melee_damage_type)
if(BRUTE)
adjustBruteLoss(damage)
if(BURN)
adjustFireLoss(damage)
if(TOX)
adjustToxLoss(damage)
if(OXY)
adjustOxyLoss(damage)
if(CLONE)
adjustCloneLoss(damage)
if(STAMINA)
adjustStaminaLoss(damage)
updatehealth()
/mob/living/carbon/monkey/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
var/damage = rand(5, 35)
if(M.is_adult)
damage = rand(20, 40)
adjustBruteLoss(damage)
updatehealth()
/mob/living/carbon/monkey/Stat()
..()
if(statpanel("Status"))
@@ -209,24 +82,6 @@
internal = null
return
/mob/living/carbon/monkey/ex_act(severity, target)
..()
switch(severity)
if(1)
gib()
return
if(2)
adjustBruteLoss(60)
adjustFireLoss(60)
adjustEarDamage(30,120)
if(3)
adjustBruteLoss(30)
if (prob(50))
Paralyse(10)
adjustEarDamage(15,60)
updatehealth()
return
/mob/living/carbon/monkey/IsAdvancedToolUser()//Unless its monkey mode monkeys cant use advanced tools
return 0
@@ -249,46 +104,27 @@
//Lasertag bullshit
if(lasercolor)
if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve
if((istype(r_hand,/obj/item/weapon/gun/energy/laser/redtag)) || (istype(l_hand,/obj/item/weapon/gun/energy/laser/redtag)))
if(is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/redtag))
threatcount += 4
if(lasercolor == "r")
if((istype(r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(l_hand,/obj/item/weapon/gun/energy/laser/bluetag)))
if(is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/bluetag))
threatcount += 4
return threatcount
//Check for weapons
if(judgebot.weaponscheck)
if(judgebot.check_for_weapons(l_hand))
threatcount += 4
if(judgebot.check_for_weapons(r_hand))
threatcount += 4
for(var/obj/item/I in held_items)
if(judgebot.check_for_weapons(I))
threatcount += 4
//mindshield implants imply trustworthyness
if(isloyal(src))
if(isloyal())
threatcount -= 1
return threatcount
/mob/living/carbon/monkey/acid_act(acidpwr, toxpwr, acid_volume)
if(wear_mask)
if(!wear_mask.unacidable)
wear_mask.acid_act(acidpwr)
update_inv_wear_mask()
else
src << "<span class='warning'>Your mask protects you from the acid.</span>"
return
take_organ_damage(min(6*toxpwr, acid_volume * acidpwr/10))
/mob/living/carbon/monkey/help_shake_act(mob/living/carbon/M)
if(health < 0 && ishuman(M))
var/mob/living/carbon/human/H = M
H.do_cpr(src)
else
..()
/mob/living/carbon/monkey/get_permeability_protection()
var/protection = 0
if(head)
@@ -298,13 +134,6 @@
protection = protection/7 //the rest of the body isn't covered.
return protection
/mob/living/carbon/monkey/check_eye_prot()
var/number = ..()
if(istype(src.wear_mask, /obj/item/clothing/mask))
var/obj/item/clothing/mask/MFP = src.wear_mask
number += MFP.flash_protect
return number
/mob/living/carbon/monkey/fully_heal(admin_revive = 0)
if(!getorganslot("lungs"))
var/obj/item/organ/lungs/L = new()
@@ -0,0 +1,216 @@
/mob/living/carbon/monkey/get_eye_protection()
var/number = ..()
if(istype(src.wear_mask, /obj/item/clothing/mask))
var/obj/item/clothing/mask/MFP = src.wear_mask
number += MFP.flash_protect
return number
/mob/living/carbon/monkey/help_shake_act(mob/living/carbon/M)
if(health < 0 && ishuman(M))
var/mob/living/carbon/human/H = M
H.do_cpr(src)
else
..()
/mob/living/carbon/monkey/attack_paw(mob/living/M)
if(..()) //successful monkey bite.
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
affecting = get_bodypart("chest")
if(M.limb_destroyer)
dismembering_strike(M, affecting.body_zone)
if(stat != DEAD)
var/dmg = rand(1, 5)
apply_damage(dmg, BRUTE, affecting)
damage_clothes(dmg, BRUTE, "melee", affecting.body_zone)
/mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L)
if(..()) //successful larva bite.
var/damage = rand(1, 3)
if(stat != DEAD)
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
if(!affecting)
affecting = get_bodypart("chest")
apply_damage(damage, BRUTE, affecting)
damage_clothes(damage, BRUTE, "melee", affecting.body_zone)
/mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M)
if(..()) //To allow surgery to return properly.
return
switch(M.a_intent)
if("help")
help_shake_act(M)
if("grab")
grabbedby(M)
if("harm")
M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
if (prob(75))
visible_message("<span class='danger'>[M] has punched [name]!</span>", \
"<span class='userdanger'>[M] has punched [name]!</span>", null, COMBAT_MESSAGE_RANGE)
playsound(loc, "punch", 25, 1, -1)
var/damage = rand(5, 10)
if (prob(40))
damage = rand(10, 15)
if ( (paralysis < 5) && (health > 0) )
Paralyse(rand(10, 15))
visible_message("<span class='danger'>[M] has knocked out [name]!</span>", \
"<span class='userdanger'>[M] has knocked out [name]!</span>", null, 5)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
if(!affecting)
affecting = get_bodypart("chest")
apply_damage(damage, BRUTE, affecting)
damage_clothes(damage, BRUTE, "melee", affecting.body_zone)
add_logs(M, src, "attacked")
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to punch [name]!</span>", \
"<span class='userdanger'>[M] has attempted to punch [name]!</span>", null, COMBAT_MESSAGE_RANGE)
if("disarm")
if (!paralysis)
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
if (prob(25))
Paralyse(2)
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
add_logs(M, src, "pushed")
visible_message("<span class='danger'>[M] has pushed down [src]!</span>", \
"<span class='userdanger'>[M] has pushed down [src]!</span>", null, COMBAT_MESSAGE_RANGE)
else
if(drop_item())
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] has disarmed [src]!</span>", \
"<span class='userdanger'>[M] has disarmed [src]!</span>", null, COMBAT_MESSAGE_RANGE)
/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M)
if(..()) //if harm or disarm intent.
if (M.a_intent == INTENT_HARM)
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))
visible_message("<span class='danger'>[M] has wounded [name]!</span>", \
"<span class='userdanger'>[M] has wounded [name]!</span>", null, COMBAT_MESSAGE_RANGE)
else
visible_message("<span class='danger'>[M] has slashed [name]!</span>", \
"<span class='userdanger'>[M] has slashed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
add_logs(M, src, "attacked")
if(!affecting)
affecting = get_bodypart("chest")
if(!dismembering_strike(M, affecting.body_zone)) //Dismemberment successful
return 1
apply_damage(damage, BRUTE, affecting)
damage_clothes(damage, BRUTE, "melee", affecting.body_zone)
else
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to lunge at [name]!</span>", \
"<span class='userdanger'>[M] has attempted to lunge at [name]!</span>", null, COMBAT_MESSAGE_RANGE)
if (M.a_intent == INTENT_DISARM)
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
if(prob(95))
Weaken(10)
visible_message("<span class='danger'>[M] has tackled down [name]!</span>", \
"<span class='userdanger'>[M] has tackled down [name]!</span>", null, COMBAT_MESSAGE_RANGE)
else
if(drop_item())
visible_message("<span class='danger'>[M] has disarmed [name]!</span>", \
"<span class='userdanger'>[M] has disarmed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(M, src, "disarmed")
updatehealth()
/mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M)
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
var/dam_zone = dismembering_strike(M, pick("chest", "l_hand", "r_hand", "l_leg", "r_leg"))
if(!dam_zone) //Dismemberment successful
return 1
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
affecting = get_bodypart("chest")
apply_damage(damage, M.melee_damage_type, affecting)
damage_clothes(damage, M.melee_damage_type, "melee", affecting.body_zone)
/mob/living/carbon/monkey/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
var/damage = rand(5, 35)
if(M.is_adult)
damage = rand(20, 40)
var/dam_zone = dismembering_strike(M, pick("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg"))
if(!dam_zone) //Dismemberment successful
return 1
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
affecting = get_bodypart("chest")
apply_damage(damage, BRUTE, affecting)
damage_clothes(damage, BRUTE, "melee", affecting.body_zone)
/mob/living/carbon/monkey/acid_act(acidpwr, acid_volume, bodyzone_hit)
. = 1
if(!bodyzone_hit || bodyzone_hit == "head")
if(wear_mask)
if(!(wear_mask.resistance_flags & UNACIDABLE))
wear_mask.acid_act(acidpwr)
else
src << "<span class='warning'>Your mask protects you from the acid.</span>"
return
if(head)
if(!(head.resistance_flags & UNACIDABLE))
head.acid_act(acidpwr)
else
src << "<span class='warning'>Your hat protects you from the acid.</span>"
return
take_bodypart_damage(acidpwr * min(0.6, acid_volume*0.1))
/mob/living/carbon/monkey/ex_act(severity, target, origin)
if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
return
..()
switch (severity)
if (1)
gib()
return
if (2)
take_overall_damage(60, 60)
damage_clothes(200, BRUTE, "bomb")
adjustEarDamage(30, 120)
if(prob(70))
Paralyse(10)
if(3)
take_overall_damage(30, 0)
damage_clothes(50, BRUTE, "bomb")
adjustEarDamage(15,60)
if (prob(50))
Paralyse(8)
//attempt to dismember bodyparts
if(severity <= 2)
var/max_limb_loss = round(4/severity) //so you don't lose four limbs at severity 3.
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(prob(50/severity) && BP.body_zone != "chest")
BP.brute_dam = BP.max_damage
BP.dismember()
max_limb_loss--
if(!max_limb_loss)
break
@@ -11,14 +11,10 @@
/mob/living/carbon/monkey/punpun/New()
Read_Memory()
if(relic_hat)
equip_to_slot_or_del(new relic_hat, slot_head)
if(relic_mask)
equip_to_slot_or_del(new relic_mask, slot_wear_mask)
if(ancestor_name)
name = ancestor_name
if(ancestor_chain > 1)
name += " [num2roman(ancestor_chain)]"
name += " \Roman[ancestor_chain]"
else
if(prob(5))
name = pick(rare_pet_monkey_names)
@@ -27,6 +23,14 @@
gender = pick(MALE, FEMALE)
..()
//These have to be after the parent new to ensure that the monkey
//bodyparts are actually created before we try to equip things to
//those slots
if(relic_hat)
equip_to_slot_or_del(new relic_hat, slot_head)
if(relic_mask)
equip_to_slot_or_del(new relic_mask, slot_wear_mask)
/mob/living/carbon/monkey/punpun/Life()
if(ticker.current_state == GAME_STATE_FINISHED && !memory_saved)
Write_Memory(0)
@@ -1,29 +1,47 @@
/mob/living/carbon/monkey/regenerate_icons()
if(!..())
update_body_parts()
update_hair()
update_inv_wear_mask()
update_inv_head()
update_inv_back()
update_icons()
update_transform()
/mob/living/carbon/monkey/update_icons()
cut_overlays()
icon_state = "monkey1"
for(var/image/I in overlays_standing)
add_overlay(I)
////////
/mob/living/carbon/monkey/update_hair()
remove_overlay(HAIR_LAYER)
var/obj/item/bodypart/head/HD = get_bodypart("head")
if(!HD) //Decapitated
return
if(disabilities & HUSK)
return
var/hair_hidden = 0
if(head)
var/obj/item/I = head
if(I.flags_inv & HIDEHAIR)
hair_hidden = 1
if(wear_mask)
var/obj/item/clothing/mask/M = wear_mask
if(M.flags_inv & HIDEHAIR)
hair_hidden = 1
if(!hair_hidden)
if(!getorgan(/obj/item/organ/brain)) //Applies the debrained overlay if there is no brain
var/image/I = image("icon"='icons/mob/human_face.dmi', "icon_state" = "debrained", "layer" = -HAIR_LAYER)
overlays_standing[HAIR_LAYER] = I
apply_overlay(HAIR_LAYER)
/mob/living/carbon/monkey/update_fire()
..("Monkey_burning")
/mob/living/carbon/monkey/update_inv_handcuffed()
remove_overlay(HANDCUFF_LAYER)
if(handcuffed)
overlays_standing[HANDCUFF_LAYER] = image("icon"='icons/mob/mob.dmi', "icon_state"="handcuff1", "layer"=-HANDCUFF_LAYER)
apply_overlay(HANDCUFF_LAYER)
/mob/living/carbon/monkey/update_inv_legcuffed()
remove_overlay(LEGCUFF_LAYER)
if(legcuffed)
@@ -47,6 +65,12 @@
I.screen_loc = ui_monkey_mask
client.screen += I
//update whether our neck item appears on our hud.
/mob/living/carbon/monkey/update_hud_neck(obj/item/I)
if(client && hud_used && hud_used.hud_shown)
I.screen_loc = ui_monkey_mask
client.screen += I
//update whether our back item appears on our hud.
/mob/living/carbon/monkey/update_hud_back(obj/item/I)
if(client && hud_used && hud_used.hud_shown)
+4
View File
@@ -24,3 +24,7 @@
var/obj/item/organ/tongue/T = getorganslot("tongue")
if(T)
. |= T.get_spans()
var/obj/item/I = get_active_held_item()
if(I)
. |= I.get_held_item_speechspans(src)

Some files were not shown because too many files have changed in this diff Show More