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
+42
View File
@@ -0,0 +1,42 @@
var/datum/subsystem/acid/SSacid
/datum/subsystem/acid
name = "Acid"
priority = 40
flags = SS_NO_INIT|SS_BACKGROUND
var/list/currentrun = list()
var/list/processing = list()
/datum/subsystem/acid/New()
NEW_SS_GLOBAL(SSacid)
/datum/subsystem/acid/stat_entry()
..("P:[processing.len]")
/datum/subsystem/acid/fire(resumed = 0)
if (!resumed)
src.currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while (currentrun.len)
var/obj/O = currentrun[currentrun.len]
currentrun.len--
if (!O || qdeleted(O))
processing -= O
if (MC_TICK_CHECK)
return
continue
if(O.acid_level && O.acid_processing())
else
O.overlays -= acid_overlay
O.priority_overlays -= acid_overlay
processing -= O
if (MC_TICK_CHECK)
return
+15 -7
View File
@@ -30,6 +30,7 @@ var/datum/subsystem/air/SSair
var/list/obj/machinery/atmos_machinery = list()
//Special functions lists
var/list/turf/active_super_conductivity = list()
var/list/turf/open/high_pressure_delta = list()
@@ -72,7 +73,7 @@ var/datum/subsystem/air/SSair
if(currentpart == SSAIR_PIPENETS || !resumed)
process_pipenets(resumed)
cost_pipenets = MC_AVERAGE(cost_pipenets, TICK_DELTA_TO_MS(world.tick_usage - timer))
if(paused)
if(state != SS_RUNNING)
return
resumed = 0
currentpart = SSAIR_ATMOSMACHINERY
@@ -81,7 +82,7 @@ var/datum/subsystem/air/SSair
timer = world.tick_usage
process_atmos_machinery(resumed)
cost_atmos_machinery = MC_AVERAGE(cost_atmos_machinery, TICK_DELTA_TO_MS(world.tick_usage - timer))
if(paused)
if(state != SS_RUNNING)
return
resumed = 0
currentpart = SSAIR_ACTIVETURFS
@@ -90,7 +91,7 @@ var/datum/subsystem/air/SSair
timer = world.tick_usage
process_active_turfs(resumed)
cost_turfs = MC_AVERAGE(cost_turfs, TICK_DELTA_TO_MS(world.tick_usage - timer))
if(paused)
if(state != SS_RUNNING)
return
resumed = 0
currentpart = SSAIR_EXCITEDGROUPS
@@ -99,7 +100,7 @@ var/datum/subsystem/air/SSair
timer = world.tick_usage
process_excited_groups(resumed)
cost_groups = MC_AVERAGE(cost_groups, TICK_DELTA_TO_MS(world.tick_usage - timer))
if(paused)
if(state != SS_RUNNING)
return
resumed = 0
currentpart = SSAIR_HIGHPRESSURE
@@ -108,7 +109,7 @@ var/datum/subsystem/air/SSair
timer = world.tick_usage
process_high_pressure_delta(resumed)
cost_highpressure = MC_AVERAGE(cost_highpressure, TICK_DELTA_TO_MS(world.tick_usage - timer))
if(paused)
if(state != SS_RUNNING)
return
resumed = 0
currentpart = SSAIR_HOTSPOTS
@@ -117,7 +118,7 @@ var/datum/subsystem/air/SSair
timer = world.tick_usage
process_hotspots(resumed)
cost_hotspots = MC_AVERAGE(cost_hotspots, TICK_DELTA_TO_MS(world.tick_usage - timer))
if(paused)
if(state != SS_RUNNING)
return
resumed = 0
currentpart = SSAIR_SUPERCONDUCTIVITY
@@ -126,7 +127,7 @@ var/datum/subsystem/air/SSair
timer = world.tick_usage
process_super_conductivity(resumed)
cost_superconductivity = MC_AVERAGE(cost_superconductivity, TICK_DELTA_TO_MS(world.tick_usage - timer))
if(paused)
if(state != SS_RUNNING)
return
resumed = 0
currentpart = SSAIR_PIPENETS
@@ -236,6 +237,8 @@ var/datum/subsystem/air/SSair
/datum/subsystem/air/proc/remove_from_active(turf/open/T)
active_turfs -= T
if(currentpart == SSAIR_ACTIVETURFS)
currentrun -= T
if(istype(T))
T.excited = 0
if(T.excited_group)
@@ -246,6 +249,8 @@ var/datum/subsystem/air/SSair
if(istype(T) && T.air)
T.excited = 1
active_turfs |= T
if(currentpart == SSAIR_ACTIVETURFS)
currentrun |= T
if(blockchanges && T.excited_group)
T.excited_group.garbage_collect()
else
@@ -264,6 +269,7 @@ var/datum/subsystem/air/SSair
if (T.blocks_air)
continue
T.Initalize_Atmos(times_fired)
CHECK_TICK
if(active_turfs.len)
var/starting_ats = active_turfs.len
@@ -279,6 +285,7 @@ var/datum/subsystem/air/SSair
var/list/new_turfs_to_check = list()
for(var/turf/open/T in turfs_to_check)
new_turfs_to_check += T.resolve_active_graph()
CHECK_TICK
active_turfs += new_turfs_to_check
turfs_to_check = new_turfs_to_check
@@ -289,6 +296,7 @@ var/datum/subsystem/air/SSair
var/datum/excited_group/EG = thing
EG.self_breakdown(space_is_all_consuming = 1)
EG.dismantle()
CHECK_TICK
var/msg = "HEY! LISTEN! [(world.timeofday - timer)/10] Seconds were wasted processing [starting_ats] turf(s) (connected to [ending_ats] other turfs) with atmos differences at round start."
world << "<span class='boldannounce'>[msg]</span>"
+2 -4
View File
@@ -15,7 +15,5 @@ var/datum/subsystem/assets/SSasset
A.register()
for(var/client/C in clients)
// Doing this to a client too soon after they've connected can cause issues, also the proc we call sleeps.
spawn(10)
getFilesSlow(C, cache, FALSE)
..()
addtimer(CALLBACK(GLOBAL_PROC, .proc/getFilesSlow, C, cache, FALSE), 10)
..()
+84
View File
@@ -0,0 +1,84 @@
var/datum/subsystem/augury/SSaugury
/datum/subsystem/augury
name = "Augury"
flags = SS_NO_INIT
var/list/watchers = list()
var/list/doombringers = list()
var/list/observers_given_action = list()
/datum/subsystem/augury/New()
NEW_SS_GLOBAL(SSaugury)
/datum/subsystem/augury/stat_entry(msg)
..("W:[watchers.len]|D:[doombringers.len]")
/datum/subsystem/augury/proc/register_doom(atom/A, severity)
doombringers[A] = severity
/datum/subsystem/augury/fire()
var/biggest_doom = null
var/biggest_threat = null
for(var/d in doombringers)
if(!d || qdeleted(d))
doombringers -= d
continue
var/threat = doombringers[d]
if((biggest_threat == null) || (biggest_threat < threat))
biggest_doom = d
biggest_threat = threat
if(doombringers.len)
for(var/i in player_list)
if(isobserver(i) && (!(observers_given_action[i])))
var/datum/action/innate/augury/A = new
A.Grant(i)
observers_given_action[i] = TRUE
else
for(var/i in observers_given_action)
if(observers_given_action[i] && isobserver(i))
var/mob/dead/observer/O = i
for(var/datum/action/innate/augury/A in O.actions)
qdel(A)
observers_given_action -= i
for(var/w in watchers)
if(!w)
watchers -= w
continue
var/mob/dead/observer/O = w
if(biggest_doom && (!O.orbiting || O.orbiting.orbiting != biggest_doom))
O.ManualFollow(biggest_doom)
/datum/action/innate/augury
name = "Auto Follow Debris"
icon_icon = 'icons/obj/meteor.dmi'
button_icon_state = "flaming"
background_icon_state = ACTION_BUTTON_DEFAULT_BACKGROUND
/datum/action/innate/augury/Destroy()
if(owner)
SSaugury.watchers -= owner
return ..()
/datum/action/innate/augury/Activate()
SSaugury.watchers += owner
owner << "<span class='notice'>You are now auto-following debris.</span>"
active = TRUE
UpdateButtonIcon()
/datum/action/innate/augury/Deactivate()
SSaugury.watchers -= owner
owner << "<span class='notice'>You are no longer auto-following debris.</span>"
active = FALSE
UpdateButtonIcon()
/datum/action/innate/augury/UpdateButtonIcon(status_only = FALSE)
..()
if(active)
button.icon_state = "template_active"
else
button.icon_state = "template"
@@ -0,0 +1,37 @@
#define COMMUNICATION_COOLDOWN 600
#define COMMUNICATION_COOLDOWN_AI 600
var/datum/subsystem/communications/SScommunications
/datum/subsystem/communications
name = "Communications"
flags = SS_NO_INIT | SS_NO_FIRE
var/silicon_message_cooldown
var/nonsilicon_message_cooldown
/datum/subsystem/communications/New()
NEW_SS_GLOBAL(SScommunications)
/datum/subsystem/communications/proc/can_announce(mob/living/user, is_silicon)
if(is_silicon && silicon_message_cooldown > world.time)
. = FALSE
else if(!is_silicon && nonsilicon_message_cooldown > world.time)
. = FALSE
else
. = TRUE
/datum/subsystem/communications/proc/make_announcement(mob/living/user, is_silicon, input)
if(!can_announce(user, is_silicon))
return FALSE
if(is_silicon)
minor_announce(html_decode(input),"[user.name] Announces:")
silicon_message_cooldown = world.time + COMMUNICATION_COOLDOWN_AI
else
priority_announce(html_decode(input), null, 'sound/misc/announce.ogg', "Captain")
nonsilicon_message_cooldown = world.time + COMMUNICATION_COOLDOWN
log_say("[key_name(user)] has made a priority announcement: [input]")
message_admins("[key_name_admin(user)] has made a priority announcement.")
#undef COMMUNICATION_COOLDOWN
#undef COMMUNICATION_COOLDOWN_AI
+3 -10
View File
@@ -59,14 +59,6 @@ var/datum/subsystem/events/SSevent
/datum/subsystem/events/proc/reschedule()
scheduled = world.time + rand(frequency_lower, max(frequency_lower,frequency_upper))
if(world.time > 108000) //3 hours
frequency_lower=1000
frequency_upper=1500
if(SSshuttle.emergency.mode < SHUTTLE_CALL)
SSshuttle.emergency.request(null, 1.5)
log_game("Round time limit reached. Shuttle has been auto-called.")
message_admins("Round time limit reached. Shuttle called.")
//selects a random event based on whether it can occur and it's 'weight'(probability)
/datum/subsystem/events/proc/spawnEvent()
if(!config.allow_random_events)
@@ -105,13 +97,14 @@ var/datum/subsystem/events/SSevent
continue
if (E.alertadmins)
message_admins("Random Event triggering: [E.name] ([E.typepath])")
deadchat_broadcast("[E.name] has just been randomly triggered!") //STOP ASSUMING IT'S BADMINS!
log_game("Random Event triggering: [E.name] ([E.typepath])")
return
/datum/round_event/proc/findEventArea() //Here's a nice proc to use to find an area for your event to land in!
var/list/safe_areas = list(
/area/turret_protected/ai,
/area/turret_protected/ai_upload,
/area/ai_monitored/turret_protected/ai,
/area/ai_monitored/turret_protected/ai_upload,
/area/engine,
/area/solar,
/area/holodeck,
-33
View File
@@ -1,33 +0,0 @@
var/datum/subsystem/fastprocess/SSfastprocess
/datum/subsystem/fastprocess
name = "Fast Process"
priority = 25
flags = SS_BACKGROUND|SS_POST_FIRE_TIMING|SS_NO_INIT
wait = 2
var/list/processing = list()
var/list/currentrun = list()
/datum/subsystem/fastprocess/New()
NEW_SS_GLOBAL(SSfastprocess)
/datum/subsystem/fastprocess/stat_entry()
..("FP:[processing.len]")
/datum/subsystem/fastprocess/fire(resumed = 0)
if (!resumed)
src.currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while(currentrun.len)
var/datum/thing = currentrun[currentrun.len]
currentrun.len--
if(thing)
thing.process(wait)
else
SSfastprocess.processing -= thing
if (MC_TICK_CHECK)
return
@@ -0,0 +1,42 @@
var/datum/subsystem/fire_burning/SSfire_burning
/datum/subsystem/fire_burning
name = "Fire Burning"
priority = 40
flags = SS_NO_INIT|SS_BACKGROUND
var/list/currentrun = list()
var/list/processing = list()
/datum/subsystem/fire_burning/New()
NEW_SS_GLOBAL(SSfire_burning)
/datum/subsystem/fire_burning/stat_entry()
..("P:[processing.len]")
/datum/subsystem/fire_burning/fire(resumed = 0)
if (!resumed)
src.currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while(currentrun.len)
var/obj/O = currentrun[currentrun.len]
currentrun.len--
if (!O || qdeleted(O))
processing -= O
if (MC_TICK_CHECK)
return
continue
if(O.resistance_flags & ON_FIRE)
O.take_damage(20, BURN, "fire", 0)
else
processing -= O
if (MC_TICK_CHECK)
return
+39 -22
View File
@@ -54,7 +54,7 @@ var/datum/subsystem/garbage_collector/SSgarbage
/datum/subsystem/garbage_collector/fire()
HandleToBeQueued()
if (!paused)
if(state == SS_RUNNING)
HandleQueue()
//If you see this proc high on the profile, what you are really seeing is the garbage collection/soft delete overhead in byond.
@@ -70,7 +70,7 @@ var/datum/subsystem/garbage_collector/SSgarbage
Queue(ref)
tobequeued.Cut(1, 2)
/datum/subsystem/garbage_collector/proc/HandleQueue(time_to_stop)
/datum/subsystem/garbage_collector/proc/HandleQueue()
delslasttick = 0
gcedlasttick = 0
var/time_to_kill = world.time - collection_timeout // Anything qdel() but not GC'd BEFORE this time needs to be manually del()
@@ -121,7 +121,7 @@ var/datum/subsystem/garbage_collector/SSgarbage
++totalgcs
/datum/subsystem/garbage_collector/proc/QueueForQueuing(datum/A)
if (istype(A) && isnull(A.gc_destroyed))
if (istype(A) && A.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
tobequeued += A
A.gc_destroyed = GC_QUEUED_FOR_QUEUING
@@ -142,7 +142,7 @@ var/datum/subsystem/garbage_collector/SSgarbage
queue[refid] = gctime
/datum/subsystem/garbage_collector/proc/HardQueue(datum/A)
if (istype(A) && isnull(A.gc_destroyed))
if (istype(A) && A.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
tobequeued += A
A.gc_destroyed = GC_QUEUED_FOR_HARD_DEL
@@ -158,19 +158,23 @@ var/datum/subsystem/garbage_collector/SSgarbage
if(!D)
return
#ifdef TESTING
SSgarbage.qdel_list += "[A.type]"
SSgarbage.qdel_list += "[D.type]"
#endif
if(!istype(D))
del(D)
else if(isnull(D.gc_destroyed))
D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED
var/hint = D.Destroy(force) // Let our friend know they're about to get fucked up.
if(!D)
return
switch(hint)
if (QDEL_HINT_QUEUE) //qdel should queue the object for deletion.
SSgarbage.QueueForQueuing(D)
if (QDEL_HINT_LETMELIVE, QDEL_HINT_IWILLGC) //qdel should let the object live after calling destory.
if (QDEL_HINT_IWILLGC)
return
if (QDEL_HINT_LETMELIVE) //qdel should let the object live after calling destory.
if(!force)
D.gc_destroyed = null //clear the gc variable (important!)
return
// Returning LETMELIVE after being told to force destroy
// indicates the objects Destroy() does not respect force
@@ -186,18 +190,18 @@ var/datum/subsystem/garbage_collector/SSgarbage
SSgarbage.HardQueue(D)
if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
del(D)
if (QDEL_HINT_PUTINPOOL) //qdel will put this object in the pool.
PlaceInPool(D, 0)
if (QDEL_HINT_FINDREFERENCE)//qdel will, if TESTING is enabled, display all references to this object, then queue the object for deletion.
SSgarbage.QueueForQueuing(D)
#ifdef TESTING
A.find_references()
D.find_references()
#endif
else
if(!SSgarbage.noqdelhint["[D.type]"])
SSgarbage.noqdelhint["[D.type]"] = "[D.type]"
testing("WARNING: [D.type] is not returning a qdel hint. It is being placed in the queue. Further instances of this type will also be queued.")
SSgarbage.QueueForQueuing(D)
else if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
CRASH("[D.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic")
// Returns 1 if the object has been queued for deletion.
/proc/qdeleted(datum/D)
@@ -207,25 +211,42 @@ var/datum/subsystem/garbage_collector/SSgarbage
return TRUE
return FALSE
// Returns true if the object's destroy has been called (set just before it is called)
/proc/qdestroying(datum/D)
if(!istype(D))
return FALSE
if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
return TRUE
return FALSE
// Default implementation of clean-up code.
// This should be overridden to remove all references pointing to the object being destroyed.
// Return the appropriate QDEL_HINT; in most cases this is QDEL_HINT_QUEUE.
/datum/proc/Destroy(force=FALSE)
tag = null
var/list/timers = active_timers
active_timers = null
for(var/thing in timers)
var/datum/timedevent/timer = thing
if (timer.spent)
continue
qdel(timer)
return QDEL_HINT_QUEUE
/datum/var/gc_destroyed //Time when this object was destroyed.
#ifdef TESTING
/client/var/running_find_references
/datum/var/running_find_references
/datum/verb/find_references()
/datum/verb/find_refs()
set category = "Debug"
set name = "Find References"
set background = 1
set src in world
find_references(FALSE)
/datum/proc/find_references(skip_alert)
running_find_references = type
if(usr && usr.client)
if(usr.client.running_find_references)
@@ -237,9 +258,10 @@ var/datum/subsystem/garbage_collector/SSgarbage
SSgarbage.next_fire = world.time + world.tick_lag
return
if(alert("Running this will create a lot of lag until it finishes. You can cancel it by running it again. Would you like to begin the search?", "Find References", "Yes", "No") == "No")
running_find_references = null
return
if(!skip_alert)
if(alert("Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", "Yes", "No") == "No")
running_find_references = null
return
//this keeps the garbage collector from failing to collect objects being searched for in here
SSgarbage.can_fire = 0
@@ -248,13 +270,7 @@ var/datum/subsystem/garbage_collector/SSgarbage
usr.client.running_find_references = type
testing("Beginning search for references to a [type].")
var/list/things = list()
for(var/client/thing)
things |= thing
for(var/datum/thing)
things |= thing
testing("Collected list of things in search for references to a [type]. ([things.len] Thing\s)")
for(var/datum/thing in things)
for(var/datum/thing in world)
if(usr && usr.client && !usr.client.running_find_references) return
for(var/varname in thing.vars)
var/variable = thing.vars[varname]
@@ -263,6 +279,7 @@ var/datum/subsystem/garbage_collector/SSgarbage
else if(islist(variable))
if(src in variable)
testing("Found [src.type] \ref[src] in [thing.type]'s [varname] list var.")
CHECK_TICK
testing("Completed search for references to a [type].")
if(usr && usr.client)
usr.client.running_find_references = null
@@ -290,7 +307,7 @@ var/datum/subsystem/garbage_collector/SSgarbage
qdel(src)
if(!running_find_references)
find_references()
find_references(TRUE)
/client/verb/show_qdeleted()
set category = "Debug"
+9 -4
View File
@@ -16,7 +16,7 @@ var/datum/subsystem/icon_smooth/SSicon_smooth
while(smooth_queue.len)
var/atom/A = smooth_queue[smooth_queue.len]
smooth_queue.len--
ss_smooth_icon(A)
smooth_icon(A)
if (MC_TICK_CHECK)
return
if (!smooth_queue.len)
@@ -25,8 +25,13 @@ var/datum/subsystem/icon_smooth/SSicon_smooth
/datum/subsystem/icon_smooth/Initialize()
smooth_zlevel(1,TRUE)
smooth_zlevel(2,TRUE)
for(var/V in smooth_queue)
var/queue = smooth_queue
smooth_queue = list()
for(var/V in queue)
var/atom/A = V
if(A.z == 1 || A.z == 2)
smooth_queue -= A
if(!A || A.z <= 2)
continue
smooth_icon(A)
CHECK_TICK
..()
+33 -16
View File
@@ -6,6 +6,8 @@ var/datum/subsystem/job/SSjob
flags = SS_NO_FIRE
var/list/occupations = list() //List of all jobs
var/list/name_occupations = list() //Dict of all jobs, keys are titles
var/list/type_occupations = list() //Dict of all jobs, keys are types
var/list/unassigned = list() //Players who need jobs
var/list/job_debug = list() //Debug info
var/initial_players_to_assign = 0 //used for checking against population caps
@@ -15,7 +17,8 @@ var/datum/subsystem/job/SSjob
/datum/subsystem/job/Initialize(timeofday)
SetupOccupations()
if(!occupations.len)
SetupOccupations()
if(config.load_jobs_from_txt)
LoadJobs()
..()
@@ -37,6 +40,8 @@ var/datum/subsystem/job/SSjob
if(!job.config_check())
continue
occupations += job
name_occupations[job.title] = job
type_occupations[J] = job
return 1
@@ -49,14 +54,15 @@ var/datum/subsystem/job/SSjob
/datum/subsystem/job/proc/GetJob(rank)
if(!rank)
return null
for(var/datum/job/J in occupations)
if(!J)
continue
if(J.title == rank)
return J
return null
if(!occupations.len)
SetupOccupations()
return name_occupations[rank]
/datum/subsystem/job/proc/GetJobType(jobtype)
if(!occupations.len)
SetupOccupations()
return type_occupations[jobtype]
/datum/subsystem/job/proc/AssignRole(mob/new_player/player, rank, latejoin=0)
Debug("Running AR, Player: [player], Rank: [rank], LJ: [latejoin]")
@@ -328,7 +334,7 @@ var/datum/subsystem/job/SSjob
for(var/mob/new_player/player in unassigned)
if(PopcapReached())
RejectPlayer(player)
else if(player.client.prefs.userandomjob)
else if(player.client.prefs.joblessrole == BERANDOMJOB)
GiveRandomJob(player)
Debug("DO, Standard Check end")
@@ -339,8 +345,15 @@ var/datum/subsystem/job/SSjob
for(var/mob/new_player/player in unassigned)
if(PopcapReached())
RejectPlayer(player)
Debug("AC2 Assistant located, Player: [player]")
AssignRole(player, "Assistant")
if(player.client.prefs.joblessrole == BEASSISTANT)
Debug("AC2 Assistant located, Player: [player]")
AssignRole(player, "Assistant")
else // For those who don't want to play if their preference were filled, back you go.
RejectPlayer(player)
for(var/mob/new_player/player in unassigned) //Players that wanted to back out but couldn't because they're antags (can you feel the edge case?)
GiveRandomJob(player)
return 1
//Gives the player the stuff he should have with his rank
@@ -375,7 +388,7 @@ var/datum/subsystem/job/SSjob
if(clear)
S = T
continue
if(istype(S, /obj/effect/landmark) && istype(S.loc, /turf))
if(istype(S, /obj/effect/landmark) && isturf(S.loc))
H.loc = S.loc
if(H.mind)
@@ -385,7 +398,6 @@ var/datum/subsystem/job/SSjob
var/new_mob = job.equip(H)
if(ismob(new_mob))
H = new_mob
job.apply_fingerprints(H)
H << "<b>You are the [rank].</b>"
H << "<b>As the [rank] you answer directly to [job.supervisors]. Special circumstances may change this.</b>"
@@ -394,7 +406,11 @@ var/datum/subsystem/job/SSjob
H << "<b>You are playing a job that is important for Game Progression. If you have to disconnect, please notify the admins via adminhelp.</b>"
if(config.minimal_access_threshold)
H << "<FONT color='blue'><B>As this station was initially staffed with a [config.jobs_have_minimal_access ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] have been added to your ID card.</B></font>"
return 1
if(job && H)
job.after_spawn(H)
return H
/datum/subsystem/job/proc/setup_officer_positions()
@@ -470,7 +486,8 @@ var/datum/subsystem/job/SSjob
/datum/subsystem/job/proc/RejectPlayer(mob/new_player/player)
if(player.mind && player.mind.special_role)
return
Debug("Popcap overflow Check observer located, Player: [player]")
if(PopcapReached())
Debug("Popcap overflow Check observer located, Player: [player]")
player << "<b>You have failed to qualify for any job you desired.</b>"
unassigned -= player
player.ready = 0
+97 -45
View File
@@ -1,67 +1,119 @@
// Needed for changeTurf() so it doesn't screw up before lighting overlays have been made.
var/lighting_overlays_initialized = FALSE
var/datum/subsystem/lighting/SSlighting
/var/list/lighting_update_lights = list() // List of lighting sources queued for update.
/var/list/lighting_update_corners = list() // List of lighting corners queued for update.
/var/list/lighting_update_overlays = list() // List of lighting overlays queued for update.
/var/list/lighting_update_lights_old = list() // List of lighting sources currently being updated.
/var/list/lighting_update_corners_old = list() // List of lighting corners currently being updated.
/var/list/lighting_update_overlays_old = list() // List of lighting overlays currently being updated.
#define SSLIGHTING_LIGHTS 1
#define SSLIGHTING_TURFS 2
/datum/subsystem/lighting
name = "lighting"
name = "Lighting"
init_order = 1
wait = 2
wait = 1
flags = SS_TICKER
priority = 25
display_order = 5
priority = 40
flags = SS_POST_FIRE_TIMING
var/list/changed_lights = list() //list of all datum/light_source that need updating
var/changed_lights_workload = 0 //stats on the largest number of lights (max changed_lights.len)
var/list/changed_turfs = list() //list of all turfs which may have a different light level
var/changed_turfs_workload = 0 //stats on the largest number of turfs changed (max changed_turfs.len)
/datum/subsystem/lighting/New()
NEW_SS_GLOBAL(SSlighting)
return ..()
/datum/subsystem/lighting/Initialize()
/datum/subsystem/lighting/stat_entry()
..("L:[round(changed_lights_workload,1)]|T:[round(changed_turfs_workload,1)]")
//Workhorse of lighting. It cycles through each light that needs updating. It updates their
//effects and then processes every turf in the queue, updating their lighting object's appearance
//Any light that returns 1 in check() deletes itself
//By using queues we are ensuring we don't perform more updates than are necessary
/datum/subsystem/lighting/fire(resumed = 0)
var/ticklimit = CURRENT_TICKLIMIT
//split our tick allotment in half so we don't spend it all on lightshift checks
CURRENT_TICKLIMIT = world.tick_usage + ((ticklimit-world.tick_usage)/2)
var/list/changed_lights = src.changed_lights
if (!resumed)
changed_lights_workload = MC_AVERAGE(changed_lights_workload, changed_lights.len)
var/i = 1
while (i <= changed_lights.len)
var/datum/light_source/LS = changed_lights[i++]
LS.check()
if (MC_TICK_CHECK)
break
if (i > 1)
changed_lights.Cut(1,i)
CURRENT_TICKLIMIT = ticklimit
var/list/changed_turfs = src.changed_turfs
if (!resumed)
changed_turfs_workload = MC_AVERAGE(changed_turfs_workload, changed_turfs.len)
i = 1
while (i <= changed_turfs.len)
var/turf/T = changed_turfs[i++]
if(T.lighting_changed)
T.redraw_lighting()
if (MC_TICK_CHECK)
break
if (i > 1)
changed_turfs.Cut(1,i)
//same as above except it attempts to shift ALL turfs in the world regardless of lighting_changed status
/datum/subsystem/lighting/Initialize(timeofday)
var/list/turfs_to_init = block(locate(1, 1, 1), locate(world.maxx, world.maxy, world.maxz))
if (config.starlight)
for(var/area/A in world)
if (A.dynamic_lighting == DYNAMIC_LIGHTING_IFSTARLIGHT)
if (A.lighting_use_dynamic == DYNAMIC_LIGHTING_IFSTARLIGHT)
A.luminosity = 0
create_all_lighting_overlays()
global.lighting_overlays_initialized = TRUE
CHECK_TICK
for(var/thing in changed_lights)
var/datum/light_source/LS = thing
LS.check()
CHECK_TICK
changed_lights.Cut()
/datum/subsystem/lighting/fire()
for(var/thing in turfs_to_init)
var/turf/T = thing
T.init_lighting()
CHECK_TICK
changed_turfs.Cut()
lighting_update_lights_old = lighting_update_lights //We use a different list so any additions to the update lists during a delay from scheck() don't cause things to be cut from the list without being updated.
lighting_update_lights = list()
for(var/datum/light_source/L in lighting_update_lights_old)
..()
if(L.check() || L.destroyed || L.force_update)
L.remove_lum()
if(!L.destroyed)
L.apply_lum()
//Used to strip valid information from an existing instance and transfer it to the replacement. i.e. when a crash occurs
//It works by using spawn(-1) to transfer the data, if there is a runtime the data does not get transfered but the loop
//does not crash
/datum/subsystem/lighting/Recover()
if(!istype(SSlighting.changed_turfs))
SSlighting.changed_turfs = list()
if(!istype(SSlighting.changed_lights))
SSlighting.changed_lights = list()
else if(L.vis_update) //We smartly update only tiles that became (in) visible to use.
L.smart_vis_update()
for(var/thing in SSlighting.changed_lights)
var/datum/light_source/LS = thing
spawn(-1) //so we don't crash the loop (inefficient)
LS.check()
L.vis_update = FALSE
L.force_update = FALSE
L.needs_update = FALSE
for(var/thing in changed_turfs)
var/turf/T = thing
if(T.lighting_changed)
spawn(-1)
T.redraw_lighting()
lighting_update_corners_old = lighting_update_corners //Same as above.
lighting_update_corners = list()
for(var/A in lighting_update_corners_old)
var/datum/lighting_corner/C = A
C.update_overlays()
C.needs_update = FALSE
lighting_update_overlays_old = lighting_update_overlays //Same as above.
lighting_update_overlays = list()
for(var/atom/movable/lighting_overlay/O in lighting_update_overlays_old)
O.update_overlay()
O.needs_update = 0
var/msg = "## DEBUG: [time2text(world.timeofday)] [name] subsystem restarted. Reports:\n"
for(var/varname in SSlighting.vars)
switch(varname)
if("tag","bestF","type","parent_type","vars")
continue
else
var/varval1 = SSlighting.vars[varname]
var/varval2 = vars[varname]
if(istype(varval1,/list))
varval1 = "/list([length(varval1)])"
varval2 = "/list([length(varval2)])"
msg += "\t [varname] = [varval1] -> [varval2]\n"
world.log << msg
+27 -1
View File
@@ -6,6 +6,9 @@ var/datum/subsystem/mapping/SSmapping
flags = SS_NO_FIRE
display_order = 50
var/list/nuke_tiles = list()
var/list/nuke_threats = list()
/datum/subsystem/mapping/New()
NEW_SS_GLOBAL(SSmapping)
@@ -34,11 +37,34 @@ var/datum/subsystem/mapping/SSmapping
else
space_zlevels += i
seedRuins(space_zlevels, rand(8,16), /area/space, space_ruins_templates)
seedRuins(space_zlevels, config.space_budget, /area/space, space_ruins_templates)
// Set up Z-level transistions.
setup_map_transitions()
..()
/* Nuke threats, for making the blue tiles on the station go RED
Used by the AI doomsday and the self destruct nuke.
*/
/datum/subsystem/mapping/proc/add_nuke_threat(datum/nuke)
nuke_threats[nuke] = TRUE
check_nuke_threats()
/datum/subsystem/mapping/proc/remove_nuke_threat(datum/nuke)
nuke_threats -= nuke
check_nuke_threats()
/datum/subsystem/mapping/proc/check_nuke_threats()
for(var/datum/d in nuke_threats)
if(!istype(d) || qdeleted(d))
nuke_threats -= d
var/threats = nuke_threats.len
for(var/N in nuke_tiles)
var/turf/open/floor/T = N
T.icon_state = (threats ? "rcircuitanim" : T.icon_regular_floor)
/datum/subsystem/mapping/Recover()
flags |= SS_NO_INIT
+1 -1
View File
@@ -87,7 +87,7 @@ var/datum/subsystem/minimap/SSminimap
var/obj/obj
var/list/obj_icons
// Don't use icons for space, just add objects in space if they exist.
if(istype(tile, /turf/open/space))
if(isspaceturf(tile))
obj = locate(/obj/structure/lattice/catwalk) in tile
if(obj)
tile_icon = new /icon('icons/obj/smooth_structures/catwalk.dmi', "catwalk", SOUTH)
-77
View File
@@ -1,77 +0,0 @@
var/datum/subsystem/objects/SSobj
/datum/var/isprocessing = 0
/datum/proc/process()
set waitfor = 0
STOP_PROCESSING(SSobj, src)
return 0
/datum/subsystem/objects
name = "Objects"
init_order = 12
priority = 40
var/list/atom_spawners = list()
var/list/processing = list()
var/list/currentrun = list()
var/list/burning = list()
/datum/subsystem/objects/New()
NEW_SS_GLOBAL(SSobj)
/datum/subsystem/objects/Initialize(timeofdayl)
trigger_atom_spawners()
setupGenetics()
for(var/thing in world)
var/atom/A = thing
A.initialize()
CHECK_TICK
. = ..()
/datum/subsystem/objects/proc/trigger_atom_spawners(zlevel, ignore_z=FALSE)
for(var/V in atom_spawners)
var/atom/A = V
if (!ignore_z && (zlevel && A.z != zlevel))
continue
A.spawn_atom_to_world()
/datum/subsystem/objects/stat_entry()
..("P:[processing.len]")
/datum/subsystem/objects/fire(resumed = 0)
if (!resumed)
src.currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while(currentrun.len)
var/datum/thing = currentrun[currentrun.len]
currentrun.len--
if(thing)
thing.process(wait)
else
SSobj.processing -= thing
if (MC_TICK_CHECK)
return
for(var/obj/burningobj in SSobj.burning)
if(burningobj && (burningobj.burn_state == ON_FIRE))
if(burningobj.burn_world_time < world.time)
burningobj.burn()
else
SSobj.burning.Remove(burningobj)
/datum/subsystem/objects/proc/setup_template_objects(list/objects)
trigger_atom_spawners(0, ignore_z=TRUE)
for(var/A in objects)
var/atom/B = A
B.initialize()
/datum/subsystem/objects/Recover()
if (istype(SSobj.atom_spawners))
atom_spawners = SSobj.atom_spawners
if (istype(SSobj.processing))
processing = SSobj.processing
if (istype(SSobj.burning))
burning = SSobj.burning
+50
View File
@@ -0,0 +1,50 @@
var/datum/subsystem/orbit/SSorbit
/datum/subsystem/orbit
name = "Orbits"
priority = 35
wait = 2
flags = SS_NO_INIT|SS_TICKER
var/list/currentrun = list()
var/list/processing = list()
/datum/subsystem/orbit/New()
NEW_SS_GLOBAL(SSorbit)
/datum/subsystem/orbit/stat_entry()
..("P:[processing.len]")
/datum/subsystem/orbit/fire(resumed = 0)
if (!resumed)
src.currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while (currentrun.len)
var/datum/orbit/O = currentrun[currentrun.len]
currentrun.len--
if (!O)
processing -= O
if (MC_TICK_CHECK)
return
continue
if (!O.orbiter)
qdel(O)
if (MC_TICK_CHECK)
return
continue
if (O.lastprocess >= world.time) //we already checked recently
if (MC_TICK_CHECK)
return
continue
var/targetloc = get_turf(O.orbiting)
if (targetloc != O.lastloc || O.orbiter.loc != targetloc)
O.Check(targetloc)
if (MC_TICK_CHECK)
return
+31 -46
View File
@@ -1,14 +1,14 @@
var/datum/subsystem/pai/SSpai
var/list/obj/item/device/paicard/pai_card_list = list()
/datum/subsystem/pai
name = "pAI"
init_order = 20
flags = SS_NO_FIRE|SS_NO_INIT
var/askDelay = 600
var/const/NEVER_FOR_THIS_ROUND = -1
flags = SS_NO_INIT|SS_NO_FIRE
var/list/candidates = list()
var/list/asked = list()
var/ghost_spam = FALSE
var/spam_delay = 100
/datum/subsystem/pai/New()
NEW_SS_GLOBAL(SSpai)
@@ -20,6 +20,8 @@ var/datum/subsystem/pai/SSpai
if(card.pai)
return
if(istype(card,/obj/item/device/paicard) && istype(candidate,/datum/paiCandidate))
if(check_ready(candidate) != candidate)
return FALSE
var/mob/living/silicon/pai/pai = new(card)
if(!candidate.name)
pai.name = pick(ninja_names)
@@ -29,7 +31,6 @@ var/datum/subsystem/pai/SSpai
pai.key = candidate.key
card.setPersonality(pai)
card.looking_for_personality = 0
ticker.mode.update_cult_icons_removed(card.pai.mind)
ticker.mode.update_rev_icons_removed(card.pai.mind)
@@ -76,8 +77,8 @@ var/datum/subsystem/pai/SSpai
if("submit")
if(candidate)
candidate.ready = 1
for(var/obj/item/device/paicard/p in world)
if(p.looking_for_personality == 1)
for(var/obj/item/device/paicard/p in pai_card_list)
if(!p.pai)
p.alertUpdate()
usr << browse(null, "window=paiRecruit")
return
@@ -134,17 +135,31 @@ var/datum/subsystem/pai/SSpai
M << browse(dat, "window=paiRecruit")
/datum/subsystem/pai/proc/spam_again()
ghost_spam = FALSE
/datum/subsystem/pai/proc/check_ready(var/datum/paiCandidate/C)
if(!C.ready)
return FALSE
for(var/mob/dead/observer/O in player_list)
if(O.key == C.key)
return C
return FALSE
/datum/subsystem/pai/proc/findPAI(obj/item/device/paicard/p, mob/user)
requestRecruits()
if(!ghost_spam)
ghost_spam = TRUE
for(var/mob/dead/observer/G in player_list)
if(!G.key || !G.client)
continue
if(!(ROLE_PAI in G.client.prefs.be_special))
continue
//G << 'sound/misc/server-ready.ogg' //Alerting them to their consideration
G << "<span class='ghostalert'>Someone is requesting a pAI personality! Use the pAI button to submit yourself as one.</span>"
addtimer(CALLBACK(src, .proc/spam_again), spam_delay)
var/list/available = list()
for(var/datum/paiCandidate/c in SSpai.candidates)
if(c.ready)
var/found = 0
for(var/mob/dead/observer/o in player_list)
if(o.key == c.key)
found = 1
if(found)
available.Add(c)
available.Add(check_ready(c))
var/dat = ""
dat += {"
@@ -180,36 +195,6 @@ var/datum/subsystem/pai/SSpai
user << browse(dat, "window=findPai")
/datum/subsystem/pai/proc/requestRecruits()
for(var/mob/dead/observer/O in player_list)
if(jobban_isbanned(O, ROLE_PAI))
continue
if(asked[O.ckey])
if(world.time < asked[O.ckey] + askDelay || asked[O.ckey] == NEVER_FOR_THIS_ROUND)
continue
else
asked.Remove(O.ckey)
if(O.client)
var/hasSubmitted = 0
for(var/datum/paiCandidate/c in SSpai.candidates)
if(c.key == O.key)
hasSubmitted = 1
if(!hasSubmitted && (ROLE_PAI in O.client.prefs.be_special))
question(O.client)
/datum/subsystem/pai/proc/question(client/C)
set waitfor = 0
if(!C)
return
asked[C.ckey] = world.time
var/response = tgalert(C, "Someone is requesting a pAI personality. Would you like to play as a personal AI?", "pAI Request", "Yes", "No", "Never for this round", StealFocus=0, Timeout=askDelay)
if(!C)
return //handle logouts that happen whilst the alert is waiting for a response.
if(response == "Yes")
recruitWindow(C.mob)
else if (response == "Never for this round")
asked[C.ckey] = NEVER_FOR_THIS_ROUND
/datum/paiCandidate
var/name
var/key
+36 -6
View File
@@ -1,12 +1,42 @@
var/datum/subsystem/parallax/SSparallax
/datum/subsystem/parallax
name = "Space Parallax"
init_order = 18
flags = SS_NO_FIRE
name = "parallax"
wait = 2
flags = SS_POST_FIRE_TIMING | SS_FIRE_IN_LOBBY | SS_BACKGROUND | SS_NO_INIT
priority = 65
var/list/currentrun
/datum/subsystem/parallax/New()
NEW_SS_GLOBAL(SSparallax)
NEW_SS_GLOBAL(SSparallax)
return ..()
/datum/subsystem/parallax/Initialize()
create_global_parallax_icons()
/datum/subsystem/parallax/fire(resumed = 0)
if (!resumed)
src.currentrun = clients.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while(length(currentrun))
var/client/C = currentrun[currentrun.len]
currentrun.len--
if (!C || !C.eye)
if (MC_TICK_CHECK)
return
continue
var/atom/movable/A = C.eye
if(!A)
return
for (A; isloc(A.loc) && !isturf(A.loc); A = A.loc);
if(A != C.movingmob)
if(C.movingmob != null)
C.movingmob.client_mobs_in_contents -= C.mob
UNSETEMPTY(C.movingmob.client_mobs_in_contents)
LAZYINITLIST(A.client_mobs_in_contents)
A.client_mobs_in_contents += C.mob
C.movingmob = A
if (MC_TICK_CHECK)
return
currentrun = null
+130
View File
@@ -0,0 +1,130 @@
var/datum/subsystem/persistence/SSpersistence
/datum/subsystem/persistence
name = "Persistence"
init_order = -100
flags = SS_NO_FIRE
var/savefile/secret_satchels
var/list/satchel_blacklist = list() //this is a typecache
var/list/new_secret_satchels = list() //these are objects
var/old_secret_satchels = ""
var/list/obj/structure/chisel_message/chisel_messages = list()
var/list/saved_messages = list()
var/savefile/chisel_messages_sav
/datum/subsystem/persistence/New()
NEW_SS_GLOBAL(SSpersistence)
/datum/subsystem/persistence/Initialize()
LoadSatchels()
LoadPoly()
LoadChiselMessages()
..()
/datum/subsystem/persistence/proc/LoadSatchels()
secret_satchels = new /savefile("data/npc_saves/SecretSatchels.sav")
satchel_blacklist = typecacheof(list(/obj/item/stack/tile/plasteel, /obj/item/weapon/crowbar))
secret_satchels[MAP_NAME] >> old_secret_satchels
var/list/expanded_old_satchels = list()
var/placed_satchels = 0
if(!isnull(old_secret_satchels))
expanded_old_satchels = splittext(old_secret_satchels,"#")
if(PlaceSecretSatchel(expanded_old_satchels))
placed_satchels++
else
expanded_old_satchels.len = 0
var/list/free_satchels = list()
for(var/turf/T in shuffle(block(locate(TRANSITIONEDGE,TRANSITIONEDGE,ZLEVEL_STATION), locate(world.maxx-TRANSITIONEDGE,world.maxy-TRANSITIONEDGE,ZLEVEL_STATION)))) //Nontrivially expensive but it's roundstart only
if(isfloorturf(T) && !istype(T,/turf/open/floor/plating/))
free_satchels += new /obj/item/weapon/storage/backpack/satchel/flat/secret(T)
if(!isemptylist(free_satchels) && ((free_satchels.len + placed_satchels) >= (50 - expanded_old_satchels.len) * 0.1)) //up to six tiles, more than enough to kill anything that moves
break
/datum/subsystem/persistence/proc/PlaceSecretSatchel(list/expanded_old_satchels)
var/satchel_string
if(expanded_old_satchels.len >= 20) //guards against low drop pools assuring that one player cannot reliably find his own gear.
satchel_string = pick_n_take(expanded_old_satchels)
old_secret_satchels = jointext(expanded_old_satchels,"#")
secret_satchels[MAP_NAME] << old_secret_satchels
var/list/chosen_satchel = splittext(satchel_string,"|")
if(!chosen_satchel || isemptylist(chosen_satchel) || chosen_satchel.len != 3) //Malformed
return 0
var/path = text2path(chosen_satchel[3]) //If the item no longer exist, this returns null
if(!path)
return 0
var/obj/item/weapon/storage/backpack/satchel/flat/F = new()
F.x = text2num(chosen_satchel[1])
F.y = text2num(chosen_satchel[2])
F.z = ZLEVEL_STATION
if(isfloorturf(F.loc) && !istype(F.loc,/turf/open/floor/plating/))
F.hide(1)
new path(F)
return 1
/datum/subsystem/persistence/proc/LoadPoly()
for(var/mob/living/simple_animal/parrot/Poly/P in living_mob_list)
twitterize(P.speech_buffer, "polytalk")
break //Who's been duping the bird?!
/datum/subsystem/persistence/proc/LoadChiselMessages()
chisel_messages_sav = new /savefile("data/npc_saves/ChiselMessages.sav")
var/saved_json
chisel_messages_sav[MAP_NAME] >> saved_json
if(!saved_json)
return
var/saved_messages = json_decode(saved_json)
for(var/item in saved_messages)
var/turf/T = locate(item["x"], item["y"], ZLEVEL_STATION)
if(!isturf(T))
continue
if(locate(/obj/structure/chisel_message) in T)
continue
var/obj/structure/chisel_message/M = new(T)
M.unpack(item)
if(!M.loc)
M.persists = FALSE
qdel(M)
/datum/subsystem/persistence/proc/CollectData()
CollectChiselMessages()
CollectSecretSatchels()
/datum/subsystem/persistence/proc/CollectSecretSatchels()
for(var/A in new_secret_satchels)
var/obj/item/weapon/storage/backpack/satchel/flat/F = A
if(qdeleted(F) || F.z != ZLEVEL_STATION || F.invisibility != INVISIBILITY_MAXIMUM)
continue
var/list/savable_obj = list()
for(var/obj/O in F)
if(is_type_in_typecache(O, satchel_blacklist) || O.admin_spawned)
continue
if(O.persistence_replacement)
savable_obj += O.persistence_replacement
else
savable_obj += O.type
if(isemptylist(savable_obj))
continue
old_secret_satchels += "[F.x]|[F.y]|[pick(savable_obj)]#"
secret_satchels[MAP_NAME] << old_secret_satchels
/datum/subsystem/persistence/proc/CollectChiselMessages()
for(var/obj/structure/chisel_message/M in chisel_messages)
saved_messages += list(M.pack())
chisel_messages_sav[MAP_NAME] << json_encode(saved_messages)
/datum/subsystem/persistence/proc/SaveChiselMessage(obj/structure/chisel_message/M)
saved_messages += list(M.pack()) // dm eats one list.
+33
View File
@@ -0,0 +1,33 @@
#define PING_BUFFER_TIME 25
var/datum/subsystem/ping/SSping
/datum/subsystem/ping
name = "Ping"
wait = 6
flags = SS_NO_INIT|SS_POST_FIRE_TIMING|SS_FIRE_IN_LOBBY
priority = 10
var/list/currentrun
/datum/subsystem/ping/New()
NEW_SS_GLOBAL(SSping)
/datum/subsystem/ping/fire(resumed = FALSE)
if (!resumed)
src.currentrun = clients.Copy()
var/list/currentrun = src.currentrun
while (length(currentrun))
var/client/C = currentrun[currentrun.len]
currentrun.len--
if (!C || world.time - C.connection_time < PING_BUFFER_TIME || C.inactivity >= (wait-1))
if (MC_TICK_CHECK)
return
continue
winset(C, null, "command=.update_ping+[world.time+world.tick_lag*world.tick_usage/100]")
if (MC_TICK_CHECK) //one day, when ss13 has 1000 people per server, you guys are gonna be glad I added this tick check
return
currentrun = null
#undef PING_BUFFER_TIME
@@ -0,0 +1,10 @@
//Fires five times every second.
var/datum/subsystem/processing/fastprocess/SSfastprocess
/datum/subsystem/processing/fastprocess
name = "Fast Processing"
wait = 2
stat_tag = "FP"
/datum/subsystem/processing/fastprocess/New()
NEW_SS_GLOBAL(SSfastprocess)
@@ -0,0 +1,11 @@
var/datum/subsystem/processing/flightpacks/SSflightpacks
/datum/subsystem/processing/flightpacks
name = "Flightpack Movement"
priority = 30
wait = 2
stat_tag = "FM"
flags = SS_NO_INIT|SS_TICKER|SS_KEEP_TIMING
/datum/subsystem/processing/flightpacks/New()
NEW_SS_GLOBAL(SSflightpacks)
@@ -0,0 +1,86 @@
var/datum/subsystem/objects/SSobj
#define INITIALIZATION_INSSOBJ 0 //New should not call Initialize
#define INITIALIZATION_INNEW_MAPLOAD 1 //New should call Initialize(TRUE)
#define INITIALIZATION_INNEW_REGULAR 2 //New should call Initialize(FALSE)
/datum/var/isprocessing = 0
/datum/proc/process()
set waitfor = 0
STOP_PROCESSING(SSobj, src)
return 0
/datum/subsystem/objects
name = "Objects"
init_order = 12
priority = 40
var/initialized = INITIALIZATION_INSSOBJ
var/old_initialized
var/list/processing = list()
var/list/currentrun = list()
/datum/subsystem/objects/New()
NEW_SS_GLOBAL(SSobj)
/datum/subsystem/objects/Initialize(timeofdayl)
fire_overlay.appearance_flags = RESET_COLOR
setupGenetics() //to set the mutations' place in structural enzymes, so monkey.initialize() knows where to put the monkey mutation.
initialized = INITIALIZATION_INNEW_MAPLOAD
InitializeAtoms()
. = ..()
/datum/subsystem/objects/proc/InitializeAtoms(list/objects = null)
if(initialized == INITIALIZATION_INSSOBJ)
return
initialized = INITIALIZATION_INNEW_MAPLOAD
if(objects)
for(var/thing in objects)
var/atom/A = thing
A.Initialize(TRUE)
CHECK_TICK
else
for(var/atom/A in world)
if(!A.initialized) //this check is to make sure we don't call it twice on an object that was created in a previous Initialize call
var/start_tick = world.time
A.Initialize(TRUE)
if(start_tick != world.time)
WARNING("[A]: [A.type] slept during it's Initialize!")
CHECK_TICK
initialized = INITIALIZATION_INNEW_REGULAR
/datum/subsystem/objects/proc/map_loader_begin()
old_initialized = initialized
initialized = INITIALIZATION_INSSOBJ
/datum/subsystem/objects/proc/map_loader_stop()
initialized = old_initialized
/datum/subsystem/objects/stat_entry()
..("P:[processing.len]")
/datum/subsystem/objects/fire(resumed = 0)
if (!resumed)
src.currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while(currentrun.len)
var/datum/thing = currentrun[currentrun.len]
currentrun.len--
if(thing)
thing.process(wait)
else
SSobj.processing -= thing
if (MC_TICK_CHECK)
return
/datum/subsystem/objects/Recover()
initialized = SSobj.initialized
if(initialized == INITIALIZATION_INNEW_MAPLOAD)
InitializeAtoms()
old_initialized = SSobj.old_initialized
if (istype(SSobj.processing))
processing = SSobj.processing
@@ -0,0 +1,34 @@
//Used to process objects. Fires once every second.
var/datum/subsystem/processing/SSprocessing
/datum/subsystem/processing
name = "Processing"
priority = 25
flags = SS_BACKGROUND|SS_POST_FIRE_TIMING|SS_NO_INIT
wait = 10
var/stat_tag = "P" //Used for logging
var/list/processing = list()
var/list/currentrun = list()
/datum/subsystem/processing/New()
NEW_SS_GLOBAL(SSprocessing)
/datum/subsystem/processing/stat_entry()
..("[stat_tag]:[processing.len]")
/datum/subsystem/processing/fire(resumed = 0)
if (!resumed)
currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/current_run = currentrun
while(current_run.len)
var/datum/thing = current_run[current_run.len]
current_run.len--
if(thing)
thing.process(wait)
else
processing -= thing
if (MC_TICK_CHECK)
return
+17
View File
@@ -0,0 +1,17 @@
var/datum/subsystem/religion/SSreligion
/datum/subsystem/religion
name = "Religion"
init_order = 19
flags = SS_NO_FIRE|SS_NO_INIT
var/bible_deity_name
var/Bible_icon_state
var/Bible_item_state
var/Bible_name
var/Bible_deity_name
var/holy_weapon
/datum/subsystem/religion/New()
NEW_SS_GLOBAL(SSreligion)
@@ -3,12 +3,16 @@ var/datum/subsystem/server_maint/SSserver
/datum/subsystem/server_maint
name = "Server Tasks"
wait = 6000
init_order = 19
flags = SS_NO_TICK_CHECK|SS_NO_INIT
flags = SS_NO_TICK_CHECK
/datum/subsystem/server_maint/New()
NEW_SS_GLOBAL(SSserver)
/datum/subsystem/server_maint/Initialize(timeofday)
if (config.hub)
world.visibility = 1
..()
/datum/subsystem/server_maint/fire()
//handle kicking inactive players
if(config.kick_inactive > 0)
@@ -17,7 +21,7 @@ var/datum/subsystem/server_maint/SSserver
if(!istype(C.mob, /mob/dead))
log_access("AFK: [key_name(C)]")
C << "<span class='danger'>You have been inactive for more than 10 minutes and have been disconnected.</span>"
del(C)
qdel(C)
if(config.sql_enabled)
sql_poll_players()
+281 -20
View File
@@ -1,3 +1,5 @@
#define HIGHLIGHT_DYNAMIC_TRANSIT 1
var/datum/subsystem/shuttle/SSshuttle
/datum/subsystem/shuttle
@@ -10,6 +12,10 @@ var/datum/subsystem/shuttle/SSshuttle
var/list/stationary = list()
var/list/transit = list()
var/list/turf/transit_turfs = list()
var/list/transit_requesters = list()
var/clear_transit = FALSE
//emergency shuttle stuff
var/obj/docking_port/mobile/emergency/emergency
var/obj/docking_port/mobile/emergency/backup/backup_shuttle
@@ -18,6 +24,7 @@ var/datum/subsystem/shuttle/SSshuttle
var/emergencyEscapeTime = 1200 //time taken for emergency shuttle to reach a safe distance after leaving station (in deciseconds)
var/area/emergencyLastCallLoc
var/emergencyNoEscape
var/list/hostileEnvironments = list()
//supply shuttle stuff
var/obj/docking_port/mobile/supply/supply
@@ -33,6 +40,11 @@ var/datum/subsystem/shuttle/SSshuttle
var/datum/round_event/shuttle_loan/shuttle_loan
var/shuttle_purchased = FALSE //If the station has purchased a replacement escape shuttle this round
var/list/shuttle_purchase_requirements_met = list() //For keeping track of ingame events that would unlock new shuttles, such as defeating a boss or discovering a secret item
var/lockdown = FALSE //disallow transit after nuke goes off
/datum/subsystem/shuttle/New()
NEW_SS_GLOBAL(SSshuttle)
@@ -53,16 +65,87 @@ var/datum/subsystem/shuttle/SSshuttle
supply_packs[P.type] = P
initial_move()
..()
setup_transit_zone()
#ifdef HIGHLIGHT_DYNAMIC_TRANSIT
color_space()
#endif
/datum/subsystem/shuttle/proc/setup_transit_zone()
if(transit_markers.len == 0)
WARNING("No /obj/effect/landmark/transit placed on the map!")
return
// transit zone
var/turf/A = get_turf(transit_markers[1])
var/turf/B = get_turf(transit_markers[2])
for(var/i in block(A, B))
var/turf/T = i
T.ChangeTurf(/turf/open/space)
transit_turfs += T
T.flags |= UNUSED_TRANSIT_TURF
#ifdef HIGHLIGHT_DYNAMIC_TRANSIT
/datum/subsystem/shuttle/proc/color_space()
if(transit_markers.len == 0)
WARNING("No /obj/effect/landmark/transit placed on the map!")
return
var/turf/A = get_turf(transit_markers[1])
var/turf/B = get_turf(transit_markers[2])
for(var/i in block(A, B))
var/turf/T = i
// Only dying the "pure" space, not the transit tiles
if(istype(T, /turf/open/space/transit) || !isspaceturf(T))
continue
if((T.x == A.x) || (T.x == B.x) || (T.y == A.y) || (T.y == B.y))
T.color = "#ffff00"
else
T.color = "#00ffff"
#endif
//world.log << "[transit_turfs.len] transit turfs registered"
/datum/subsystem/shuttle/fire()
for(var/thing in mobile)
if(thing)
var/obj/docking_port/mobile/P = thing
P.check()
if(!thing)
mobile.Remove(thing)
continue
mobile.Remove(thing)
var/obj/docking_port/mobile/P = thing
P.check()
var/changed_transit = FALSE
for(var/thing in transit)
var/obj/docking_port/stationary/transit/T = thing
if(!T.owner)
qdel(T, force=TRUE)
changed_transit = TRUE
// This next one removes transit docks/zones that aren't
// immediately being used. This will mean that the zone creation
// code will be running a lot.
var/obj/docking_port/mobile/owner = T.owner
if(owner)
var/idle = owner.mode == SHUTTLE_IDLE
var/not_centcom_evac = owner.launch_status == NOLAUNCH
var/not_in_use = (!T.get_docked())
if(idle && not_centcom_evac && not_in_use)
qdel(T, force=TRUE)
changed_transit = TRUE
if(clear_transit)
transit_requesters.Cut()
for(var/i in transit)
qdel(i, force=TRUE)
setup_transit_zone()
clear_transit = FALSE
changed_transit = TRUE
#ifdef HIGHLIGHT_DYNAMIC_TRANSIT
if(changed_transit)
color_space()
#endif
while(transit_requesters.len)
var/requester = popleft(transit_requesters)
var/success = generate_transit_dock(requester)
if(!success) // BACK OF THE QUEUE
transit_requesters += requester
if(MC_TICK_CHECK)
return
/datum/subsystem/shuttle/proc/getShuttle(id)
for(var/obj/docking_port/mobile/M in mobile)
@@ -105,6 +188,9 @@ var/datum/subsystem/shuttle/SSshuttle
if(SHUTTLE_DOCKED)
user << "The emergency shuttle is already here."
return
if(SHUTTLE_IGNITING)
user << "The emergency shuttle is firing its engines to leave."
return
if(SHUTTLE_ESCAPE)
user << "The emergency shuttle is moving away to a safe distance."
return
@@ -114,22 +200,24 @@ var/datum/subsystem/shuttle/SSshuttle
call_reason = trim(html_encode(call_reason))
if(length(call_reason) < CALL_SHUTTLE_REASON_LENGTH)
if(length(call_reason) < CALL_SHUTTLE_REASON_LENGTH && seclevel2num(get_security_level()) > SEC_LEVEL_GREEN)
user << "You must provide a reason."
return
var/area/signal_origin = get_area(user)
var/emergency_reason = "\nNature of emergency:\n\n[call_reason]"
if(seclevel2num(get_security_level()) == SEC_LEVEL_RED) // There is a serious threat we gotta move no time to give them five minutes.
emergency.request(null, 0.5, signal_origin, html_decode(emergency_reason), 1)
else
emergency.request(null, 1, signal_origin, html_decode(emergency_reason), 0)
var/security_num = seclevel2num(get_security_level())
switch(security_num)
if(SEC_LEVEL_GREEN)
emergency.request(null, 2, signal_origin, html_decode(emergency_reason), 0)
if(SEC_LEVEL_BLUE)
emergency.request(null, 1, signal_origin, html_decode(emergency_reason), 0)
else
emergency.request(null, 0.5, signal_origin, html_decode(emergency_reason), 1) // There is a serious threat we gotta move no time to give them five minutes.
log_game("[key_name(user)] has called the shuttle.")
message_admins("[key_name_admin(user)] has called the shuttle.")
return
// Called when an emergency shuttle mobile docking port is
// destroyed, which will only happen with admin intervention
/datum/subsystem/shuttle/proc/emergencyDeregister()
@@ -149,19 +237,24 @@ var/datum/subsystem/shuttle/SSshuttle
return
if(ticker.mode.name == "meteor")
return
if(seclevel2num(get_security_level()) == SEC_LEVEL_RED)
if(emergency.timeLeft(1) < emergencyCallTime * 0.25)
return
else
if(emergency.timeLeft(1) < emergencyCallTime * 0.5)
return
var/security_num = seclevel2num(get_security_level())
switch(security_num)
if(SEC_LEVEL_GREEN)
if(emergency.timeLeft(1) < emergencyCallTime)
return
if(SEC_LEVEL_BLUE)
if(emergency.timeLeft(1) < emergencyCallTime * 0.5)
return
else
if(emergency.timeLeft(1) < emergencyCallTime * 0.25)
return
return 1
/datum/subsystem/shuttle/proc/autoEvac()
var/callShuttle = 1
for(var/thing in shuttle_caller_list)
if(istype(thing, /mob/living/silicon/ai))
if(isAI(thing))
var/mob/living/silicon/ai/AI = thing
if(AI.stat || !AI.client)
continue
@@ -181,6 +274,34 @@ var/datum/subsystem/shuttle/SSshuttle
log_game("There is no means of calling the shuttle anymore. Shuttle automatically called.")
message_admins("All the communications consoles were destroyed and all AIs are inactive. Shuttle called.")
/datum/subsystem/shuttle/proc/registerHostileEnvironment(datum/bad)
hostileEnvironments[bad] = TRUE
checkHostileEnvironment()
/datum/subsystem/shuttle/proc/clearHostileEnvironment(datum/bad)
hostileEnvironments -= bad
checkHostileEnvironment()
/datum/subsystem/shuttle/proc/checkHostileEnvironment()
for(var/datum/d in hostileEnvironments)
if(!istype(d) || qdeleted(d))
hostileEnvironments -= d
emergencyNoEscape = hostileEnvironments.len
if(emergencyNoEscape && (emergency.mode == SHUTTLE_IGNITING))
emergency.mode = SHUTTLE_STRANDED
emergency.timer = null
emergency.sound_played = FALSE
priority_announce("Hostile environment detected. \
Departure has been postponed indefinitely pending \
conflict resolution.", null, 'sound/misc/notice1.ogg', "Priority")
if(!emergencyNoEscape && (emergency.mode == SHUTTLE_STRANDED))
emergency.mode = SHUTTLE_DOCKED
emergency.setTimer(emergencyDockTime)
priority_announce("Hostile environment resolved. \
You have 3 minutes to board the Emergency Shuttle.",
null, 'sound/AI/shuttledock.ogg', "Priority")
//try to move/request to dockHome if possible, otherwise dockAway. Mainly used for admin buttons
/datum/subsystem/shuttle/proc/toggleShuttle(shuttleId, dockHome, dockAway, timed)
var/obj/docking_port/mobile/M = getShuttle(shuttleId)
@@ -213,11 +334,149 @@ var/datum/subsystem/shuttle/SSshuttle
return 2
return 0 //dock successful
/datum/subsystem/shuttle/proc/request_transit_dock(obj/docking_port/mobile/M)
if(!istype(M))
throw EXCEPTION("[M] is not a mobile docking port")
if(M.assigned_transit)
return
else
if(!(M in transit_requesters))
transit_requesters += M
/datum/subsystem/shuttle/proc/generate_transit_dock(obj/docking_port/mobile/M)
// First, determine the size of the needed zone
// Because of shuttle rotation, the "width" of the shuttle is not
// always x.
var/travel_dir = M.preferred_direction
// Remember, the direction is the direction we appear to be
// coming from
var/dock_angle = dir2angle(M.preferred_direction) + M.port_angle + 180
var/dock_dir = angle2dir(dock_angle)
var/transit_width = SHUTTLE_TRANSIT_BORDER * 2
var/transit_height = SHUTTLE_TRANSIT_BORDER * 2
// Shuttles travelling on their side have their dimensions swapped
// from our perspective
switch(dock_dir)
if(NORTH, SOUTH)
transit_width += M.width
transit_height += M.height
if(EAST, WEST)
transit_width += M.height
transit_height += M.width
/*
world << "The attempted transit dock will be [transit_width] width, and \
[transit_height] in height. The travel dir is [travel_dir]."
*/
// Then find a place to put the zone
var/list/proposed_zone
base:
for(var/i in transit_turfs)
CHECK_TICK
var/turf/topleft = i
if(!(topleft.flags & UNUSED_TRANSIT_TURF))
continue
var/turf/bottomright = locate(topleft.x + transit_width,
topleft.y + transit_height, topleft.z)
if(!bottomright)
continue
if(!(bottomright.flags & UNUSED_TRANSIT_TURF))
continue
proposed_zone = block(topleft, bottomright)
if(!proposed_zone)
continue
for(var/j in proposed_zone)
var/turf/T = j
if(!T)
continue base
if(!(T.flags & UNUSED_TRANSIT_TURF))
continue base
//world << "[COORD(topleft)] and [COORD(bottomright)]"
break base
if((!proposed_zone) || (!proposed_zone.len))
return FALSE
var/turf/topleft = proposed_zone[1]
//world << "[COORD(topleft)] is TOPLEFT"
// Then create a transit docking port in the middle
var/coords = M.return_coords(0, 0, dock_dir)
//world << json_encode(coords)
/* 0------2
| |
| |
| x |
3------1
*/
var/x0 = coords[1]
var/y0 = coords[2]
var/x1 = coords[3]
var/y1 = coords[4]
// Then we want the point closest to -infinity,-infinity
var/x2 = min(x0, x1)
var/y2 = min(y0, y1)
/*
var/lowx = topleft.x + SHUTTLE_TRANSIT_BORDER
var/lowy = topleft.y + SHUTTLE_TRANSIT_BORDER
var/turf/low_point = locate(lowx, lowy, topleft.z)
new /obj/effect/landmark/stationary(low_point)
world << "Starting at the low point, we go [x2],[y2]"
*/
// Then invert the numbers
var/transit_x = topleft.x + SHUTTLE_TRANSIT_BORDER + abs(x2)
var/transit_y = topleft.y + SHUTTLE_TRANSIT_BORDER + abs(y2)
var/transit_path = /turf/open/space/transit
switch(travel_dir)
if(NORTH)
transit_path = /turf/open/space/transit/north
if(SOUTH)
transit_path = /turf/open/space/transit/south
if(EAST)
transit_path = /turf/open/space/transit/east
if(WEST)
transit_path = /turf/open/space/transit/west
//world << "Docking port at [transit_x], [transit_y], [topleft.z]"
var/turf/midpoint = locate(transit_x, transit_y, topleft.z)
if(!midpoint)
return FALSE
//world << "Making transit dock at [COORD(midpoint)]"
var/area/shuttle/transit/A = new()
A.parallax_movedir = travel_dir
var/obj/docking_port/stationary/transit/new_transit_dock = new(midpoint)
new_transit_dock.assigned_turfs = proposed_zone
new_transit_dock.name = "Transit for [M.id]/[M.name]"
new_transit_dock.turf_type = transit_path
new_transit_dock.owner = M
new_transit_dock.assigned_area = A
// Add 180, because ports point inwards, rather than outwards
new_transit_dock.setDir(angle2dir(dock_angle))
for(var/i in new_transit_dock.assigned_turfs)
var/turf/T = i
T.ChangeTurf(transit_path)
T.flags &= ~(UNUSED_TRANSIT_TURF)
A.contents += T
M.assigned_transit = new_transit_dock
return TRUE
/datum/subsystem/shuttle/proc/initial_move()
for(var/obj/docking_port/mobile/M in mobile)
if(!M.roundstart_move)
continue
moveShuttle(M.id, "[M.roundstart_move]", 0)
M.dockRoundstart()
CHECK_TICK
/datum/subsystem/shuttle/Recover()
@@ -239,6 +498,8 @@ var/datum/subsystem/shuttle/SSshuttle
backup_shuttle = SSshuttle.backup_shuttle
if (istype(SSshuttle.supply))
supply = SSshuttle.supply
if (istype(SSshuttle.transit_turfs))
transit_turfs = SSshuttle.transit_turfs
centcom_message = SSshuttle.centcom_message
ordernum = SSshuttle.ordernum
+3 -2
View File
@@ -2,9 +2,9 @@ var/datum/subsystem/spacedrift/SSspacedrift
/datum/subsystem/spacedrift
name = "Space Drift"
priority = 40
priority = 30
wait = 5
flags = SS_NO_INIT|SS_BACKGROUND
flags = SS_NO_INIT|SS_KEEP_TIMING
var/list/currentrun = list()
var/list/processing = list()
@@ -61,3 +61,4 @@ var/datum/subsystem/spacedrift/SSspacedrift
AM.inertia_last_loc = AM.loc
if (MC_TICK_CHECK)
return
+44
View File
@@ -0,0 +1,44 @@
var/datum/subsystem/squeak/SSsqueak
// The Squeak
// because this is about placement of mice mobs, and nothing to do with
// mice - the computer peripheral
/datum/subsystem/squeak
name = "Squeak"
priority = 40
flags = SS_NO_FIRE
var/list/exposed_wires = list()
/datum/subsystem/squeak/New()
NEW_SS_GLOBAL(SSsqueak)
/datum/subsystem/squeak/Initialize(timeofday)
trigger_migration()
/datum/subsystem/squeak/proc/trigger_migration(num_mice=10)
find_exposed_wires()
var/mob/living/simple_animal/mouse/M
var/turf/proposed_turf
while((num_mice > 0) && exposed_wires.len)
proposed_turf = pick_n_take(exposed_wires)
if(!M)
M = new(proposed_turf)
else
M.forceMove(proposed_turf)
if(M.environment_is_safe())
num_mice -= 1
M = null
/datum/subsystem/squeak/proc/find_exposed_wires()
exposed_wires.Cut()
var/list/all_turfs = block(locate(1,1,1), locate(world.maxx,world.maxy,1))
for(var/turf/open/floor/plating/T in all_turfs)
if(is_blocked_turf(T))
continue
if(locate(/obj/structure/cable) in T)
exposed_wires += T
+37
View File
@@ -0,0 +1,37 @@
var/datum/subsystem/stickyban/SSstickyban
/datum/subsystem/stickyban
name = "Sticky Ban"
init_order = -10
flags = SS_NO_FIRE
var/list/cache = list()
/datum/subsystem/stickyban/New()
NEW_SS_GLOBAL(SSstickyban)
/datum/subsystem/stickyban/Initialize(timeofday)
var/list/bannedkeys = world.GetConfig("ban")
//sanitize the sticky ban list
for (var/bannedkey in bannedkeys)
var/ckey = ckey(bannedkey)
var/list/ban = stickyban2list(world.GetConfig("ban", bannedkey))
//byond stores sticky bans by key, that can end up confusing things
//i also remove it here so that if any stickybans cause a runtime, they just stop existing
world.SetConfig("ban", bannedkey, null)
if (!ban["ckey"])
ban["ckey"] = ckey
//storing these can break things and isn't needed for sticky ban tracking
ban -= "IP"
ban -= "computer_id"
ban["matches_this_round"] = list()
ban["existing_user_matches_this_round"] = list()
ban["admin_matches_this_round"] = list()
cache[ckey] = ban
for (var/bannedckey in cache)
world.SetConfig("ban", bannedckey, list2stickyban(cache[bannedckey]))
+3
View File
@@ -18,6 +18,9 @@ var/datum/subsystem/tgui/SStgui
NEW_SS_GLOBAL(SStgui)
/datum/subsystem/tgui/Shutdown()
close_all_uis()
/datum/subsystem/tgui/stat_entry()
..("P:[processing_uis.len]")
+139
View File
@@ -0,0 +1,139 @@
#define MAX_THROWING_DIST 512 // 2 z-levels on default width
#define MAX_TICKS_TO_MAKE_UP 3 //how many missed ticks will we attempt to make up for this run.
var/datum/subsystem/throwing/SSthrowing
/datum/subsystem/throwing
name = "Throwing"
priority = 25
wait = 1
flags = SS_NO_INIT|SS_KEEP_TIMING|SS_TICKER
var/list/currentrun
var/list/processing
/datum/subsystem/throwing/New()
NEW_SS_GLOBAL(SSthrowing)
processing = list()
/datum/subsystem/throwing/stat_entry()
..("P:[processing.len]")
/datum/subsystem/throwing/fire(resumed = 0)
if (!resumed)
src.currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while(length(currentrun))
var/atom/movable/AM = currentrun[currentrun.len]
var/datum/thrownthing/TT = currentrun[AM]
currentrun.len--
if (!AM || !TT)
processing -= AM
if (MC_TICK_CHECK)
return
continue
TT.tick()
if (MC_TICK_CHECK)
return
currentrun = null
/datum/thrownthing
var/atom/movable/thrownthing
var/atom/target
var/turf/target_turf
var/init_dir
var/maxrange
var/speed
var/mob/thrower
var/diagonals_first
var/dist_travelled = 0
var/start_time
var/dist_x
var/dist_y
var/dx
var/dy
var/pure_diagonal
var/diagonal_error
var/datum/callback/callback
/datum/thrownthing/proc/tick()
var/atom/movable/AM = thrownthing
if (!isturf(AM.loc) || !AM.throwing)
finialize()
return
if (dist_travelled && hitcheck()) //to catch sneaky things moving on our tile while we slept
finialize()
return
var/atom/step
//calculate how many tiles to move, making up for any missed ticks.
var/tilestomove = round(min(((((world.time+world.tick_lag) - start_time) * speed) - (dist_travelled ? dist_travelled : -1)), speed*MAX_TICKS_TO_MAKE_UP) * (world.tick_lag * SSthrowing.wait))
while (tilestomove-- > 0)
if ((dist_travelled >= maxrange || AM.loc == target_turf) && AM.has_gravity(AM.loc))
finialize()
return
if (dist_travelled <= max(dist_x, dist_y)) //if we haven't reached the target yet we home in on it, otherwise we use the initial direction
step = get_step(AM, get_dir(AM, target_turf))
else
step = get_step(AM, init_dir)
if (!pure_diagonal && !diagonals_first) // not a purely diagonal trajectory and we don't want all diagonal moves to be done first
if (diagonal_error >= 0 && max(dist_x,dist_y) - dist_travelled != 1) //we do a step forward unless we're right before the target
step = get_step(AM, dx)
diagonal_error += (diagonal_error < 0) ? dist_x/2 : -dist_y
if (!step) // going off the edge of the map makes get_step return null, don't let things go off the edge
finialize()
return
AM.Move(step, get_dir(AM, step))
if (!AM.throwing) // we hit something during our move
finialize(hit = TRUE)
return
dist_travelled++
if (dist_travelled > MAX_THROWING_DIST)
finialize()
return
/datum/thrownthing/proc/finialize(hit = FALSE)
set waitfor = 0
SSthrowing.processing -= thrownthing
//done throwing, either because it hit something or it finished moving
thrownthing.throwing = 0
if (!hit)
for (var/thing in get_turf(thrownthing)) //looking for our target on the turf we land on.
var/atom/A = thing
if (A == target)
hit = 1
thrownthing.throw_impact(A)
break
if (!hit)
thrownthing.throw_impact(get_turf(thrownthing)) // we haven't hit something yet and we still must, let's hit the ground.
thrownthing.newtonian_move(init_dir)
else
thrownthing.newtonian_move(init_dir)
if (callback)
callback.Invoke()
/datum/thrownthing/proc/hitcheck()
for (var/thing in get_turf(thrownthing))
var/atom/movable/AM = thing
if (AM == thrownthing)
continue
if (AM.density && !(AM.pass_flags & LETPASSTHROW) && !(AM.flags & ON_BORDER))
thrownthing.throwing = 0
thrownthing.throw_impact(AM)
return 1
+214 -77
View File
@@ -11,6 +11,8 @@ var/datum/subsystem/ticker/ticker
var/current_state = GAME_STATE_STARTUP //state of current round (used by process()) Use the defines GAME_STATE_* !
var/force_ending = 0 //Round was ended by admin intervention
// If true, there is no lobby phase, the game starts immediately.
var/start_immediately = FALSE
var/hide_mode = 0
var/datum/game_mode/mode = null
@@ -22,21 +24,19 @@ var/datum/subsystem/ticker/ticker
var/list/datum/mind/minds = list() //The characters in the game. Used for objective tracking.
//These bible variables should be a preference
var/Bible_icon_state //icon_state the chaplain has chosen for his bible
var/Bible_item_state //item_state the chaplain has chosen for his bible
var/Bible_name //name of the bible
var/Bible_deity_name //name of chaplin's deity
var/list/syndicate_coalition = list() //list of traitor-compatible factions
var/list/factions = list() //list of all factions
var/list/availablefactions = list() //list of factions with openings
var/list/scripture_states = list(SCRIPTURE_DRIVER = TRUE, \
SCRIPTURE_SCRIPT = FALSE, \
SCRIPTURE_APPLICATION = FALSE, \
SCRIPTURE_REVENANT = FALSE, \
SCRIPTURE_JUDGEMENT = FALSE) //list of clockcult scripture states for announcements
var/delay_end = 0 //if set true, the round will not restart on it's own
var/triai = 0 //Global holder for Triumvirate
var/tipped = 0 //Did we broadcast the tip of the day yet?
var/modevoted = 0 //Have we sent a vote for the gamemode?
var/selected_tip // What will be the tip of the day?
var/timeLeft = 1200 //pregame timer
@@ -51,11 +51,14 @@ var/datum/subsystem/ticker/ticker
var/maprotatechecked = 0
var/modevoted = 0 //Have we sent a vote for the gamemode?
var/news_report
/datum/subsystem/ticker/New()
NEW_SS_GLOBAL(ticker)
login_music = pickweight(list('sound/ambience/title1.ogg' = 30, 'sound/ambience/title2.ogg' = 30, 'sound/ambience/title3.ogg' = 30, 'sound/ambience/title4.ogg' = 30, 'sound/ambience/title5.ogg' = 30, 'sound/ambience/title6.ogg' = 30, 'sound/ambience/title7.ogg' = 30, 'sound/ambience/clown.ogg' = 3)) // choose title music!
login_music = pickweight(list('sound/ambience/title2.ogg' = 15, 'sound/ambience/title1.ogg' =15, 'sound/ambience/title3.ogg' =14, 'sound/ambience/title4.ogg' =14, 'sound/misc/i_did_not_grief_them.ogg' =14, 'sound/ambience/clown.ogg' = 9)) // choose title music!
if(SSevent.holidays && SSevent.holidays[APRIL_FOOLS])
login_music = 'sound/ambience/clown.ogg'
@@ -64,16 +67,17 @@ var/datum/subsystem/ticker/ticker
syndicate_code_phrase = generate_code_phrase()
if(!syndicate_code_response)
syndicate_code_response = generate_code_phrase()
setupFactions()
..()
/datum/subsystem/ticker/fire()
switch(current_state)
if(GAME_STATE_STARTUP)
timeLeft = config.lobby_countdown * 10
world << "<b><font color='blue'>Welcome to the pre-game lobby!</font></b>"
world << "Please, setup your character and select ready. Game will start in [config.lobby_countdown] seconds"
world << "<span class='boldnotice'>Welcome to [station_name()]!</span>"
world << "Please set up your character and select \"Ready\". The game will start in [config.lobby_countdown] seconds."
current_state = GAME_STATE_PREGAME
for(var/client/C in clients)
window_flash(C) //let them know lobby has opened up.
if(GAME_STATE_PREGAME)
//lobby stats for statpanels
@@ -84,6 +88,9 @@ var/datum/subsystem/ticker/ticker
if(player.ready)
++totalPlayersReady
if(start_immediately)
timeLeft = 0
//countdown
if(timeLeft < 0)
return
@@ -109,16 +116,19 @@ var/datum/subsystem/ticker/ticker
mode.process(wait * 0.1)
check_queue()
check_maprotate()
scripture_states = scripture_unlock_alert(scripture_states)
if(!mode.explosion_in_progress && mode.check_finished() || force_ending)
current_state = GAME_STATE_FINISHED
toggle_ooc(1) // Turn it on
declare_completion(force_ending)
spawn(50)
if(mode.station_was_nuked)
world.Reboot("Station destroyed by Nuclear Device.", "end_proper", "nuke")
else
world.Reboot("Round ended.", "end_proper", "proper completion")
addtimer(CALLBACK(src, .proc/NukeCleanup), 50)
/datum/subsystem/ticker/proc/NukeCleanup()
if(mode.station_was_nuked)
world.Reboot("Station destroyed by Nuclear Device.", "end_proper", "nuke")
else
world.Reboot("Round ended.", "end_proper", "proper completion")
/datum/subsystem/ticker/proc/setup()
//Create and announce mode
@@ -159,19 +169,19 @@ var/datum/subsystem/ticker/ticker
if(!can_continue)
qdel(mode)
mode = null
world << "<B>Error setting up [master_mode]. It's likely that there are no available antagonists for the selected mode.</B> Reverting to pre-game lobby."
world << "<B>Error setting up [master_mode].</B> Reverting to pre-game lobby."
SSjob.ResetOccupations()
return 0
else
world << "<span class='notice'>DEBUG: Bypassing prestart checks..."
message_admins("<span class='notice'>DEBUG: Bypassing prestart checks...</span>")
if(hide_mode)
var/list/modes = new
for (var/datum/game_mode/M in runnable_modes)
modes += M.name
modes = sortList(modes)
world << "<B>The current game mode is - Secret!</B>"
world << "<B>Possibilities:</B> [english_list(modes)]"
world << "<b>The gamemode is: secret!\n\
Possibilities:</B> [english_list(modes)]"
else
mode.announce()
@@ -197,50 +207,56 @@ var/datum/subsystem/ticker/ticker
var/datum/holiday/holiday = SSevent.holidays[holidayname]
world << "<h4>[holiday.greet()]</h4>"
spawn(0)//Forking here so we dont have to wait for this to finish
mode.post_setup()
//Cleanup some stuff
for(var/obj/effect/landmark/start/S in landmarks_list)
//Deleting Startpoints but we need the ai point to AI-ize people later
if(S.name != "AI")
qdel(S)
var/list/adm = get_admin_counts()
if(!adm["present"])
send2irc("Server", "Round just started with no active admins online!")
PostSetup()
return 1
/datum/subsystem/ticker/proc/PostSetup()
set waitfor = 0
mode.post_setup()
//Cleanup some stuff
for(var/obj/effect/landmark/start/S in landmarks_list)
//Deleting Startpoints but we need the ai point to AI-ize people later
if(S.name != "AI")
qdel(S)
/*
var/list/adm = get_admin_counts()
if(!adm["present"])
send2irc("Server", "Round just started with no active admins online!")
*/
/datum/subsystem/ticker/proc/station_explosion_detonation(atom/bomb)
if(bomb) //BOOM
var/turf/epi = bomb.loc
qdel(bomb)
if(epi)
explosion(epi, 0, 256, 512, 0, TRUE, TRUE, 0, TRUE)
//Plus it provides an easy way to make cinematics for other events. Just use this as a template
/datum/subsystem/ticker/proc/station_explosion_cinematic(station_missed=0, override = null)
/datum/subsystem/ticker/proc/station_explosion_cinematic(station_missed=0, override = null, atom/bomb = null)
if( cinematic )
return //already a cinematic in progress!
for (var/datum/html_interface/hi in html_interfaces)
hi.closeAll()
SStgui.close_all_uis()
//Turn off the shuttles, there's no escape now
if(!station_missed && bomb)
SSshuttle.registerHostileEnvironment(src)
SSshuttle.lockdown = TRUE
//initialise our cinematic screen object
cinematic = new /obj/screen{icon='icons/effects/station_explosion.dmi';icon_state="station_intact";layer=21;mouse_opacity=0;screen_loc="1,0";}(src)
var/obj/structure/bed/temp_buckle = new(src)
if(station_missed)
for(var/mob/M in mob_list)
M.buckled = temp_buckle //buckles the mob so it can't do anything
if(M.client)
M.client.screen += cinematic //show every client the cinematic
else //nuke kills everyone on z-level 1 to prevent "hurr-durr I survived"
for(var/mob/M in mob_list)
M.buckled = temp_buckle
if(M.client)
M.client.screen += cinematic
if(M.stat != DEAD)
var/turf/T = get_turf(M)
if(T && T.z==1)
M.death(0) //no mercy
for(var/mob/M in mob_list)
M.notransform = TRUE //stop everything moving
if(M.client)
M.client.screen += cinematic //show every client the cinematic
var/actually_blew_up = TRUE
//Now animate the cinematic
switch(station_missed)
if(1) //nuke was nearby but (mostly) missed
if(NUKE_NEAR_MISS) //nuke was nearby but (mostly) missed
if( mode && !override )
override = mode.name
switch( override )
@@ -248,27 +264,32 @@ var/datum/subsystem/ticker/ticker
flick("intro_nuke",cinematic)
sleep(35)
world << sound('sound/effects/explosionfar.ogg')
station_explosion_detonation(bomb)
flick("station_intact_fade_red",cinematic)
cinematic.icon_state = "summary_nukefail"
if("gang war") //Gang Domination (just show the override screen)
cinematic.icon_state = "intro_malf_still"
flick("intro_malf",cinematic)
actually_blew_up = FALSE
sleep(70)
if("fake") //The round isn't over, we're just freaking people out for fun
flick("intro_nuke",cinematic)
sleep(35)
world << sound('sound/items/bikehorn.ogg')
flick("summary_selfdes",cinematic)
actually_blew_up = FALSE
else
flick("intro_nuke",cinematic)
sleep(35)
world << sound('sound/effects/explosionfar.ogg')
//flick("end",cinematic)
station_explosion_detonation(bomb)
if(2) //nuke was nowhere nearby //TODO: a really distant explosion animation
if(NUKE_MISS_STATION || NUKE_SYNDICATE_BASE) //nuke was nowhere nearby //TODO: a really distant explosion animation
sleep(50)
world << sound('sound/effects/explosionfar.ogg')
station_explosion_detonation(bomb)
actually_blew_up = station_missed == NUKE_SYNDICATE_BASE //don't kill everyone on station if it detonated off station
else //station was destroyed
if( mode && !override )
override = mode.name
@@ -278,47 +299,61 @@ var/datum/subsystem/ticker/ticker
sleep(35)
flick("station_explode_fade_red",cinematic)
world << sound('sound/effects/explosionfar.ogg')
station_explosion_detonation(bomb)
cinematic.icon_state = "summary_nukewin"
if("AI malfunction") //Malf (screen,explosion,summary)
flick("intro_malf",cinematic)
sleep(76)
flick("station_explode_fade_red",cinematic)
world << sound('sound/effects/explosionfar.ogg')
station_explosion_detonation(bomb) //TODO: If we ever decide to actually detonate the vault bomb
cinematic.icon_state = "summary_malf"
if("blob") //Station nuked (nuke,explosion,summary)
flick("intro_nuke",cinematic)
sleep(35)
flick("station_explode_fade_red",cinematic)
world << sound('sound/effects/explosionfar.ogg')
station_explosion_detonation(bomb) //TODO: no idea what this case could be
cinematic.icon_state = "summary_selfdes"
if("no_core") //Nuke failed to detonate as it had no core
flick("intro_nuke",cinematic)
sleep(35)
flick("station_intact",cinematic)
world << sound('sound/ambience/signal.ogg')
sleep(100)
if(cinematic)
qdel(cinematic)
cinematic = null
if(temp_buckle)
qdel(temp_buckle)
addtimer(CALLBACK(src, .proc/finish_cinematic, null, FALSE), 100)
return //Faster exit, since nothing happened
else //Station nuked (nuke,explosion,summary)
flick("intro_nuke",cinematic)
sleep(35)
flick("station_explode_fade_red", cinematic)
world << sound('sound/effects/explosionfar.ogg')
station_explosion_detonation(bomb)
cinematic.icon_state = "summary_selfdes"
//If its actually the end of the round, wait for it to end.
//Otherwise if its a verb it will continue on afterwards.
spawn(300)
if(cinematic)
qdel(cinematic) //end the cinematic
if(temp_buckle)
qdel(temp_buckle) //release everybody
return
var/bombloc = null
if(actually_blew_up)
if(bomb && bomb.loc)
bombloc = bomb.z
else if(!station_missed)
bombloc = ZLEVEL_STATION
if(mode)
mode.explosion_in_progress = 0
world << "<B>The station was destoyed by the nuclear blast!</B>"
mode.station_was_nuked = (station_missed<2) //station_missed==1 is a draw. the station becomes irradiated and needs to be evacuated.
addtimer(CALLBACK(src, .proc/finish_cinematic, bombloc, actually_blew_up), 300)
/datum/subsystem/ticker/proc/finish_cinematic(killz, actually_blew_up)
if(cinematic)
qdel(cinematic) //end the cinematic
cinematic = null
for(var/mob/M in mob_list)
M.notransform = FALSE
if(actually_blew_up && !isnull(killz) && M.stat != DEAD && M.z == killz)
M.gib()
/datum/subsystem/ticker/proc/create_characters()
for(var/mob/new_player/player in player_list)
@@ -350,7 +385,7 @@ var/datum/subsystem/ticker/ticker
SSjob.EquipRank(player, player.mind.assigned_role, 0)
if(captainless)
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player))
if(!isnewplayer(M))
M << "Captainship not forced on anyone."
@@ -359,6 +394,7 @@ var/datum/subsystem/ticker/ticker
var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED
var/num_survivors = 0
var/num_escapees = 0
var/num_shuttle_escapees = 0
world << "<BR><BR><BR><FONT size=3><B>The round has ended.</B></FONT>"
@@ -368,11 +404,16 @@ var/datum/subsystem/ticker/ticker
if(Player.stat != DEAD && !isbrain(Player))
num_survivors++
if(station_evacuated) //If the shuttle has already left the station
var/area/shuttle_area
if(SSshuttle && SSshuttle.emergency)
shuttle_area = SSshuttle.emergency.areaInstance
if(!Player.onCentcom() && !Player.onSyndieBase())
Player << "<font color='blue'><b>You managed to survive, but were marooned on [station_name()]...</b></FONT>"
else
num_escapees++
Player << "<font color='green'><b>You managed to survive the events on [station_name()] as [Player.real_name].</b></FONT>"
if(get_area(Player) == shuttle_area)
num_shuttle_escapees++
else
Player << "<font color='green'><b>You managed to survive the events on [station_name()] as [Player.real_name].</b></FONT>"
else
@@ -381,15 +422,22 @@ var/datum/subsystem/ticker/ticker
//Round statistics report
var/datum/station_state/end_state = new /datum/station_state()
end_state.count()
var/station_integrity = min(round( 100 * start_state.score(end_state), 0.1), 100)
var/station_integrity = min(PERCENT(start_state.score(end_state)), 100)
world << "<BR>[TAB]Shift Duration: <B>[round(world.time / 36000)]:[add_zero("[world.time / 600 % 60]", 2)]:[world.time / 100 % 6][world.time / 100 % 10]</B>"
world << "<BR>[TAB]Station Integrity: <B>[mode.station_was_nuked ? "<font color='red'>Destroyed</font>" : "[station_integrity]%"]</B>"
if(mode.station_was_nuked)
ticker.news_report = STATION_DESTROYED_NUKE
var/total_players = joined_player_list.len
if(joined_player_list.len)
world << "<BR>[TAB]Total Population: <B>[joined_player_list.len]</B>"
world << "<BR>[TAB]Total Population: <B>[total_players]</B>"
if(station_evacuated)
world << "<BR>[TAB]Evacuation Rate: <B>[num_escapees] ([round((num_escapees/joined_player_list.len)*100, 0.1)]%)</B>"
world << "<BR>[TAB]Survival Rate: <B>[num_survivors] ([round((num_survivors/joined_player_list.len)*100, 0.1)]%)</B>"
world << "<BR>[TAB]Evacuation Rate: <B>[num_escapees] ([PERCENT(num_escapees/total_players)]%)</B>"
world << "<BR>[TAB](on emergency shuttle): <B>[num_shuttle_escapees] ([PERCENT(num_shuttle_escapees/total_players)]%)</B>"
news_report = STATION_EVACUATED
if(SSshuttle.emergency.is_hijacked())
news_report = SHUTTLE_HIJACK
world << "<BR>[TAB]Survival Rate: <B>[num_survivors] ([PERCENT(num_survivors/total_players)]%)</B>"
world << "<BR>"
//Silicon laws report
@@ -426,6 +474,9 @@ var/datum/subsystem/ticker/ticker
if (findtext("[handler]","auto_declare_completion_"))
call(mode, handler)(force_ending)
if(cross_allowed)
send_news_report()
//Print a list of antagonists to the server log
var/list/total_antagonists = list()
//Look into all mobs in world, dead or alive
@@ -443,6 +494,43 @@ var/datum/subsystem/ticker/ticker
for(var/i in total_antagonists)
log_game("[i]s[total_antagonists[i]].")
//Borers
var/borerwin = FALSE
if(borers.len)
var/borertext = "<br><font size=3><b>The borers were:</b></font>"
for(var/mob/living/simple_animal/borer/B in borers)
if((B.key || B.controlling) && B.stat != DEAD)
borertext += "<br>[B.controlling ? B.victim.key : B.key] was [B.truename] ("
var/turf/location = get_turf(B)
if(location.z == ZLEVEL_CENTCOM && B.victim)
borertext += "escaped with host"
else
borertext += "failed"
borertext += ")"
world << borertext
var/total_borers = 0
for(var/mob/living/simple_animal/borer/B in borers)
if((B.key || B.victim) && B.stat != DEAD)
total_borers++
if(total_borers)
var/total_borer_hosts = 0
for(var/mob/living/carbon/C in mob_list)
var/mob/living/simple_animal/borer/D = C.has_brain_worms()
var/turf/location = get_turf(C)
if(location.z == ZLEVEL_CENTCOM && D && D.stat != DEAD)
total_borer_hosts++
if(total_borer_hosts_needed <= total_borer_hosts)
borerwin = TRUE
world << "<b>There were [total_borers] borers alive at round end!</b>"
world << "<b>A total of [total_borer_hosts] borers with hosts escaped on the shuttle alive. The borers needed [total_borer_hosts_needed] hosts to escape.</b>"
if(borerwin)
world << "<b><font color='green'>The borers were successful!</font></b>"
else
world << "<b><font color='red'>The borers have failed!</font></b>"
mode.declare_station_goal_completion()
//Adds the del() log to world.log in a format condensable by the runtime condenser found in tools
if(SSgarbage.didntgc.len)
var/dellog = ""
@@ -451,6 +539,8 @@ var/datum/subsystem/ticker/ticker
dellog += "Failures : [SSgarbage.didntgc[path]] \n"
world.log << dellog
//Collects persistence features
SSpersistence.CollectData()
return 1
/datum/subsystem/ticker/proc/send_tip_of_the_round()
@@ -504,9 +594,10 @@ var/datum/subsystem/ticker/ticker
//map rotate chance defaults to 75% of the length of the round (in minutes)
if (!prob((world.time/600)*config.maprotatechancedelta))
return
spawn(0) //compiling a map can lock up the mc for 30 to 60 seconds if we don't spawn
maprotate()
INVOKE_ASYNC(GLOBAL_PROC, /.proc/maprotate)
/datum/subsystem/ticker/proc/send_gamemode_vote(var/)
SSvote.initiate_vote("roundtype","server")
/world/proc/has_round_started()
if (ticker && ticker.current_state >= GAME_STATE_PLAYING)
@@ -526,11 +617,6 @@ var/datum/subsystem/ticker/ticker
minds = ticker.minds
Bible_icon_state = ticker.Bible_icon_state
Bible_item_state = ticker.Bible_item_state
Bible_name = ticker.Bible_name
Bible_deity_name = ticker.Bible_deity_name
syndicate_coalition = ticker.syndicate_coalition
factions = ticker.factions
availablefactions = ticker.availablefactions
@@ -551,5 +637,56 @@ var/datum/subsystem/ticker/ticker
cinematic = ticker.cinematic
maprotatechecked = ticker.maprotatechecked
/datum/subsystem/ticker/proc/send_gamemode_vote(var/)
SSvote.initiate_vote("roundtype","server")
modevoted = ticker.modevoted
/datum/subsystem/ticker/proc/send_news_report()
var/news_message
var/news_source = "Nanotrasen News Network"
switch(news_report)
if(NUKE_SYNDICATE_BASE)
news_message = "In a daring raid, the heroic crew of [station_name()] detonated a nuclear device in the heart of a terrorist base."
if(STATION_DESTROYED_NUKE)
news_message = "We would like to reassure all employees that the reports of a Syndicate backed nuclear attack on [station_name()] are, in fact, a hoax. Have a secure day!"
if(STATION_EVACUATED)
news_message = "The crew of [station_name()] has been evacuated amid unconfirmed reports of enemy activity."
if(GANG_LOSS)
news_message = "Organized crime aboard [station_name()] has been stamped out by members of our ever vigilant security team. Remember to thank your assigned officers today!"
if(GANG_TAKEOVER)
news_message = "Contact with [station_name()] has been lost after a sophisticated hacking attack by organized criminal elements. Stay vigilant!"
if(BLOB_WIN)
news_message = "[station_name()] was overcome by an unknown biological outbreak, killing all crew on board. Don't let it happen to you! Remember, a clean work station is a safe work station."
if(BLOB_NUKE)
news_message = "[station_name()] is currently undergoing decontanimation after a controlled burst of radiation was used to remove a biological ooze. All employees were safely evacuated prior, and are enjoying a relaxing vacation."
if(BLOB_DESTROYED)
news_message = "[station_name()] is currently undergoing decontamination procedures after the destruction of a biological hazard. As a reminder, any crew members experiencing cramps or bloating should report immediately to security for incineration."
if(CULT_ESCAPE)
news_message = "Security Alert: A group of religious fanatics have escaped from [station_name()]."
if(CULT_FAILURE)
news_message = "Following the dismantling of a restricted cult aboard [station_name()], we would like to remind all employees that worship outside of the Chapel is strictly prohibited, and cause for termination."
if(CULT_SUMMON)
news_message = "Company officials would like to clarify that [station_name()] was scheduled to be decommissioned following meteor damage earlier this year. Earlier reports of an unknowable eldritch horror were made in error."
if(NUKE_MISS)
news_message = "The Syndicate have bungled a terrorist attack [station_name()], detonating a nuclear weapon in empty space near by."
if(OPERATIVES_KILLED)
news_message = "Repairs to [station_name()] are underway after an elite Syndicate death squad was wiped out by the crew."
if(OPERATIVE_SKIRMISH)
news_message = "A skirmish between security forces and Syndicate agents aboard [station_name()] ended with both sides bloodied but intact."
if(REVS_WIN)
news_message = "Company officials have reassured investors that despite a union led revolt aboard [station_name()] that there will be no wage increases for workers."
if(REVS_LOSE)
news_message = "[station_name()] quickly put down a misguided attempt at mutiny. Remember, unionizing is illegal!"
if(WIZARD_KILLED)
news_message = "Tensions have flared with the Wizard's Federation following the death of one of their members aboard [station_name()]."
if(STATION_NUKED)
news_message = "[station_name()] activated its self destruct device for unknown reasons. Attempts to clone the Captain so he can be arrested and executed are under way."
if(CLOCK_SUMMON)
news_message = "The garbled messages about hailing a mouse and strange energy readings from [station_name()] have been discovered to be an ill-advised, if thorough, prank by a clown."
if(CLOCK_SILICONS)
news_message = "The project started by [station_name()] to upgrade their silicon units with advanced equipment have been largely successful, though they have thus far refused to release schematics in a violation of company policy."
if(CLOCK_PROSELYTIZATION)
news_message = "The burst of energy released near [station_name()] has been confirmed as merely a test of a new weapon. However, due to an unexpected mechanical error, their communications system has been knocked offline."
if(SHUTTLE_HIJACK)
news_message = "During routine evacuation procedures, the emergency shuttle of [station_name()] had its navigation protocols corrupted and went off course, but was recovered shortly after."
if(news_message)
send2irc(news_source, news_message,"News_Report")
+297 -58
View File
@@ -1,102 +1,341 @@
#define BUCKET_LEN (world.fps*1*60) //how many ticks should we keep in the bucket. (1 minutes worth)
#define BUCKET_POS(timer) (round((timer.timeToRun - SStimer.head_offset) / world.tick_lag) + 1)
var/datum/subsystem/timer/SStimer
/datum/subsystem/timer
name = "Timer"
wait = 2 //SS_TICKER subsystem, so wait is in ticks
wait = 1 //SS_TICKER subsystem, so wait is in ticks
init_order = 1
display_order = 3
can_fire = 0 //start disabled
flags = SS_FIRE_IN_LOBBY|SS_TICKER|SS_POST_FIRE_TIMING|SS_NO_INIT
flags = SS_FIRE_IN_LOBBY|SS_TICKER|SS_NO_INIT
var/list/datum/timedevent/processing
var/list/hashes
var/head_offset = 0 //world.time of the first entry in the the bucket.
var/practical_offset = 0 //index of the first non-empty item in the bucket.
var/bucket_resolution = 0 //world.tick_lag the bucket was designed for
var/bucket_count = 0 //how many timers are in the buckets
var/list/bucket_list //list of buckets, each bucket holds every timer that has to run that byond tick.
var/list/timer_id_dict //list of all active timers assoicated to their timer id (for easy lookup)
var/list/clienttime_timers //special snowflake timers that run on fancy pansy "client time"
/datum/subsystem/timer/New()
processing = list()
hashes = list()
bucket_list = list()
timer_id_dict = list()
clienttime_timers = list()
NEW_SS_GLOBAL(SStimer)
/datum/subsystem/timer/stat_entry(msg)
..("P:[processing.len]")
..("B:[bucket_count] P:[length(processing)] H:[length(hashes)] C:[length(clienttime_timers)]")
/datum/subsystem/timer/fire()
if(!processing.len)
can_fire = 0 //nothing to do, lets stop firing.
return
for(var/datum/timedevent/event in processing)
if(!event.thingToCall || qdeleted(event.thingToCall))
qdel(event)
if(event.timeToRun <= world.time)
runevent(event)
qdel(event)
/datum/subsystem/timer/fire(resumed = FALSE)
if (length(clienttime_timers))
for (var/thing in clienttime_timers)
var/datum/timedevent/ctime_timer = thing
if (ctime_timer.spent)
qdel(ctime_timer)
continue
if (ctime_timer.timeToRun <= REALTIMEOFDAY)
var/datum/callback/callBack = ctime_timer.callBack
ctime_timer.spent = TRUE
callBack.InvokeAsync()
qdel(ctime_timer)
if (MC_TICK_CHECK)
return
var/static/list/spent = list()
var/static/datum/timedevent/timer
var/static/datum/timedevent/head
if (practical_offset > BUCKET_LEN || (!resumed && length(src.bucket_list) != BUCKET_LEN || world.tick_lag != bucket_resolution))
shift_buckets()
resumed = FALSE
if (!resumed)
timer = null
head = null
var/list/bucket_list = src.bucket_list
while (practical_offset <= BUCKET_LEN && head_offset + (practical_offset*world.tick_lag) <= world.time && !MC_TICK_CHECK)
if (!timer || !head || timer == head)
head = bucket_list[practical_offset]
if (!head)
practical_offset++
if (MC_TICK_CHECK)
break
continue
timer = head
do
var/datum/callback/callBack = timer.callBack
if (!callBack)
qdel(timer)
bucket_resolution = null //force bucket recreation
CRASH("Invalid timer: timer.timeToRun=[timer.timeToRun]||qdeleted(timer)=[qdeleted(timer)]||world.time=[world.time]||head_offset=[head_offset]||practical_offset=[practical_offset]||timer.spent=[timer.spent]")
if (!timer.spent)
spent += timer
timer.spent = TRUE
callBack.InvokeAsync()
timer = timer.next
if (MC_TICK_CHECK)
return
while (timer && timer != head)
timer = null
bucket_list[practical_offset++] = null
if (MC_TICK_CHECK)
return
/datum/subsystem/timer/proc/runevent(datum/timedevent/event)
set waitfor = 0
if(event.thingToCall == GLOBAL_PROC && istext(event.procToCall))
call("/proc/[event.procToCall]")(arglist(event.argList))
else
call(event.thingToCall, event.procToCall)(arglist(event.argList))
bucket_count -= length(spent)
for (var/spent_timer in spent)
qdel(spent_timer)
spent.len = 0
/datum/subsystem/timer/proc/shift_buckets()
var/list/bucket_list = src.bucket_list
var/list/alltimers = list()
//collect the timers currently in the bucket
for (var/bucket_head in bucket_list)
if (!bucket_head)
continue
var/datum/timedevent/bucket_node = bucket_head
do
alltimers += bucket_node
bucket_node = bucket_node.next
while(bucket_node && bucket_node != bucket_head)
bucket_list.len = 0
bucket_list.len = BUCKET_LEN
practical_offset = 1
bucket_count = 0
head_offset = world.time
bucket_resolution = world.tick_lag
alltimers += processing
if (!length(alltimers))
return
sortTim(alltimers, .proc/cmp_timer)
var/datum/timedevent/head = alltimers[1]
if (head.timeToRun < head_offset)
head_offset = head.timeToRun
var/list/timers_to_remove = list()
for (var/thing in alltimers)
var/datum/timedevent/timer = thing
if (!timer)
timers_to_remove += timer
continue
var/bucket_pos = BUCKET_POS(timer)
if (bucket_pos > BUCKET_LEN)
break
timers_to_remove += timer //remove it from the big list once we are done
if (!timer.callBack || timer.spent)
continue
bucket_count++
var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
if (!bucket_head)
bucket_list[bucket_pos] = timer
timer.next = null
timer.prev = null
continue
if (!bucket_head.prev)
bucket_head.prev = bucket_head
timer.next = bucket_head
timer.prev = bucket_head.prev
timer.next.prev = timer
timer.prev.next = timer
processing = (alltimers - timers_to_remove)
/datum/subsystem/timer/Recover()
processing |= SStimer.processing
hashes |= SStimer.hashes
timer_id_dict |= SStimer.timer_id_dict
bucket_list |= SStimer.bucket_list
/datum/var/list/active_timers
/datum/timedevent
var/thingToCall
var/procToCall
var/timeToRun
var/argList
var/id
var/datum/callback/callBack
var/timeToRun
var/hash
var/list/flags
var/spent = FALSE //set to true right before running.
//cicular doublely linked list
var/datum/timedevent/next
var/datum/timedevent/prev
var/static/nextid = 1
/datum/timedevent/New()
/datum/timedevent/New(datum/callback/callBack, timeToRun, flags, hash)
id = nextid++
src.callBack = callBack
src.timeToRun = timeToRun
src.flags = flags
src.hash = hash
if (flags & TIMER_UNIQUE)
SStimer.hashes[hash] = src
if (flags & TIMER_STOPPABLE)
SStimer.timer_id_dict["timerid[id]"] = src
if (callBack.object != GLOBAL_PROC)
LAZYINITLIST(callBack.object.active_timers)
callBack.object.active_timers += src
if (flags & TIMER_CLIENT_TIME)
SStimer.clienttime_timers += src
return
//get the list of buckets
var/list/bucket_list = SStimer.bucket_list
//calculate our place in the bucket list
var/bucket_pos = BUCKET_POS(src)
//we are too far aways from needing to run to be in the bucket list, shift_buckets() will handle us.
if (bucket_pos > length(bucket_list))
SStimer.processing += src
return
//get the bucket for our tick
var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
SStimer.bucket_count++
//empty bucket, we will just add ourselves
if (!bucket_head)
bucket_list[bucket_pos] = src
if (bucket_pos < SStimer.practical_offset)
SStimer.practical_offset = bucket_pos
return
//other wise, lets do a simplified linked list add.
if (!bucket_head.prev)
bucket_head.prev = bucket_head
next = bucket_head
prev = bucket_head.prev
next.prev = src
prev.next = src
/datum/timedevent/Destroy()
SStimer.processing -= src
SStimer.hashes -= hash
..()
if (flags & TIMER_UNIQUE)
SStimer.hashes -= hash
if (callBack && callBack.object && callBack.object != GLOBAL_PROC && callBack.object.active_timers)
callBack.object.active_timers -= src
UNSETEMPTY(callBack.object.active_timers)
callBack = null
if (flags & TIMER_STOPPABLE)
SStimer.timer_id_dict -= "timerid[id]"
if (flags & TIMER_CLIENT_TIME)
SStimer.clienttime_timers -= src
return QDEL_HINT_IWILLGC
if (!spent)
if (prev == next && next)
next.prev = null
prev.next = null
else
if (prev)
prev.next = next
if (next)
next.prev = prev
var/bucketpos = BUCKET_POS(src)
var/datum/timedevent/buckethead
var/list/bucket_list = SStimer.bucket_list
if (bucketpos > 0 && bucketpos <= length(bucket_list))
buckethead = bucket_list[bucketpos]
SStimer.bucket_count--
else
SStimer.processing -= src
if (buckethead == src)
bucket_list[bucketpos] = next
else
if (prev && prev.next == src)
prev.next = next
if (next && next.prev == src)
next.prev = prev
next = null
prev = null
return QDEL_HINT_IWILLGC
/proc/addtimer(thingToCall, procToCall, wait, unique = FALSE, ...)
if (!thingToCall || !procToCall)
proc/addtimer(datum/callback/callback, wait, flags)
if (!callback)
return
if (!SStimer.can_fire)
SStimer.can_fire = 1
var/datum/timedevent/event = new()
event.thingToCall = thingToCall
event.procToCall = procToCall
event.timeToRun = world.time + wait
var/hashlist = args.Copy()
hashlist[1] = "[thingToCall](\ref[thingToCall])"
event.hash = jointext(args, null)
if(args.len > 4)
event.argList = args.Copy(5)
// Check for dupes if unique = 1.
if(unique)
var/datum/timedevent/hash_event = SStimer.hashes[event.hash]
if(hash_event)
return hash_event.id
SStimer.hashes[event.hash] = event
if (wait <= 0)
SStimer.runevent(event)
SStimer.hashes -= event.hash
callback.InvokeAsync()
return
// If we are unique (or we're not checking that), add the timer and return the id.
SStimer.processing += event
return event.id
var/hash
if (flags & TIMER_UNIQUE)
var/list/hashlist = list(callback.object, "(\ref[callback.object])", callback.delegate, wait, flags & TIMER_CLIENT_TIME)
hashlist += callback.arguments
hash = hashlist.Join("|||||||")
var/datum/timedevent/hash_timer = SStimer.hashes[hash]
if(hash_timer)
if (flags & TIMER_OVERRIDE)
qdel(hash_timer)
else
if (hash_timer.flags & TIMER_STOPPABLE)
. = hash_timer.id
return
var/timeToRun = world.time + wait
if (flags & TIMER_CLIENT_TIME)
timeToRun = REALTIMEOFDAY + wait
var/datum/timedevent/timer = new(callback, timeToRun, flags, hash)
if (flags & TIMER_STOPPABLE)
return timer.id
/proc/deltimer(id)
for(var/datum/timedevent/event in SStimer.processing)
if(event.id == id)
qdel(event)
return 1
return 0
if (!id)
return FALSE
if (!istext(id))
if (istype(id, /datum/timedevent))
qdel(id)
return TRUE
var/datum/timedevent/timer = SStimer.timer_id_dict["timerid[id]"]
if (timer && !timer.spent)
qdel(timer)
return TRUE
return FALSE
#undef BUCKET_LEN
#undef BUCKET_POS
+11 -4
View File
@@ -58,15 +58,20 @@ var/datum/subsystem/vote/SSvote
greatest_votes = votes
//default-vote for everyone who didn't vote
if(!config.vote_no_default && choices.len)
var/non_voters = (clients.len - total_votes)
if(non_voters > 0)
var/list/non_voters = directory.Copy()
non_voters -= voted
for (var/non_voter_ckey in non_voters)
var/client/C = non_voters[non_voter_ckey]
if (!C || C.is_afk())
non_voters -= non_voter_ckey
if(non_voters.len > 0)
if(mode == "restart")
choices["Continue Playing"] += non_voters
choices["Continue Playing"] += non_voters.len
if(choices["Continue Playing"] >= greatest_votes)
greatest_votes = choices["Continue Playing"]
else if(mode == "gamemode")
if(master_mode in choices)
choices[master_mode] += non_voters
choices[master_mode] += non_voters.len
if(choices[master_mode] >= greatest_votes)
greatest_votes = choices[master_mode]
//get all options with that many votes and return them in a list
@@ -121,6 +126,7 @@ var/datum/subsystem/vote/SSvote
restart = 1
else
master_mode = .
if("roundtype")
if(ticker && ticker.mode)
message_admins("A vote has tried to change the gamemode, but the game has already started. Aborting.")
@@ -128,6 +134,7 @@ var/datum/subsystem/vote/SSvote
world.save_mode(.)
master_mode = .
world << "<span class='adminnotice'><b>The mode is now: [master_mode]</b></span>"
if(restart)
var/active_admins = 0
for(var/client/C in admins)
+2 -2
View File
@@ -29,13 +29,13 @@ var/datum/subsystem/weather/SSweather
var/datum/weather/W = pickweight(possible_weather_for_this_z)
run_weather(W.name, Z)
eligible_zlevels -= Z
addtimer(src, "make_z_eligible", rand(3000, 6000) + W.weather_duration_upper, TRUE, Z) //Around 5-10 minutes between weathers
addtimer(CALLBACK(src, .proc/make_z_eligible, Z), rand(3000, 6000) + W.weather_duration_upper, TIMER_UNIQUE) //Around 5-10 minutes between weathers
/datum/subsystem/weather/Initialize(start_timeofday)
..()
for(var/V in subtypesof(/datum/weather))
var/datum/weather/W = V
existing_weather |= new W
new W //weather->New will handle adding itself to the list
/datum/subsystem/weather/proc/run_weather(weather_name, Z)
if(!weather_name)