@@ -1,175 +1,175 @@
|
||||
## Citadel Station 13
|
||||
Based and maintained from /tg/station.
|
||||
|
||||
[](https://travis-ci.org/Citadel-Station-13/Citadel-Station-13)
|
||||
[](http://isitmaintained.com/project/Citadel-Station-13/Citadel-Station-13 "Percentage of issues still open")
|
||||
[](http://isitmaintained.com/project/Citadel-Station-13/Citadel-Station-13 "Average time to resolve an issue")
|
||||
|
||||
[](https://forthebadge.com) [](https://forthebadge.com) [](http://forthebadge.com) [](https://www.reddit.com/r/SS13/comments/5oplxp/what_is_the_main_problem_with_byond_as_an_engine/dclbu1a)
|
||||
|
||||
**Upstream Information**
|
||||
* **Website:** <https://www.tgstation13.org>
|
||||
* **Code:** <https://github.com/tgstation/tgstation>
|
||||
* **Wiki:** <https://tgstation13.org/wiki/Main_Page>
|
||||
* **Codedocs:** <https://codedocs.tgstation13.org>
|
||||
* **/tg/station Discord:** <https://tgstation13.org/phpBB/viewforum.php?f=60>
|
||||
* **Coderbus Discord:** <https://discord.gg/Vh8TJp9>
|
||||
* ~~**IRC:** <irc://irc.rizon.net/coderbus>~~ (dead)
|
||||
|
||||
**Citadel Station Information**
|
||||
* **Website:** <http://citadel-station.net>
|
||||
* **Code:** <https://github.com/Citadel-Station-13/Citadel-Station-13>
|
||||
* **Wiki:** <https://citadel-station.net/wiki/index.php?title=Main_Page>
|
||||
* **Forums:** <http://citadel-station.net/forum>
|
||||
* **Ban Appeals:** <http://citadel-station.net/forum/forumdisplay.php?fid=8>
|
||||
* **Discord:** <https://discord.gg/E6SQuhz>
|
||||
|
||||
## DOWNLOADING
|
||||
|
||||
There are a number of ways to download the source code. Some are described here, an alternative all-inclusive guide is also located at http://www.tgstation13.org/wiki/Downloading_the_source_code
|
||||
|
||||
Option 1:
|
||||
Follow this: http://www.tgstation13.org/wiki/Setting_up_git
|
||||
|
||||
Option 2: Download the source code as a zip by clicking the ZIP button in the
|
||||
code tab of https://github.com/tgstation/tgstation
|
||||
(note: this will use a lot of bandwidth if you wish to update and is a lot of
|
||||
hassle if you want to make any changes at all, so it's not recommended.)
|
||||
|
||||
Option 3: Download a pre-compiled nightly at https://tgstation13.download/nightlies/ (same caveats as option 2)
|
||||
|
||||
## INSTALLATION
|
||||
|
||||
First-time installation should be fairly straightforward. First, you'll need
|
||||
BYOND installed. You can get it from https://www.byond.com/download. Once you've done
|
||||
that, extract the game files to wherever you want to keep them. This is a
|
||||
sourcecode-only release, so the next step is to compile the server files.
|
||||
Open tgstation.dme by double-clicking it, open the Build menu, and click
|
||||
compile. This'll take a little while, and if everything's done right you'll get
|
||||
a message like this:
|
||||
|
||||
```
|
||||
saving tgstation.dmb (DEBUG mode)
|
||||
tgstation.dmb - 0 errors, 0 warnings
|
||||
```
|
||||
|
||||
If you see any errors or warnings, something has gone wrong - possibly a corrupt
|
||||
download or the files extracted wrong. If problems persist, ask for assistance
|
||||
in irc://irc.rizon.net/coderbus
|
||||
|
||||
Once that's done, open up the config folder. You'll want to edit config.txt to
|
||||
set the probabilities for different gamemodes in Secret and to set your server
|
||||
location so that all your players don't get disconnected at the end of each
|
||||
round. It's recommended you don't turn on the gamemodes with probability 0,
|
||||
except Extended, as they have various issues and aren't currently being tested,
|
||||
so they may have unknown and bizarre bugs. Extended is essentially no mode, and
|
||||
isn't in the Secret rotation by default as it's just not very fun.
|
||||
|
||||
You'll also want to edit config/admins.txt to remove the default admins and add
|
||||
your own. "Game Master" is the highest level of access, and probably the one
|
||||
you'll want to use for now. You can set up your own ranks and find out more in
|
||||
config/admin_ranks.txt
|
||||
|
||||
The format is
|
||||
|
||||
```
|
||||
byondkey = Rank
|
||||
```
|
||||
|
||||
where the admin rank must be properly capitalised.
|
||||
|
||||
This codebase also depends on a native library called rust-g. A precompiled
|
||||
Windows DLL is included in this repository, but Linux users will need to build
|
||||
and install it themselves. Directions can be found at the [rust-g
|
||||
repo](https://github.com/tgstation13/rust-g).
|
||||
|
||||
Finally, to start the server, run Dream Daemon and enter the path to your
|
||||
compiled tgstation.dmb file. Make sure to set the port to the one you
|
||||
specified in the config.txt, and set the Security box to 'Safe'. Then press GO
|
||||
and the server should start up and be ready to join. It is also recommended that
|
||||
you set up the SQL backend (see below).
|
||||
|
||||
## UPDATING
|
||||
|
||||
To update an existing installation, first back up your /config and /data folders
|
||||
as these store your server configuration, player preferences and banlist.
|
||||
|
||||
Then, extract the new files (preferably into a clean directory, but updating in
|
||||
place should work fine), copy your /config and /data folders back into the new
|
||||
install, overwriting when prompted except if we've specified otherwise, and
|
||||
recompile the game. Once you start the server up again, you should be running
|
||||
the new version.
|
||||
|
||||
## HOSTING
|
||||
|
||||
If you'd like a more robust server hosting option for tgstation and its
|
||||
derivatives. Check out our server tools suite at
|
||||
https://github.com/tgstation/tgstation-server
|
||||
|
||||
## MAPS
|
||||
|
||||
/tg/station currently comes equipped with five maps.
|
||||
|
||||
* [BoxStation (default)](http://tgstation13.org/wiki/Boxstation)
|
||||
* [MetaStation](https://tgstation13.org/wiki/MetaStation)
|
||||
* [DeltaStation](https://tgstation13.org/wiki/DeltaStation)
|
||||
* [OmegaStation](https://tgstation13.org/wiki/OmegaStation)
|
||||
* [PubbyStation](https://tgstation13.org/wiki/PubbyStation)
|
||||
|
||||
|
||||
All maps have their own code file that is in the base of the _maps directory. Maps are loaded dynamically when the game starts. Follow this guideline when adding your own map, to your fork, for easy compatibility.
|
||||
|
||||
The map that will be loaded for the upcoming round is determined by reading data/next_map.json, which is a copy of the json files found in the _maps tree. If this file does not exist, the default map from config/maps.txt will be loaded. Failing that, BoxStation will be loaded. If you want to set a specific map to load next round you can use the Change Map verb in game before restarting the server or copy a json from _maps to data/next_map.json before starting the server. Also, for debugging purposes, ticking a corresponding map's code file in Dream Maker will force that map to load every round.
|
||||
|
||||
If you are hosting a server, and want randomly picked maps to be played each round, you can enable map rotation in [config.txt](config/config.txt) and then set the maps to be picked in the [maps.txt](config/maps.txt) file.
|
||||
|
||||
Anytime you want to make changes to a map it's imperative you use the [Map Merging tools](http://tgstation13.org/wiki/Map_Merger)
|
||||
|
||||
## AWAY MISSIONS
|
||||
|
||||
/tg/station supports loading away missions however they are disabled by default.
|
||||
|
||||
Map files for away missions are located in the _maps/RandomZLevels directory. Each away mission includes it's own code definitions located in /code/modules/awaymissions/mission_code. These files must be included and compiled with the server beforehand otherwise the server will crash upon trying to load away missions that lack their code.
|
||||
|
||||
To enable an away mission open `config/awaymissionconfig.txt` and uncomment one of the .dmm lines by removing the #. If more than one away mission is uncommented then the away mission loader will randomly select one the enabled ones to load.
|
||||
|
||||
## SQL SETUP
|
||||
|
||||
The SQL backend requires a Mariadb server running 10.2 or later. Mysql is not supported but Mariadb is a drop in replacement for mysql. SQL is required for the library, stats tracking, admin notes, and job-only bans, among other features, mostly related to server administration. Your server details go in /config/dbconfig.txt, and the SQL schema is in /SQL/tgstation_schema.sql and /SQL/tgstation_schema_prefix.sql depending on if you want table prefixes. More detailed setup instructions are located here: https://www.tgstation13.org/wiki/Downloading_the_source_code#Setting_up_the_database
|
||||
|
||||
## WEB/CDN RESOURCE DELIVERY
|
||||
|
||||
Web delivery of game resources makes it quicker for players to join and reduces some of the stress on the game server.
|
||||
|
||||
1. Edit compile_options.dm to set the `PRELOAD_RSC` define to `0`
|
||||
1. Add a url to config/external_rsc_urls pointing to a .zip file containing the .rsc.
|
||||
* If you keep up to date with /tg/ you could reuse /tg/'s rsc cdn at http://tgstation13.download/byond/tgstation.zip. Otherwise you can use cdn services like CDN77 or cloudflare (requires adding a page rule to enable caching of the zip), or roll your own cdn using route 53 and vps providers.
|
||||
* Regardless even offloading the rsc to a website without a CDN will be a massive improvement over the in game system for transferring files.
|
||||
|
||||
## IRC BOT SETUP
|
||||
|
||||
Included in the repository is a python3 compatible IRC bot capable of relaying adminhelps to a specified
|
||||
IRC channel/server, see the /tools/minibot folder for more
|
||||
|
||||
## CONTRIBUTING
|
||||
|
||||
Please see [CONTRIBUTING.md](.github/CONTRIBUTING.md)
|
||||
|
||||
## LICENSE
|
||||
|
||||
All code after [commit 333c566b88108de218d882840e61928a9b759d8f on 2014/31/12 at 4:38 PM PST](https://github.com/tgstation/tgstation/commit/333c566b88108de218d882840e61928a9b759d8f) is licensed under [GNU AGPL v3](http://www.gnu.org/licenses/agpl-3.0.html).
|
||||
|
||||
All code before [commit 333c566b88108de218d882840e61928a9b759d8f on 2014/31/12 at 4:38 PM PST](https://github.com/tgstation/tgstation/commit/333c566b88108de218d882840e61928a9b759d8f) is licensed under [GNU GPL v3](https://www.gnu.org/licenses/gpl-3.0.html).
|
||||
(Including tools unless their readme specifies otherwise.)
|
||||
|
||||
See LICENSE and GPLv3.txt for more details.
|
||||
|
||||
The TGS3 API is licensed as a subproject under the MIT license.
|
||||
|
||||
See the footers of code/\_\_DEFINES/server\_tools.dm, code/modules/server\_tools/st\_commands.dm, and code/modules/server\_tools/st\_inteface.dm for the MIT license.
|
||||
|
||||
tgui clientside is licensed as a subproject under the MIT license.
|
||||
Font Awesome font files, used by tgui, are licensed under the SIL Open Font License v1.1
|
||||
tgui assets are licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/).
|
||||
|
||||
All assets including icons and sound are under a [Creative Commons 3.0 BY-SA license](https://creativecommons.org/licenses/by-sa/3.0/) unless otherwise indicated.
|
||||
## Citadel Station 13
|
||||
Based and maintained from /tg/station.
|
||||
|
||||
[](https://travis-ci.org/Citadel-Station-13/Citadel-Station-13)
|
||||
[](http://isitmaintained.com/project/Citadel-Station-13/Citadel-Station-13 "Percentage of issues still open")
|
||||
[](http://isitmaintained.com/project/Citadel-Station-13/Citadel-Station-13 "Average time to resolve an issue")
|
||||
|
||||
[](https://forthebadge.com) [](https://forthebadge.com) [](http://forthebadge.com) [](https://www.reddit.com/r/SS13/comments/5oplxp/what_is_the_main_problem_with_byond_as_an_engine/dclbu1a)
|
||||
|
||||
**Upstream Information**
|
||||
* **Website:** <https://www.tgstation13.org>
|
||||
* **Code:** <https://github.com/tgstation/tgstation>
|
||||
* **Wiki:** <https://tgstation13.org/wiki/Main_Page>
|
||||
* **Codedocs:** <https://codedocs.tgstation13.org>
|
||||
* **/tg/station Discord:** <https://tgstation13.org/phpBB/viewforum.php?f=60>
|
||||
* **Coderbus Discord:** <https://discord.gg/Vh8TJp9>
|
||||
* ~~**IRC:** <irc://irc.rizon.net/coderbus>~~ (dead)
|
||||
|
||||
**Citadel Station Information**
|
||||
* **Website:** <http://citadel-station.net>
|
||||
* **Code:** <https://github.com/Citadel-Station-13/Citadel-Station-13>
|
||||
* **Wiki:** <https://citadel-station.net/wiki/index.php?title=Main_Page>
|
||||
* **Forums:** <http://citadel-station.net/forum>
|
||||
* **Ban Appeals:** <http://citadel-station.net/forum/forumdisplay.php?fid=8>
|
||||
* **Discord:** <https://discord.gg/E6SQuhz>
|
||||
|
||||
## DOWNLOADING
|
||||
|
||||
There are a number of ways to download the source code. Some are described here, an alternative all-inclusive guide is also located at http://www.tgstation13.org/wiki/Downloading_the_source_code
|
||||
|
||||
Option 1:
|
||||
Follow this: http://www.tgstation13.org/wiki/Setting_up_git
|
||||
|
||||
Option 2: Download the source code as a zip by clicking the ZIP button in the
|
||||
code tab of https://github.com/tgstation/tgstation
|
||||
(note: this will use a lot of bandwidth if you wish to update and is a lot of
|
||||
hassle if you want to make any changes at all, so it's not recommended.)
|
||||
|
||||
Option 3: Download a pre-compiled nightly at https://tgstation13.download/nightlies/ (same caveats as option 2)
|
||||
|
||||
## INSTALLATION
|
||||
|
||||
First-time installation should be fairly straightforward. First, you'll need
|
||||
BYOND installed. You can get it from https://www.byond.com/download. Once you've done
|
||||
that, extract the game files to wherever you want to keep them. This is a
|
||||
sourcecode-only release, so the next step is to compile the server files.
|
||||
Open tgstation.dme by double-clicking it, open the Build menu, and click
|
||||
compile. This'll take a little while, and if everything's done right you'll get
|
||||
a message like this:
|
||||
|
||||
```
|
||||
saving tgstation.dmb (DEBUG mode)
|
||||
tgstation.dmb - 0 errors, 0 warnings
|
||||
```
|
||||
|
||||
If you see any errors or warnings, something has gone wrong - possibly a corrupt
|
||||
download or the files extracted wrong. If problems persist, ask for assistance
|
||||
in irc://irc.rizon.net/coderbus
|
||||
|
||||
Once that's done, open up the config folder. You'll want to edit config.txt to
|
||||
set the probabilities for different gamemodes in Secret and to set your server
|
||||
location so that all your players don't get disconnected at the end of each
|
||||
round. It's recommended you don't turn on the gamemodes with probability 0,
|
||||
except Extended, as they have various issues and aren't currently being tested,
|
||||
so they may have unknown and bizarre bugs. Extended is essentially no mode, and
|
||||
isn't in the Secret rotation by default as it's just not very fun.
|
||||
|
||||
You'll also want to edit config/admins.txt to remove the default admins and add
|
||||
your own. "Game Master" is the highest level of access, and probably the one
|
||||
you'll want to use for now. You can set up your own ranks and find out more in
|
||||
config/admin_ranks.txt
|
||||
|
||||
The format is
|
||||
|
||||
```
|
||||
byondkey = Rank
|
||||
```
|
||||
|
||||
where the admin rank must be properly capitalised.
|
||||
|
||||
This codebase also depends on a native library called rust-g. A precompiled
|
||||
Windows DLL is included in this repository, but Linux users will need to build
|
||||
and install it themselves. Directions can be found at the [rust-g
|
||||
repo](https://github.com/tgstation13/rust-g).
|
||||
|
||||
Finally, to start the server, run Dream Daemon and enter the path to your
|
||||
compiled tgstation.dmb file. Make sure to set the port to the one you
|
||||
specified in the config.txt, and set the Security box to 'Safe'. Then press GO
|
||||
and the server should start up and be ready to join. It is also recommended that
|
||||
you set up the SQL backend (see below).
|
||||
|
||||
## UPDATING
|
||||
|
||||
To update an existing installation, first back up your /config and /data folders
|
||||
as these store your server configuration, player preferences and banlist.
|
||||
|
||||
Then, extract the new files (preferably into a clean directory, but updating in
|
||||
place should work fine), copy your /config and /data folders back into the new
|
||||
install, overwriting when prompted except if we've specified otherwise, and
|
||||
recompile the game. Once you start the server up again, you should be running
|
||||
the new version.
|
||||
|
||||
## HOSTING
|
||||
|
||||
If you'd like a more robust server hosting option for tgstation and its
|
||||
derivatives. Check out our server tools suite at
|
||||
https://github.com/tgstation/tgstation-server
|
||||
|
||||
## MAPS
|
||||
|
||||
/tg/station currently comes equipped with five maps.
|
||||
|
||||
* [BoxStation (default)](http://tgstation13.org/wiki/Boxstation)
|
||||
* [MetaStation](https://tgstation13.org/wiki/MetaStation)
|
||||
* [DeltaStation](https://tgstation13.org/wiki/DeltaStation)
|
||||
* [OmegaStation](https://tgstation13.org/wiki/OmegaStation)
|
||||
* [PubbyStation](https://tgstation13.org/wiki/PubbyStation)
|
||||
|
||||
|
||||
All maps have their own code file that is in the base of the _maps directory. Maps are loaded dynamically when the game starts. Follow this guideline when adding your own map, to your fork, for easy compatibility.
|
||||
|
||||
The map that will be loaded for the upcoming round is determined by reading data/next_map.json, which is a copy of the json files found in the _maps tree. If this file does not exist, the default map from config/maps.txt will be loaded. Failing that, BoxStation will be loaded. If you want to set a specific map to load next round you can use the Change Map verb in game before restarting the server or copy a json from _maps to data/next_map.json before starting the server. Also, for debugging purposes, ticking a corresponding map's code file in Dream Maker will force that map to load every round.
|
||||
|
||||
If you are hosting a server, and want randomly picked maps to be played each round, you can enable map rotation in [config.txt](config/config.txt) and then set the maps to be picked in the [maps.txt](config/maps.txt) file.
|
||||
|
||||
Anytime you want to make changes to a map it's imperative you use the [Map Merging tools](http://tgstation13.org/wiki/Map_Merger)
|
||||
|
||||
## AWAY MISSIONS
|
||||
|
||||
/tg/station supports loading away missions however they are disabled by default.
|
||||
|
||||
Map files for away missions are located in the _maps/RandomZLevels directory. Each away mission includes it's own code definitions located in /code/modules/awaymissions/mission_code. These files must be included and compiled with the server beforehand otherwise the server will crash upon trying to load away missions that lack their code.
|
||||
|
||||
To enable an away mission open `config/awaymissionconfig.txt` and uncomment one of the .dmm lines by removing the #. If more than one away mission is uncommented then the away mission loader will randomly select one the enabled ones to load.
|
||||
|
||||
## SQL SETUP
|
||||
|
||||
The SQL backend requires a Mariadb server running 10.2 or later. Mysql is not supported but Mariadb is a drop in replacement for mysql. SQL is required for the library, stats tracking, admin notes, and job-only bans, among other features, mostly related to server administration. Your server details go in /config/dbconfig.txt, and the SQL schema is in /SQL/tgstation_schema.sql and /SQL/tgstation_schema_prefix.sql depending on if you want table prefixes. More detailed setup instructions are located here: https://www.tgstation13.org/wiki/Downloading_the_source_code#Setting_up_the_database
|
||||
|
||||
## WEB/CDN RESOURCE DELIVERY
|
||||
|
||||
Web delivery of game resources makes it quicker for players to join and reduces some of the stress on the game server.
|
||||
|
||||
1. Edit compile_options.dm to set the `PRELOAD_RSC` define to `0`
|
||||
1. Add a url to config/external_rsc_urls pointing to a .zip file containing the .rsc.
|
||||
* If you keep up to date with /tg/ you could reuse /tg/'s rsc cdn at http://tgstation13.download/byond/tgstation.zip. Otherwise you can use cdn services like CDN77 or cloudflare (requires adding a page rule to enable caching of the zip), or roll your own cdn using route 53 and vps providers.
|
||||
* Regardless even offloading the rsc to a website without a CDN will be a massive improvement over the in game system for transferring files.
|
||||
|
||||
## IRC BOT SETUP
|
||||
|
||||
Included in the repository is a python3 compatible IRC bot capable of relaying adminhelps to a specified
|
||||
IRC channel/server, see the /tools/minibot folder for more
|
||||
|
||||
## CONTRIBUTING
|
||||
|
||||
Please see [CONTRIBUTING.md](.github/CONTRIBUTING.md)
|
||||
|
||||
## LICENSE
|
||||
|
||||
All code after [commit 333c566b88108de218d882840e61928a9b759d8f on 2014/31/12 at 4:38 PM PST](https://github.com/tgstation/tgstation/commit/333c566b88108de218d882840e61928a9b759d8f) is licensed under [GNU AGPL v3](http://www.gnu.org/licenses/agpl-3.0.html).
|
||||
|
||||
All code before [commit 333c566b88108de218d882840e61928a9b759d8f on 2014/31/12 at 4:38 PM PST](https://github.com/tgstation/tgstation/commit/333c566b88108de218d882840e61928a9b759d8f) is licensed under [GNU GPL v3](https://www.gnu.org/licenses/gpl-3.0.html).
|
||||
(Including tools unless their readme specifies otherwise.)
|
||||
|
||||
See LICENSE and GPLv3.txt for more details.
|
||||
|
||||
The TGS3 API is licensed as a subproject under the MIT license.
|
||||
|
||||
See the footers of code/\_\_DEFINES/server\_tools.dm, code/modules/server\_tools/st\_commands.dm, and code/modules/server\_tools/st\_inteface.dm for the MIT license.
|
||||
|
||||
tgui clientside is licensed as a subproject under the MIT license.
|
||||
Font Awesome font files, used by tgui, are licensed under the SIL Open Font License v1.1
|
||||
tgui assets are licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/).
|
||||
|
||||
All assets including icons and sound are under a [Creative Commons 3.0 BY-SA license](https://creativecommons.org/licenses/by-sa/3.0/) unless otherwise indicated.
|
||||
|
||||
+473
-473
@@ -1,473 +1,473 @@
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
|
||||
--
|
||||
-- Table structure for table `admin`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `admin`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `admin` (
|
||||
`ckey` varchar(32) NOT NULL,
|
||||
`rank` varchar(32) NOT NULL,
|
||||
PRIMARY KEY (`ckey`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `admin_log`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `admin_log`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `admin_log` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`datetime` datetime NOT NULL,
|
||||
`round_id` int(11) unsigned NOT NULL,
|
||||
`adminckey` varchar(32) NOT NULL,
|
||||
`adminip` int(10) unsigned NOT NULL,
|
||||
`operation` enum('add admin','remove admin','change admin rank','add rank','remove rank','change rank flags') NOT NULL,
|
||||
`target` varchar(32) NOT NULL,
|
||||
`log` varchar(1000) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `admin_ranks`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `admin_ranks`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `admin_ranks` (
|
||||
`rank` varchar(32) NOT NULL,
|
||||
`flags` smallint(5) unsigned NOT NULL,
|
||||
`exclude_flags` smallint(5) unsigned NOT NULL,
|
||||
`can_edit_flags` smallint(5) unsigned NOT NULL,
|
||||
PRIMARY KEY (`rank`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `ban`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `ban`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `ban` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`bantime` datetime NOT NULL,
|
||||
`server_ip` int(10) unsigned NOT NULL,
|
||||
`server_port` smallint(5) unsigned NOT NULL,
|
||||
`round_id` int(11) NOT NULL,
|
||||
`bantype` enum('PERMABAN','TEMPBAN','JOB_PERMABAN','JOB_TEMPBAN','ADMIN_PERMABAN','ADMIN_TEMPBAN') NOT NULL,
|
||||
`reason` varchar(2048) NOT NULL,
|
||||
`job` varchar(32) DEFAULT NULL,
|
||||
`duration` int(11) NOT NULL,
|
||||
`expiration_time` datetime NOT NULL,
|
||||
`ckey` varchar(32) NOT NULL,
|
||||
`computerid` varchar(32) NOT NULL,
|
||||
`ip` int(10) unsigned NOT NULL,
|
||||
`a_ckey` varchar(32) NOT NULL,
|
||||
`a_computerid` varchar(32) NOT NULL,
|
||||
`a_ip` int(10) unsigned NOT NULL,
|
||||
`who` varchar(2048) NOT NULL,
|
||||
`adminwho` varchar(2048) NOT NULL,
|
||||
`edits` text,
|
||||
`unbanned` tinyint(3) unsigned DEFAULT NULL,
|
||||
`unbanned_datetime` datetime DEFAULT NULL,
|
||||
`unbanned_ckey` varchar(32) DEFAULT NULL,
|
||||
`unbanned_computerid` varchar(32) DEFAULT NULL,
|
||||
`unbanned_ip` int(10) unsigned DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_ban_checkban` (`ckey`,`bantype`,`expiration_time`,`unbanned`,`job`),
|
||||
KEY `idx_ban_isbanned` (`ckey`,`ip`,`computerid`,`bantype`,`expiration_time`,`unbanned`),
|
||||
KEY `idx_ban_count` (`id`,`a_ckey`,`bantype`,`expiration_time`,`unbanned`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `connection_log`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `connection_log`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `connection_log` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`datetime` datetime DEFAULT NULL,
|
||||
`server_ip` int(10) unsigned NOT NULL,
|
||||
`server_port` smallint(5) unsigned NOT NULL,
|
||||
`round_id` int(11) unsigned NOT NULL,
|
||||
`ckey` varchar(45) DEFAULT NULL,
|
||||
`ip` int(10) unsigned NOT NULL,
|
||||
`computerid` varchar(45) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `death`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `death`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `death` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`pod` varchar(50) NOT NULL,
|
||||
`x_coord` smallint(5) unsigned NOT NULL,
|
||||
`y_coord` smallint(5) unsigned NOT NULL,
|
||||
`z_coord` smallint(5) unsigned NOT NULL,
|
||||
`mapname` varchar(32) NOT NULL,
|
||||
`server_ip` int(10) unsigned NOT NULL,
|
||||
`server_port` smallint(5) unsigned NOT NULL,
|
||||
`round_id` int(11) NOT NULL,
|
||||
`tod` datetime NOT NULL COMMENT 'Time of death',
|
||||
`job` varchar(32) NOT NULL,
|
||||
`special` varchar(32) DEFAULT NULL,
|
||||
`name` varchar(96) NOT NULL,
|
||||
`byondkey` varchar(32) NOT NULL,
|
||||
`laname` varchar(96) DEFAULT NULL,
|
||||
`lakey` varchar(32) DEFAULT NULL,
|
||||
`bruteloss` smallint(5) unsigned NOT NULL,
|
||||
`brainloss` smallint(5) unsigned NOT NULL,
|
||||
`fireloss` smallint(5) unsigned NOT NULL,
|
||||
`oxyloss` smallint(5) unsigned NOT NULL,
|
||||
`toxloss` smallint(5) unsigned NOT NULL,
|
||||
`cloneloss` smallint(5) unsigned NOT NULL,
|
||||
`staminaloss` smallint(5) unsigned NOT NULL,
|
||||
`last_words` varchar(255) DEFAULT NULL,
|
||||
`suicide` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `feedback`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `feedback`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `feedback` (
|
||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`datetime` datetime NOT NULL,
|
||||
`round_id` int(11) unsigned NOT NULL,
|
||||
`key_name` varchar(32) NOT NULL,
|
||||
`key_type` enum('text', 'amount', 'tally', 'nested tally', 'associative') NOT NULL,
|
||||
`version` tinyint(3) unsigned NOT NULL,
|
||||
`json` json NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `ipintel`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `ipintel`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `ipintel` (
|
||||
`ip` int(10) unsigned NOT NULL,
|
||||
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`intel` double NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`ip`),
|
||||
KEY `idx_ipintel` (`ip`,`intel`,`date`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `legacy_population`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `legacy_population`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `legacy_population` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`playercount` int(11) DEFAULT NULL,
|
||||
`admincount` int(11) DEFAULT NULL,
|
||||
`time` datetime NOT NULL,
|
||||
`server_ip` int(10) unsigned NOT NULL,
|
||||
`server_port` smallint(5) unsigned NOT NULL,
|
||||
`round_id` int(11) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `library`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `library`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `library` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`author` varchar(45) NOT NULL,
|
||||
`title` varchar(45) NOT NULL,
|
||||
`content` text NOT NULL,
|
||||
`category` enum('Any','Fiction','Non-Fiction','Adult','Reference','Religion') NOT NULL,
|
||||
`ckey` varchar(32) NOT NULL DEFAULT 'LEGACY',
|
||||
`datetime` datetime NOT NULL,
|
||||
`deleted` tinyint(1) unsigned DEFAULT NULL,
|
||||
`round_id_created` int(11) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `deleted_idx` (`deleted`),
|
||||
KEY `idx_lib_id_del` (`id`,`deleted`),
|
||||
KEY `idx_lib_del_title` (`deleted`,`title`),
|
||||
KEY `idx_lib_search` (`deleted`,`author`,`title`,`category`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `messages`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `messages`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `messages` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`type` enum('memo','message','message sent','note','watchlist entry') NOT NULL,
|
||||
`targetckey` varchar(32) NOT NULL,
|
||||
`adminckey` varchar(32) NOT NULL,
|
||||
`text` varchar(2048) NOT NULL,
|
||||
`timestamp` datetime NOT NULL,
|
||||
`server` varchar(32) DEFAULT NULL,
|
||||
`server_ip` int(10) unsigned NOT NULL,
|
||||
`server_port` smallint(5) unsigned NOT NULL,
|
||||
`round_id` int(11) unsigned NOT NULL,
|
||||
`secret` tinyint(1) unsigned NOT NULL,
|
||||
`expire_timestamp` datetime DEFAULT NULL,
|
||||
`severity` enum('high','medium','minor','none') DEFAULT NULL,
|
||||
`lasteditor` varchar(32) DEFAULT NULL,
|
||||
`edits` text,
|
||||
`deleted` tinyint(1) unsigned NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_msg_ckey_time` (`targetckey`,`timestamp`, `deleted`),
|
||||
KEY `idx_msg_type_ckeys_time` (`type`,`targetckey`,`adminckey`,`timestamp`, `deleted`),
|
||||
KEY `idx_msg_type_ckey_time_odr` (`type`,`targetckey`,`timestamp`, `deleted`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `role_time`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `role_time`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
|
||||
CREATE TABLE `role_time`
|
||||
( `ckey` VARCHAR(32) NOT NULL ,
|
||||
`job` VARCHAR(32) NOT NULL ,
|
||||
`minutes` INT UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`ckey`, `job`)
|
||||
) ENGINE = InnoDB;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `role_time`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `role_time_log`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `role_time_log` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`ckey` varchar(32) NOT NULL,
|
||||
`job` varchar(128) NOT NULL,
|
||||
`delta` int(11) NOT NULL,
|
||||
`datetime` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ckey` (`ckey`),
|
||||
KEY `job` (`job`),
|
||||
KEY `datetime` (`datetime`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `player`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `player`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `player` (
|
||||
`ckey` varchar(32) NOT NULL,
|
||||
`byond_key` varchar(32) DEFAULT NULL,
|
||||
`firstseen` datetime NOT NULL,
|
||||
`firstseen_round_id` int(11) unsigned NOT NULL,
|
||||
`lastseen` datetime NOT NULL,
|
||||
`lastseen_round_id` int(11) unsigned NOT NULL,
|
||||
`ip` int(10) unsigned NOT NULL,
|
||||
`computerid` varchar(32) NOT NULL,
|
||||
`lastadminrank` varchar(32) NOT NULL DEFAULT 'Player',
|
||||
`accountjoindate` DATE DEFAULT NULL,
|
||||
`flags` smallint(5) unsigned DEFAULT '0' NOT NULL,
|
||||
PRIMARY KEY (`ckey`),
|
||||
KEY `idx_player_cid_ckey` (`computerid`,`ckey`),
|
||||
KEY `idx_player_ip_ckey` (`ip`,`ckey`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `poll_option`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `poll_option`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `poll_option` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`pollid` int(11) NOT NULL,
|
||||
`text` varchar(255) NOT NULL,
|
||||
`minval` int(3) DEFAULT NULL,
|
||||
`maxval` int(3) DEFAULT NULL,
|
||||
`descmin` varchar(32) DEFAULT NULL,
|
||||
`descmid` varchar(32) DEFAULT NULL,
|
||||
`descmax` varchar(32) DEFAULT NULL,
|
||||
`default_percentage_calc` tinyint(1) unsigned NOT NULL DEFAULT '1',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_pop_pollid` (`pollid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `poll_question`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `poll_question`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `poll_question` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`polltype` enum('OPTION','TEXT','NUMVAL','MULTICHOICE','IRV') NOT NULL,
|
||||
`starttime` datetime NOT NULL,
|
||||
`endtime` datetime NOT NULL,
|
||||
`question` varchar(255) NOT NULL,
|
||||
`adminonly` tinyint(1) unsigned NOT NULL,
|
||||
`multiplechoiceoptions` int(2) DEFAULT NULL,
|
||||
`createdby_ckey` varchar(32) DEFAULT NULL,
|
||||
`createdby_ip` int(10) unsigned NOT NULL,
|
||||
`dontshow` tinyint(1) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_pquest_question_time_ckey` (`question`,`starttime`,`endtime`,`createdby_ckey`,`createdby_ip`),
|
||||
KEY `idx_pquest_time_admin` (`starttime`,`endtime`,`adminonly`),
|
||||
KEY `idx_pquest_id_time_type_admin` (`id`,`starttime`,`endtime`,`polltype`,`adminonly`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `poll_textreply`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `poll_textreply`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `poll_textreply` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`datetime` datetime NOT NULL,
|
||||
`pollid` int(11) NOT NULL,
|
||||
`ckey` varchar(32) NOT NULL,
|
||||
`ip` int(10) unsigned NOT NULL,
|
||||
`replytext` varchar(2048) NOT NULL,
|
||||
`adminrank` varchar(32) NOT NULL DEFAULT 'Player',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_ptext_pollid_ckey` (`pollid`,`ckey`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `poll_vote`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `poll_vote`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `poll_vote` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`datetime` datetime NOT NULL,
|
||||
`pollid` int(11) NOT NULL,
|
||||
`optionid` int(11) NOT NULL,
|
||||
`ckey` varchar(32) NOT NULL,
|
||||
`ip` int(10) unsigned NOT NULL,
|
||||
`adminrank` varchar(32) NOT NULL,
|
||||
`rating` int(2) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_pvote_pollid_ckey` (`pollid`,`ckey`),
|
||||
KEY `idx_pvote_optionid_ckey` (`optionid`,`ckey`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `round`
|
||||
--
|
||||
DROP TABLE IF EXISTS `round`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `round` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`initialize_datetime` DATETIME NOT NULL,
|
||||
`start_datetime` DATETIME NULL,
|
||||
`shutdown_datetime` DATETIME NULL,
|
||||
`end_datetime` DATETIME NULL,
|
||||
`server_ip` INT(10) UNSIGNED NOT NULL,
|
||||
`server_port` SMALLINT(5) UNSIGNED NOT NULL,
|
||||
`commit_hash` CHAR(40) NULL,
|
||||
`game_mode` VARCHAR(32) NULL,
|
||||
`game_mode_result` VARCHAR(64) NULL,
|
||||
`end_state` VARCHAR(64) NULL,
|
||||
`shuttle_name` VARCHAR(64) NULL,
|
||||
`map_name` VARCHAR(32) NULL,
|
||||
`station_name` VARCHAR(80) NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||
|
||||
--
|
||||
-- Table structure for table `schema_revision`
|
||||
--
|
||||
DROP TABLE IF EXISTS `schema_revision`;
|
||||
CREATE TABLE `schema_revision` (
|
||||
`major` TINYINT(3) unsigned NOT NULL,
|
||||
`minor` TINYINT(3) unsigned NOT NULL,
|
||||
`date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`major`, `minor`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE TRIGGER `role_timeTlogupdate` AFTER UPDATE ON `role_time` FOR EACH ROW BEGIN INSERT into role_time_log (ckey, job, delta) VALUES (NEW.CKEY, NEW.job, NEW.minutes-OLD.minutes);
|
||||
END
|
||||
$$
|
||||
CREATE TRIGGER `role_timeTloginsert` AFTER INSERT ON `role_time` FOR EACH ROW BEGIN INSERT into role_time_log (ckey, job, delta) VALUES (NEW.ckey, NEW.job, NEW.minutes);
|
||||
END
|
||||
$$
|
||||
CREATE TRIGGER `role_timeTlogdelete` AFTER DELETE ON `role_time` FOR EACH ROW BEGIN INSERT into role_time_log (ckey, job, delta) VALUES (OLD.ckey, OLD.job, 0-OLD.minutes);
|
||||
END
|
||||
$$
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
|
||||
--
|
||||
-- Table structure for table `admin`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `admin`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `admin` (
|
||||
`ckey` varchar(32) NOT NULL,
|
||||
`rank` varchar(32) NOT NULL,
|
||||
PRIMARY KEY (`ckey`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `admin_log`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `admin_log`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `admin_log` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`datetime` datetime NOT NULL,
|
||||
`round_id` int(11) unsigned NOT NULL,
|
||||
`adminckey` varchar(32) NOT NULL,
|
||||
`adminip` int(10) unsigned NOT NULL,
|
||||
`operation` enum('add admin','remove admin','change admin rank','add rank','remove rank','change rank flags') NOT NULL,
|
||||
`target` varchar(32) NOT NULL,
|
||||
`log` varchar(1000) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `admin_ranks`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `admin_ranks`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `admin_ranks` (
|
||||
`rank` varchar(32) NOT NULL,
|
||||
`flags` smallint(5) unsigned NOT NULL,
|
||||
`exclude_flags` smallint(5) unsigned NOT NULL,
|
||||
`can_edit_flags` smallint(5) unsigned NOT NULL,
|
||||
PRIMARY KEY (`rank`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `ban`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `ban`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `ban` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`bantime` datetime NOT NULL,
|
||||
`server_ip` int(10) unsigned NOT NULL,
|
||||
`server_port` smallint(5) unsigned NOT NULL,
|
||||
`round_id` int(11) NOT NULL,
|
||||
`bantype` enum('PERMABAN','TEMPBAN','JOB_PERMABAN','JOB_TEMPBAN','ADMIN_PERMABAN','ADMIN_TEMPBAN') NOT NULL,
|
||||
`reason` varchar(2048) NOT NULL,
|
||||
`job` varchar(32) DEFAULT NULL,
|
||||
`duration` int(11) NOT NULL,
|
||||
`expiration_time` datetime NOT NULL,
|
||||
`ckey` varchar(32) NOT NULL,
|
||||
`computerid` varchar(32) NOT NULL,
|
||||
`ip` int(10) unsigned NOT NULL,
|
||||
`a_ckey` varchar(32) NOT NULL,
|
||||
`a_computerid` varchar(32) NOT NULL,
|
||||
`a_ip` int(10) unsigned NOT NULL,
|
||||
`who` varchar(2048) NOT NULL,
|
||||
`adminwho` varchar(2048) NOT NULL,
|
||||
`edits` text,
|
||||
`unbanned` tinyint(3) unsigned DEFAULT NULL,
|
||||
`unbanned_datetime` datetime DEFAULT NULL,
|
||||
`unbanned_ckey` varchar(32) DEFAULT NULL,
|
||||
`unbanned_computerid` varchar(32) DEFAULT NULL,
|
||||
`unbanned_ip` int(10) unsigned DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_ban_checkban` (`ckey`,`bantype`,`expiration_time`,`unbanned`,`job`),
|
||||
KEY `idx_ban_isbanned` (`ckey`,`ip`,`computerid`,`bantype`,`expiration_time`,`unbanned`),
|
||||
KEY `idx_ban_count` (`id`,`a_ckey`,`bantype`,`expiration_time`,`unbanned`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `connection_log`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `connection_log`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `connection_log` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`datetime` datetime DEFAULT NULL,
|
||||
`server_ip` int(10) unsigned NOT NULL,
|
||||
`server_port` smallint(5) unsigned NOT NULL,
|
||||
`round_id` int(11) unsigned NOT NULL,
|
||||
`ckey` varchar(45) DEFAULT NULL,
|
||||
`ip` int(10) unsigned NOT NULL,
|
||||
`computerid` varchar(45) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `death`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `death`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `death` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`pod` varchar(50) NOT NULL,
|
||||
`x_coord` smallint(5) unsigned NOT NULL,
|
||||
`y_coord` smallint(5) unsigned NOT NULL,
|
||||
`z_coord` smallint(5) unsigned NOT NULL,
|
||||
`mapname` varchar(32) NOT NULL,
|
||||
`server_ip` int(10) unsigned NOT NULL,
|
||||
`server_port` smallint(5) unsigned NOT NULL,
|
||||
`round_id` int(11) NOT NULL,
|
||||
`tod` datetime NOT NULL COMMENT 'Time of death',
|
||||
`job` varchar(32) NOT NULL,
|
||||
`special` varchar(32) DEFAULT NULL,
|
||||
`name` varchar(96) NOT NULL,
|
||||
`byondkey` varchar(32) NOT NULL,
|
||||
`laname` varchar(96) DEFAULT NULL,
|
||||
`lakey` varchar(32) DEFAULT NULL,
|
||||
`bruteloss` smallint(5) unsigned NOT NULL,
|
||||
`brainloss` smallint(5) unsigned NOT NULL,
|
||||
`fireloss` smallint(5) unsigned NOT NULL,
|
||||
`oxyloss` smallint(5) unsigned NOT NULL,
|
||||
`toxloss` smallint(5) unsigned NOT NULL,
|
||||
`cloneloss` smallint(5) unsigned NOT NULL,
|
||||
`staminaloss` smallint(5) unsigned NOT NULL,
|
||||
`last_words` varchar(255) DEFAULT NULL,
|
||||
`suicide` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `feedback`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `feedback`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `feedback` (
|
||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`datetime` datetime NOT NULL,
|
||||
`round_id` int(11) unsigned NOT NULL,
|
||||
`key_name` varchar(32) NOT NULL,
|
||||
`key_type` enum('text', 'amount', 'tally', 'nested tally', 'associative') NOT NULL,
|
||||
`version` tinyint(3) unsigned NOT NULL,
|
||||
`json` json NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `ipintel`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `ipintel`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `ipintel` (
|
||||
`ip` int(10) unsigned NOT NULL,
|
||||
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`intel` double NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`ip`),
|
||||
KEY `idx_ipintel` (`ip`,`intel`,`date`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `legacy_population`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `legacy_population`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `legacy_population` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`playercount` int(11) DEFAULT NULL,
|
||||
`admincount` int(11) DEFAULT NULL,
|
||||
`time` datetime NOT NULL,
|
||||
`server_ip` int(10) unsigned NOT NULL,
|
||||
`server_port` smallint(5) unsigned NOT NULL,
|
||||
`round_id` int(11) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `library`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `library`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `library` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`author` varchar(45) NOT NULL,
|
||||
`title` varchar(45) NOT NULL,
|
||||
`content` text NOT NULL,
|
||||
`category` enum('Any','Fiction','Non-Fiction','Adult','Reference','Religion') NOT NULL,
|
||||
`ckey` varchar(32) NOT NULL DEFAULT 'LEGACY',
|
||||
`datetime` datetime NOT NULL,
|
||||
`deleted` tinyint(1) unsigned DEFAULT NULL,
|
||||
`round_id_created` int(11) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `deleted_idx` (`deleted`),
|
||||
KEY `idx_lib_id_del` (`id`,`deleted`),
|
||||
KEY `idx_lib_del_title` (`deleted`,`title`),
|
||||
KEY `idx_lib_search` (`deleted`,`author`,`title`,`category`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `messages`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `messages`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `messages` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`type` enum('memo','message','message sent','note','watchlist entry') NOT NULL,
|
||||
`targetckey` varchar(32) NOT NULL,
|
||||
`adminckey` varchar(32) NOT NULL,
|
||||
`text` varchar(2048) NOT NULL,
|
||||
`timestamp` datetime NOT NULL,
|
||||
`server` varchar(32) DEFAULT NULL,
|
||||
`server_ip` int(10) unsigned NOT NULL,
|
||||
`server_port` smallint(5) unsigned NOT NULL,
|
||||
`round_id` int(11) unsigned NOT NULL,
|
||||
`secret` tinyint(1) unsigned NOT NULL,
|
||||
`expire_timestamp` datetime DEFAULT NULL,
|
||||
`severity` enum('high','medium','minor','none') DEFAULT NULL,
|
||||
`lasteditor` varchar(32) DEFAULT NULL,
|
||||
`edits` text,
|
||||
`deleted` tinyint(1) unsigned NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_msg_ckey_time` (`targetckey`,`timestamp`, `deleted`),
|
||||
KEY `idx_msg_type_ckeys_time` (`type`,`targetckey`,`adminckey`,`timestamp`, `deleted`),
|
||||
KEY `idx_msg_type_ckey_time_odr` (`type`,`targetckey`,`timestamp`, `deleted`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `role_time`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `role_time`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
|
||||
CREATE TABLE `role_time`
|
||||
( `ckey` VARCHAR(32) NOT NULL ,
|
||||
`job` VARCHAR(32) NOT NULL ,
|
||||
`minutes` INT UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`ckey`, `job`)
|
||||
) ENGINE = InnoDB;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `role_time`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `role_time_log`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `role_time_log` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`ckey` varchar(32) NOT NULL,
|
||||
`job` varchar(128) NOT NULL,
|
||||
`delta` int(11) NOT NULL,
|
||||
`datetime` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ckey` (`ckey`),
|
||||
KEY `job` (`job`),
|
||||
KEY `datetime` (`datetime`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `player`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `player`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `player` (
|
||||
`ckey` varchar(32) NOT NULL,
|
||||
`byond_key` varchar(32) DEFAULT NULL,
|
||||
`firstseen` datetime NOT NULL,
|
||||
`firstseen_round_id` int(11) unsigned NOT NULL,
|
||||
`lastseen` datetime NOT NULL,
|
||||
`lastseen_round_id` int(11) unsigned NOT NULL,
|
||||
`ip` int(10) unsigned NOT NULL,
|
||||
`computerid` varchar(32) NOT NULL,
|
||||
`lastadminrank` varchar(32) NOT NULL DEFAULT 'Player',
|
||||
`accountjoindate` DATE DEFAULT NULL,
|
||||
`flags` smallint(5) unsigned DEFAULT '0' NOT NULL,
|
||||
PRIMARY KEY (`ckey`),
|
||||
KEY `idx_player_cid_ckey` (`computerid`,`ckey`),
|
||||
KEY `idx_player_ip_ckey` (`ip`,`ckey`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `poll_option`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `poll_option`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `poll_option` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`pollid` int(11) NOT NULL,
|
||||
`text` varchar(255) NOT NULL,
|
||||
`minval` int(3) DEFAULT NULL,
|
||||
`maxval` int(3) DEFAULT NULL,
|
||||
`descmin` varchar(32) DEFAULT NULL,
|
||||
`descmid` varchar(32) DEFAULT NULL,
|
||||
`descmax` varchar(32) DEFAULT NULL,
|
||||
`default_percentage_calc` tinyint(1) unsigned NOT NULL DEFAULT '1',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_pop_pollid` (`pollid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `poll_question`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `poll_question`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `poll_question` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`polltype` enum('OPTION','TEXT','NUMVAL','MULTICHOICE','IRV') NOT NULL,
|
||||
`starttime` datetime NOT NULL,
|
||||
`endtime` datetime NOT NULL,
|
||||
`question` varchar(255) NOT NULL,
|
||||
`adminonly` tinyint(1) unsigned NOT NULL,
|
||||
`multiplechoiceoptions` int(2) DEFAULT NULL,
|
||||
`createdby_ckey` varchar(32) DEFAULT NULL,
|
||||
`createdby_ip` int(10) unsigned NOT NULL,
|
||||
`dontshow` tinyint(1) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_pquest_question_time_ckey` (`question`,`starttime`,`endtime`,`createdby_ckey`,`createdby_ip`),
|
||||
KEY `idx_pquest_time_admin` (`starttime`,`endtime`,`adminonly`),
|
||||
KEY `idx_pquest_id_time_type_admin` (`id`,`starttime`,`endtime`,`polltype`,`adminonly`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `poll_textreply`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `poll_textreply`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `poll_textreply` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`datetime` datetime NOT NULL,
|
||||
`pollid` int(11) NOT NULL,
|
||||
`ckey` varchar(32) NOT NULL,
|
||||
`ip` int(10) unsigned NOT NULL,
|
||||
`replytext` varchar(2048) NOT NULL,
|
||||
`adminrank` varchar(32) NOT NULL DEFAULT 'Player',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_ptext_pollid_ckey` (`pollid`,`ckey`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `poll_vote`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `poll_vote`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `poll_vote` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`datetime` datetime NOT NULL,
|
||||
`pollid` int(11) NOT NULL,
|
||||
`optionid` int(11) NOT NULL,
|
||||
`ckey` varchar(32) NOT NULL,
|
||||
`ip` int(10) unsigned NOT NULL,
|
||||
`adminrank` varchar(32) NOT NULL,
|
||||
`rating` int(2) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_pvote_pollid_ckey` (`pollid`,`ckey`),
|
||||
KEY `idx_pvote_optionid_ckey` (`optionid`,`ckey`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `round`
|
||||
--
|
||||
DROP TABLE IF EXISTS `round`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `round` (
|
||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`initialize_datetime` DATETIME NOT NULL,
|
||||
`start_datetime` DATETIME NULL,
|
||||
`shutdown_datetime` DATETIME NULL,
|
||||
`end_datetime` DATETIME NULL,
|
||||
`server_ip` INT(10) UNSIGNED NOT NULL,
|
||||
`server_port` SMALLINT(5) UNSIGNED NOT NULL,
|
||||
`commit_hash` CHAR(40) NULL,
|
||||
`game_mode` VARCHAR(32) NULL,
|
||||
`game_mode_result` VARCHAR(64) NULL,
|
||||
`end_state` VARCHAR(64) NULL,
|
||||
`shuttle_name` VARCHAR(64) NULL,
|
||||
`map_name` VARCHAR(32) NULL,
|
||||
`station_name` VARCHAR(80) NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||
|
||||
--
|
||||
-- Table structure for table `schema_revision`
|
||||
--
|
||||
DROP TABLE IF EXISTS `schema_revision`;
|
||||
CREATE TABLE `schema_revision` (
|
||||
`major` TINYINT(3) unsigned NOT NULL,
|
||||
`minor` TINYINT(3) unsigned NOT NULL,
|
||||
`date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`major`, `minor`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE TRIGGER `role_timeTlogupdate` AFTER UPDATE ON `role_time` FOR EACH ROW BEGIN INSERT into role_time_log (ckey, job, delta) VALUES (NEW.CKEY, NEW.job, NEW.minutes-OLD.minutes);
|
||||
END
|
||||
$$
|
||||
CREATE TRIGGER `role_timeTloginsert` AFTER INSERT ON `role_time` FOR EACH ROW BEGIN INSERT into role_time_log (ckey, job, delta) VALUES (NEW.ckey, NEW.job, NEW.minutes);
|
||||
END
|
||||
$$
|
||||
CREATE TRIGGER `role_timeTlogdelete` AFTER DELETE ON `role_time` FOR EACH ROW BEGIN INSERT into role_time_log (ckey, job, delta) VALUES (OLD.ckey, OLD.job, 0-OLD.minutes);
|
||||
END
|
||||
$$
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
{
|
||||
"documentation": "/tg/station server 3 configuration file",
|
||||
"changelog": {
|
||||
"script": "tools/ss13_genchangelog.py",
|
||||
"arguments": "html/changelog.html html/changelogs",
|
||||
"pip_dependancies": [
|
||||
"PyYaml",
|
||||
"beautifulsoup4"
|
||||
]
|
||||
},
|
||||
"synchronize_paths": [
|
||||
"html/changelog.html",
|
||||
"html/changelogs/*"
|
||||
],
|
||||
"static_directories": [
|
||||
"config",
|
||||
"data"
|
||||
],
|
||||
"dlls": [
|
||||
"libmariadb.dll"
|
||||
]
|
||||
}
|
||||
{
|
||||
"documentation": "/tg/station server 3 configuration file",
|
||||
"changelog": {
|
||||
"script": "tools/ss13_genchangelog.py",
|
||||
"arguments": "html/changelog.html html/changelogs",
|
||||
"pip_dependancies": [
|
||||
"PyYaml",
|
||||
"beautifulsoup4"
|
||||
]
|
||||
},
|
||||
"synchronize_paths": [
|
||||
"html/changelog.html",
|
||||
"html/changelogs/*"
|
||||
],
|
||||
"static_directories": [
|
||||
"config",
|
||||
"data"
|
||||
],
|
||||
"dlls": [
|
||||
"libmariadb.dll"
|
||||
]
|
||||
}
|
||||
|
||||
+11
-11
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"map_name": "Box Station",
|
||||
"map_path": "map_files/BoxStation",
|
||||
"map_file": "BoxStation.dmm",
|
||||
"shuttles": {
|
||||
"cargo": "cargo_box",
|
||||
"ferry": "ferry_fancy",
|
||||
"whiteship": "whiteship_box",
|
||||
"emergency": "emergency_box"
|
||||
}
|
||||
}
|
||||
{
|
||||
"map_name": "Box Station",
|
||||
"map_path": "map_files/BoxStation",
|
||||
"map_file": "BoxStation.dmm",
|
||||
"shuttles": {
|
||||
"cargo": "cargo_box",
|
||||
"ferry": "ferry_fancy",
|
||||
"whiteship": "whiteship_box",
|
||||
"emergency": "emergency_box"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -32964,6 +32964,10 @@
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/effect/decal/cleanable/oil,
|
||||
/obj/effect/turf_decal/bot,
|
||||
/obj/item/stack/ore/silver{
|
||||
amount = 2
|
||||
},
|
||||
/obj/item/stack/ore/iron,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/quartermaster/miningoffice)
|
||||
"biu" = (
|
||||
|
||||
@@ -19827,6 +19827,9 @@
|
||||
/obj/effect/turf_decal/stripes/line{
|
||||
dir = 8
|
||||
},
|
||||
/obj/item/stack/ore/silver{
|
||||
amount = 2
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
/area/quartermaster/miningoffice)
|
||||
"aJC" = (
|
||||
@@ -20222,6 +20225,7 @@
|
||||
/obj/effect/turf_decal/stripes/line{
|
||||
dir = 4
|
||||
},
|
||||
/obj/item/stack/ore/iron,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/quartermaster/miningoffice)
|
||||
"aKq" = (
|
||||
|
||||
@@ -807,6 +807,11 @@
|
||||
},
|
||||
/turf/open/floor/plasteel/cafeteria,
|
||||
/area/crew_quarters/fitness/pool)
|
||||
"abU" = (
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
|
||||
/obj/effect/landmark/xmastree,
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/crew_quarters/bar)
|
||||
"abV" = (
|
||||
/obj/effect/turf_decal/stripes/corner,
|
||||
/turf/open/floor/plasteel/white,
|
||||
@@ -824,6 +829,13 @@
|
||||
"abY" = (
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/ai_monitored/turret_protected/ai)
|
||||
"abZ" = (
|
||||
/obj/structure/flora/ausbushes/ywflowers,
|
||||
/obj/structure/flora/ausbushes/ppflowers,
|
||||
/obj/structure/flora/ausbushes/sparsegrass,
|
||||
/obj/effect/landmark/xmastree,
|
||||
/turf/open/floor/grass,
|
||||
/area/hydroponics/garden/monastery)
|
||||
"acc" = (
|
||||
/obj/effect/turf_decal/stripes/line{
|
||||
dir = 4
|
||||
@@ -47489,12 +47501,6 @@
|
||||
},
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/chapel/main/monastery)
|
||||
"cgj" = (
|
||||
/obj/structure/flora/ausbushes/ywflowers,
|
||||
/obj/structure/flora/ausbushes/ppflowers,
|
||||
/obj/structure/flora/ausbushes/sparsegrass,
|
||||
/turf/open/floor/grass,
|
||||
/area/hydroponics/garden/monastery)
|
||||
"cgk" = (
|
||||
/obj/structure/flora/ausbushes/ywflowers,
|
||||
/obj/structure/flora/ausbushes/sparsegrass,
|
||||
@@ -61209,6 +61215,14 @@
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/engineering)
|
||||
"vzp" = (
|
||||
/obj/effect/turf_decal/tile/brown,
|
||||
/obj/item/stack/ore/iron,
|
||||
/obj/item/stack/ore/silver{
|
||||
amount = 2
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
/area/quartermaster/miningdock)
|
||||
"vzz" = (
|
||||
/obj/machinery/door/firedoor,
|
||||
/obj/machinery/door/airlock/public/glass{
|
||||
@@ -79792,7 +79806,7 @@ cuE
|
||||
cgK
|
||||
cgJ
|
||||
cgH
|
||||
cgj
|
||||
abZ
|
||||
cvj
|
||||
bWV
|
||||
cfn
|
||||
@@ -94890,7 +94904,7 @@ aYg
|
||||
aZd
|
||||
beB
|
||||
bbq
|
||||
beB
|
||||
abU
|
||||
bdx
|
||||
beB
|
||||
bft
|
||||
@@ -103631,7 +103645,7 @@ bbI
|
||||
bcG
|
||||
bdM
|
||||
beP
|
||||
bfH
|
||||
vzp
|
||||
bfH
|
||||
bhv
|
||||
bbI
|
||||
@@ -110827,7 +110841,7 @@ bcQ
|
||||
aaa
|
||||
aaa
|
||||
aaa
|
||||
abN
|
||||
bBW
|
||||
aaa
|
||||
aEj
|
||||
aEj
|
||||
@@ -111084,7 +111098,7 @@ bcQ
|
||||
aaa
|
||||
aaa
|
||||
aaa
|
||||
aaa
|
||||
cFB
|
||||
aaa
|
||||
aEl
|
||||
bnl
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"map_name": "Runtime Station",
|
||||
"map_path": "map_files/debug",
|
||||
"map_file": "runtimestation.dmm",
|
||||
"shuttles": {
|
||||
"cargo": "cargo_delta"
|
||||
}
|
||||
}
|
||||
{
|
||||
"map_name": "Runtime Station",
|
||||
"map_path": "map_files/debug",
|
||||
"map_file": "runtimestation.dmm",
|
||||
"shuttles": {
|
||||
"cargo": "cargo_delta"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1560,6 +1560,7 @@
|
||||
/area/shuttle/abandoned/bridge)
|
||||
"cc" = (
|
||||
/obj/machinery/door/airlock/external,
|
||||
/obj/structure/fans/tiny,
|
||||
/obj/effect/mapping_helpers/airlock/cyclelink_helper{
|
||||
dir = 1
|
||||
},
|
||||
|
||||
+25
-25
@@ -1,25 +1,25 @@
|
||||
#!/usr/bin/env python3
|
||||
from config import *
|
||||
import sys
|
||||
import pickle
|
||||
import socket
|
||||
|
||||
|
||||
def pack():
|
||||
ip = sys.argv[1]
|
||||
try:
|
||||
data = sys.argv[2:]
|
||||
except:
|
||||
data = "NO DATA SPECIFIED"
|
||||
|
||||
nudge(pickle.dumps({"ip": ip, "data": data}))
|
||||
|
||||
|
||||
def nudge(data):
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect(("localhost", 45678))
|
||||
s.send(data)
|
||||
s.close()
|
||||
|
||||
if __name__ == "__main__" and len(sys.argv) > 1:
|
||||
pack()
|
||||
#!/usr/bin/env python3
|
||||
from config import *
|
||||
import sys
|
||||
import pickle
|
||||
import socket
|
||||
|
||||
|
||||
def pack():
|
||||
ip = sys.argv[1]
|
||||
try:
|
||||
data = sys.argv[2:]
|
||||
except:
|
||||
data = "NO DATA SPECIFIED"
|
||||
|
||||
nudge(pickle.dumps({"ip": ip, "data": data}))
|
||||
|
||||
|
||||
def nudge(data):
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect(("localhost", 45678))
|
||||
s.send(data)
|
||||
s.close()
|
||||
|
||||
if __name__ == "__main__" and len(sys.argv) > 1:
|
||||
pack()
|
||||
|
||||
@@ -35,8 +35,9 @@
|
||||
#define R_SPAWN (1<<12)
|
||||
#define R_AUTOLOGIN (1<<13)
|
||||
#define R_DBRANKS (1<<14)
|
||||
#define R_SENSITIVE (1<<15)
|
||||
|
||||
#define R_DEFAULT R_AUTOLOGIN
|
||||
#define R_DEFAULT R_AUTOLOGIN | R_SENSITIVE
|
||||
|
||||
#define R_EVERYTHING ALL //the sum of all other rank permissions, used for +EVERYTHING
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
#define MAX_HIGH_PRESSURE_DAMAGE 16 // CITADEL CHANGES Max to 16, low to 8.
|
||||
#define LOW_PRESSURE_DAMAGE 8 //The amount of damage someone takes when in a low pressure area (The pressure threshold is so low that it doesn't make sense to do any calculations, so it just applies this flat value).
|
||||
|
||||
#define COLD_SLOWDOWN_FACTOR 20 //Humans are slowed by the difference between bodytemp and BODYTEMP_COLD_DAMAGE_LIMIT divided by this
|
||||
#define COLD_SLOWDOWN_FACTOR 35 //Humans are slowed by the difference between bodytemp and BODYTEMP_COLD_DAMAGE_LIMIT divided by this
|
||||
|
||||
//PIPES
|
||||
//Atmos pipe limits
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
//#define ROLE_MONSTERHUNTER "monster hunter" Disabled for now
|
||||
#define ROLE_GHOSTCAFE "ghostcafe"
|
||||
#define ROLE_MINOR_ANTAG "minorantag"
|
||||
#define ROLE_RESPAWN "respawnsystem"
|
||||
//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR.
|
||||
//The gamemode specific ones are just so the gamemodes can query whether a player is old enough
|
||||
//(in game days played) to play that role
|
||||
|
||||
+10
-10
@@ -1,6 +1,6 @@
|
||||
// tgstation-server DMAPI
|
||||
|
||||
#define TGS_DMAPI_VERSION "5.2.9"
|
||||
#define TGS_DMAPI_VERSION "5.2.10"
|
||||
|
||||
// All functions and datums outside this document are subject to change with any version and should not be relied on.
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
#define TGS_EVENT_REPO_CHECKOUT 1
|
||||
/// When the repository performs a fetch operation. No parameters
|
||||
#define TGS_EVENT_REPO_FETCH 2
|
||||
/// When the repository merges a pull request. Parameters: PR Number, PR Sha, (Nullable) Comment made by TGS user
|
||||
/// When the repository test merges. Parameters: PR Number, PR Sha, (Nullable) Comment made by TGS user
|
||||
#define TGS_EVENT_REPO_MERGE_PULL_REQUEST 3
|
||||
/// Before the repository makes a sychronize operation. Parameters: Absolute repostiory path
|
||||
#define TGS_EVENT_REPO_PRE_SYNCHRONIZE 4
|
||||
@@ -190,21 +190,21 @@
|
||||
|
||||
/// Represents a merge of a GitHub pull request.
|
||||
/datum/tgs_revision_information/test_merge
|
||||
/// The pull request number.
|
||||
/// The test merge number.
|
||||
var/number
|
||||
/// The pull request title when it was merged.
|
||||
/// The test merge source's title when it was merged.
|
||||
var/title
|
||||
/// The pull request body when it was merged.
|
||||
/// The test merge source's body when it was merged.
|
||||
var/body
|
||||
/// The GitHub username of the pull request's author.
|
||||
/// The Username of the test merge source's author.
|
||||
var/author
|
||||
/// An http URL to the pull request.
|
||||
/// An http URL to the test merge source.
|
||||
var/url
|
||||
/// The SHA of the pull request when that was merged.
|
||||
/// The SHA of the test merge when that was merged.
|
||||
var/pull_request_commit
|
||||
/// ISO 8601 timestamp of when the pull request was merged.
|
||||
/// ISO 8601 timestamp of when the test merge was created on TGS.
|
||||
var/time_merged
|
||||
/// (Nullable) Comment left by the TGS user who initiated the merge..
|
||||
/// Optional comment left by the TGS user who initiated the merge.
|
||||
var/comment
|
||||
|
||||
/// Represents a connected chat channel.
|
||||
|
||||
@@ -225,6 +225,8 @@
|
||||
. += "[seperator]AUTOLOGIN"
|
||||
if(rights & R_DBRANKS)
|
||||
. += "[seperator]DBRANKS"
|
||||
if(rights & R_SENSITIVE)
|
||||
. += "[seperator]SENSITIVE"
|
||||
if(!.)
|
||||
. = "NONE"
|
||||
return .
|
||||
|
||||
@@ -67,7 +67,8 @@ GLOBAL_LIST_INIT(bitfields, list(
|
||||
"SOUNDS" = R_SOUNDS,
|
||||
"SPAWN" = R_SPAWN,
|
||||
"AUTOLOGIN" = R_AUTOLOGIN,
|
||||
"DBRANKS" = R_DBRANKS
|
||||
"DBRANKS" = R_DBRANKS,
|
||||
"SENSITIVE" = R_SENSITIVE
|
||||
),
|
||||
"interaction_flags_atom" = list(
|
||||
"INTERACT_ATOM_REQUIRES_ANCHORED" = INTERACT_ATOM_REQUIRES_ANCHORED,
|
||||
|
||||
@@ -172,8 +172,6 @@
|
||||
|
||||
/datum/config_entry/string/hostedby
|
||||
|
||||
/datum/config_entry/flag/norespawn
|
||||
|
||||
/datum/config_entry/flag/guest_jobban
|
||||
|
||||
/datum/config_entry/flag/usewhitelist
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/// Allows usage of respawn system
|
||||
/datum/config_entry/flag/respawns_enabled
|
||||
config_entry_value = FALSE
|
||||
|
||||
/// Minutes before allowing respawns.
|
||||
/datum/config_entry/number/respawn_delay
|
||||
config_entry_value = 15.0
|
||||
integer = FALSE
|
||||
|
||||
/// Minutes before allowing respawn, if user cryo'd.
|
||||
/datum/config_entry/number/respawn_delay_cryo
|
||||
config_entry_value = 5.0
|
||||
integer = FALSE
|
||||
|
||||
/// Allows respawning as non-assistant. Overrides all others of this type.
|
||||
/datum/config_entry/flag/allow_non_assistant_respawn
|
||||
config_entry_value = FALSE
|
||||
|
||||
/// Allows respawning as a combat role, defined as security/head.
|
||||
/datum/config_entry/flag/allow_combat_role_respawn
|
||||
config_entry_value = FALSE
|
||||
|
||||
/// Allows respawning as the same character as a previous life
|
||||
/datum/config_entry/flag/allow_same_character_respawn
|
||||
config_entry_value = FALSE
|
||||
|
||||
/// Observing penalizes for respawns, not just joining.
|
||||
/datum/config_entry/flag/respawn_penalty_includes_observe
|
||||
config_entry_value = FALSE
|
||||
|
||||
/// Minutes from roundstart before someone can respawn
|
||||
/datum/config_entry/number/respawn_minimum_delay_roundstart
|
||||
config_entry_value = 30.0
|
||||
integer = FALSE
|
||||
|
||||
/// Gamemode config tags that are banned from respawning
|
||||
/datum/config_entry/keyed_list/respawn_chaos_gamemodes
|
||||
key_mode = KEY_MODE_TEXT
|
||||
value_mode = VALUE_MODE_FLAG
|
||||
|
||||
/datum/config_entry/keyed_list/respawn_chaos_gamemodes/ValidateListEntry(key_name, key_value)
|
||||
. = ..()
|
||||
return . && (key_name in config.modes)
|
||||
|
||||
/datum/config_entry/keyed_list/respawn_chaos_gamemodes/preprocess_key(key)
|
||||
. = ..()
|
||||
return lowertext(key)
|
||||
@@ -93,6 +93,7 @@ SUBSYSTEM_DEF(input)
|
||||
user.full_macro_assert()
|
||||
|
||||
/datum/controller/subsystem/input/fire()
|
||||
set waitfor = FALSE
|
||||
var/list/clients = GLOB.clients // Let's sing the list cache song
|
||||
for(var/i in 1 to clients.len)
|
||||
var/client/C = clients[i]
|
||||
|
||||
@@ -371,6 +371,11 @@ SUBSYSTEM_DEF(ticker)
|
||||
if(player.ready == PLAYER_READY_TO_PLAY && player.mind)
|
||||
GLOB.joined_player_list += player.ckey
|
||||
player.create_character(FALSE)
|
||||
if(player.new_character && player.client && player.client.prefs) // we cannot afford a runtime, ever
|
||||
LAZYOR(player.client.prefs.slots_joined_as, player.client.prefs.default_slot)
|
||||
LAZYOR(player.client.prefs.characters_joined_as, player.new_character.real_name)
|
||||
else
|
||||
stack_trace("WARNING: Either a player did not have a new_character, did not have a client, or did not have preferences. This is VERY bad.")
|
||||
else
|
||||
player.new_player_panel()
|
||||
CHECK_TICK
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Datum Component System (DCS)
|
||||
|
||||
## Concept
|
||||
|
||||
Loosely adapted from /vg/. This is an entity component system for adding behaviours to datums when inheritance doesn't quite cut it. By using signals and events instead of direct inheritance, you can inject behaviours without hacky overloads. It requires a different method of thinking, but is not hard to use correctly. If a behaviour can have application across more than one thing. Make it generic, make it a component. Atom/mob/obj event? Give it a signal, and forward it's arguments with a `SendSignal()` call. Now every component that want's to can also know about this happening.
|
||||
|
||||
See [this thread](https://tgstation13.org/phpBB/viewtopic.php?f=5&t=22674) for an introduction to the system as a whole.
|
||||
|
||||
### See/Define signals and their arguments in [__DEFINES\components.dm](..\..\__DEFINES\components.dm)
|
||||
# Datum Component System (DCS)
|
||||
|
||||
## Concept
|
||||
|
||||
Loosely adapted from /vg/. This is an entity component system for adding behaviours to datums when inheritance doesn't quite cut it. By using signals and events instead of direct inheritance, you can inject behaviours without hacky overloads. It requires a different method of thinking, but is not hard to use correctly. If a behaviour can have application across more than one thing. Make it generic, make it a component. Atom/mob/obj event? Give it a signal, and forward it's arguments with a `SendSignal()` call. Now every component that want's to can also know about this happening.
|
||||
|
||||
See [this thread](https://tgstation13.org/phpBB/viewtopic.php?f=5&t=22674) for an introduction to the system as a whole.
|
||||
|
||||
### See/Define signals and their arguments in [__DEFINES\components.dm](..\..\__DEFINES\components.dm)
|
||||
|
||||
@@ -89,6 +89,11 @@
|
||||
to_chat(user, "<span class='warning'>You can't tackle while tased!</span>")
|
||||
return
|
||||
|
||||
var/left_paralysis = HAS_TRAIT(user, TRAIT_PARALYSIS_L_ARM)
|
||||
var/right_paralysis = HAS_TRAIT(user, TRAIT_PARALYSIS_R_ARM)
|
||||
if(left_paralysis && right_paralysis)
|
||||
to_chat(user, "<span class='warning'>You can't tackle without the use of your arms!</span>")
|
||||
|
||||
user.face_atom(A)
|
||||
|
||||
var/list/modifiers = params2list(params)
|
||||
@@ -280,6 +285,10 @@
|
||||
attack_mod -= 2
|
||||
if(HAS_TRAIT(sacker, TRAIT_GIANT))
|
||||
attack_mod += 2
|
||||
var/left_paralysis = HAS_TRAIT(sacker, TRAIT_PARALYSIS_L_ARM)
|
||||
var/right_paralysis = HAS_TRAIT(sacker, TRAIT_PARALYSIS_R_ARM)
|
||||
if(left_paralysis || right_paralysis)
|
||||
attack_mod -= 2
|
||||
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/S = sacker
|
||||
|
||||
@@ -31,9 +31,8 @@ Bonus
|
||||
var/bleed = FALSE
|
||||
var/pain = FALSE
|
||||
threshold_desc = list(
|
||||
"Resistance 9" = "Doubles the intensity of the immolation effect, but reduces the frequency of all of this symptom's effects.",
|
||||
"Stage Speed 8" = "Increases explosion radius and explosion damage to the host when the host is wet.",
|
||||
"Transmission 8" = "Additionally synthesizes chlorine trifluoride and napalm inside the host. More chemicals are synthesized if the resistance 9 threshold has been met."
|
||||
"Resistance 7" = "Erodes the host's skin, causing them to bleed profusely.",
|
||||
"Transmission 8" = "Eat's away at the host's musclemass, causing increased fatigue."
|
||||
)
|
||||
|
||||
/datum/symptom/flesh_eating/Start(datum/disease/advance/A)
|
||||
|
||||
@@ -263,18 +263,18 @@
|
||||
|
||||
/datum/symptom/heal/coma/CanHeal(datum/disease/advance/A)
|
||||
var/mob/living/M = A.affected_mob
|
||||
if(M.getBruteLoss() + M.getFireLoss() >= 70 && !active_coma)
|
||||
to_chat(M, "<span class='warning'>You feel yourself slip into a regenerative coma...</span>")
|
||||
active_coma = TRUE
|
||||
addtimer(CALLBACK(src, .proc/coma, M), 60)
|
||||
if(HAS_TRAIT(M, TRAIT_DEATHCOMA))
|
||||
return power
|
||||
else if(M.IsUnconscious() || M.stat == UNCONSCIOUS)
|
||||
return power * 0.9
|
||||
else if(M.stat == SOFT_CRIT)
|
||||
return power * 0.5
|
||||
else if(M.IsSleeping())
|
||||
return power * 0.25
|
||||
else if(M.getBruteLoss() + M.getFireLoss() >= 70 && !active_coma)
|
||||
to_chat(M, "<span class='warning'>You feel yourself slip into a regenerative coma...</span>")
|
||||
active_coma = TRUE
|
||||
addtimer(CALLBACK(src, .proc/coma, M), 60)
|
||||
else if(M.IsUnconscious() || M.stat == UNCONSCIOUS)
|
||||
return power * 0.9
|
||||
|
||||
/datum/symptom/heal/coma/proc/coma(mob/living/M)
|
||||
if(deathgasp)
|
||||
|
||||
@@ -13,6 +13,8 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
|
||||
var/save_key
|
||||
/// Do not attempt to render a preview on examine. If this is on, it will display as \[flavor_name\]
|
||||
var/examine_no_preview = FALSE
|
||||
/// Examine FULLY views. Overrides examine_no_preview
|
||||
var/examine_full_view = FALSE
|
||||
|
||||
/datum/element/flavor_text/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FLAVOR_LEN, _always_show = FALSE, _edit = TRUE, _save_key, _examine_no_preview = FALSE)
|
||||
. = ..()
|
||||
@@ -37,7 +39,7 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
|
||||
if(can_edit && ismob(target)) //but only mobs receive the proc/verb for the time being
|
||||
var/mob/M = target
|
||||
LAZYOR(GLOB.mobs_with_editable_flavor_text[M], src)
|
||||
M.verbs |= /mob/proc/manage_flavor_tests
|
||||
add_verb(M, /mob/proc/manage_flavor_tests)
|
||||
|
||||
if(save_key && ishuman(target))
|
||||
RegisterSignal(target, COMSIG_HUMAN_PREFS_COPIED_TO, .proc/update_prefs_flavor_text)
|
||||
@@ -71,6 +73,9 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
|
||||
examine_list += "<span class='notice'><a href='?src=[REF(src)];show_flavor=[REF(target)]'>\[[flavor_name]\]</a></span>"
|
||||
return
|
||||
var/msg = replacetext(text, "\n", " ")
|
||||
if(examine_full_view)
|
||||
examine_list += "[msg]"
|
||||
return
|
||||
if(length_char(msg) <= 40)
|
||||
examine_list += "<span class='notice'>[msg]</span>"
|
||||
else
|
||||
@@ -113,6 +118,21 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
|
||||
var/datum/element/flavor_text/F = choices[chosen]
|
||||
F.set_flavor(src)
|
||||
|
||||
/mob/proc/set_pose()
|
||||
set name = "Set Pose"
|
||||
set desc = "Sets your temporary flavor text"
|
||||
set category = "IC"
|
||||
|
||||
var/list/L = GLOB.mobs_with_editable_flavor_text[src]
|
||||
var/datum/element/flavor_text/carbon/temporary/T
|
||||
for(var/i in L)
|
||||
if(istype(i, /datum/element/flavor_text/carbon/temporary))
|
||||
T = i
|
||||
if(!T)
|
||||
to_chat(src, "<span class='warning'>Your mob type does not support temporary flavor text.</span>")
|
||||
return
|
||||
T.set_flavor(src)
|
||||
|
||||
/datum/element/flavor_text/proc/set_flavor(mob/user)
|
||||
if(!(user in texts_by_atom))
|
||||
return FALSE
|
||||
@@ -135,7 +155,7 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
|
||||
var/static/list/i_dont_even_know_who_you_are = typecacheof(list(/datum/antagonist/abductor, /datum/antagonist/ert,
|
||||
/datum/antagonist/nukeop, /datum/antagonist/wizard))
|
||||
|
||||
/datum/element/flavor_text/carbon/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FLAVOR_LEN, _always_show = FALSE, _edit = TRUE, _save_key = "flavor_text", _examine_no_preview = FALSE)
|
||||
/datum/element/flavor_text/carbon/Attach(datum/target, text = "", _name = "Flavor Text", _addendum, _max_len = MAX_FLAVOR_LEN, _always_show = FALSE, _edit = TRUE, _save_key, _examine_no_preview = FALSE)
|
||||
if(!iscarbon(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
. = ..()
|
||||
@@ -167,3 +187,19 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
|
||||
texts_by_atom[user] = ""
|
||||
if(user.dna)
|
||||
user.dna.features[save_key] = ""
|
||||
|
||||
/datum/element/flavor_text/carbon/temporary
|
||||
examine_full_view = TRUE
|
||||
max_len = 1024
|
||||
|
||||
/datum/element/flavor_text/carbon/temporary/Attach(datum/target, text, _name, _addendum, _max_len, _always_show, _edit, _save_key, _examine_no_preview)
|
||||
. = ..()
|
||||
if(. & ELEMENT_INCOMPATIBLE)
|
||||
return
|
||||
if(ismob(target))
|
||||
add_verb(target, /mob/proc/set_pose)
|
||||
|
||||
/datum/element/flavor_Text/carbon/temporary/Detach(datum/source, force)
|
||||
. = ..()
|
||||
if(ismob(source))
|
||||
remove_verb(source, /mob/proc/set_pose)
|
||||
|
||||
@@ -438,12 +438,19 @@
|
||||
return
|
||||
else
|
||||
linked_alert.icon_state = "fleshmend"
|
||||
owner.adjustBruteLoss(-10, FALSE)
|
||||
owner.adjustFireLoss(-5, FALSE)
|
||||
owner.adjustOxyLoss(-10)
|
||||
if(!iscarbon(owner))
|
||||
owner.adjustBruteLoss(-10, FALSE)
|
||||
owner.adjustFireLoss(-5, FALSE)
|
||||
return
|
||||
var/mob/living/carbon/C = owner
|
||||
var/list/damaged_parts = C.get_damaged_bodyparts(TRUE,TRUE, status = list(BODYPART_ORGANIC, BODYPART_HYBRID, BODYPART_NANITES))
|
||||
if(damaged_parts.len)
|
||||
for(var/obj/item/bodypart/part in damaged_parts)
|
||||
part.heal_damage(10/damaged_parts.len, 5/damaged_parts.len, only_organic = FALSE, updating_health = FALSE)
|
||||
C.updatehealth()
|
||||
C.update_damage_overlays()
|
||||
|
||||
QDEL_LIST(C.all_scars)
|
||||
|
||||
/obj/screen/alert/status_effect/fleshmend
|
||||
@@ -599,7 +606,7 @@
|
||||
|
||||
//Heal brain damage and toxyloss, alongside trauma
|
||||
owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, -8)
|
||||
owner.adjustToxLoss(-6, forced = TRUE)
|
||||
owner.adjustToxLoss(-6, forced = TRUE, toxins_type = TOX_OMNI)
|
||||
M.cure_trauma_type(resilience = TRAUMA_RESILIENCE_BASIC)
|
||||
//Purges 50 rads per tick
|
||||
if(owner.radiation > 0)
|
||||
|
||||
@@ -137,12 +137,18 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
|
||||
var/lums = T.get_lumcount()
|
||||
if(lums <= 0.2)
|
||||
if(quirk_holder.m_intent == MOVE_INTENT_RUN)
|
||||
to_chat(quirk_holder, "<span class='warning'>Easy, easy, take it slow... you're in the dark...</span>")
|
||||
quirk_holder.toggle_move_intent()
|
||||
addtimer(CALLBACK(src, .proc/recheck),2) //0.2 seconds of being in the dark
|
||||
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "nyctophobia", /datum/mood_event/nyctophobia)
|
||||
else
|
||||
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "nyctophobia")
|
||||
|
||||
/datum/quirk/nyctophobia/proc/recheck()
|
||||
var/turf/T = get_turf(quirk_holder)
|
||||
var/lums = T.get_lumcount()
|
||||
if(lums <= 0.2) //check again, did they remain in the dark for 0.2 seconds?
|
||||
to_chat(quirk_holder, "<span class='warning'>Easy, easy, take it slow... you're in the dark...</span>")
|
||||
quirk_holder.toggle_move_intent()
|
||||
|
||||
/datum/quirk/lightless
|
||||
name = "Light Sensitivity"
|
||||
desc = "Bright lights irritate you. Your eyes start to water, your skin feels itchy against the photon radiation, and your hair gets dry and frizzy. Maybe it's a medical condition. If only Nanotrasen was more considerate of your needs..."
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
. = list()
|
||||
.["version"] = GLOB.game_version
|
||||
.["mode"] = "hidden" //CIT CHANGE - hides the gamemode in topic() calls to prevent meta'ing the gamemode
|
||||
.["respawn"] = config ? !CONFIG_GET(flag/norespawn) : FALSE
|
||||
.["respawn"] = config ? CONFIG_GET(flag/respawns_enabled) : FALSE
|
||||
.["enter"] = GLOB.enter_allowed
|
||||
.["vote"] = CONFIG_GET(flag/allow_vote_mode)
|
||||
.["ai"] = CONFIG_GET(flag/allow_ai)
|
||||
|
||||
@@ -1143,21 +1143,3 @@
|
||||
*/
|
||||
/atom/proc/setClosed()
|
||||
return
|
||||
|
||||
///Passes Stat Browser Panel clicks to the game and calls client click on an atom
|
||||
/atom/Topic(href, list/href_list)
|
||||
. = ..()
|
||||
if(!usr?.client)
|
||||
return
|
||||
var/client/usr_client = usr.client
|
||||
var/list/paramslist = list()
|
||||
if(href_list["statpanel_item_shiftclick"])
|
||||
paramslist["shift"] = "1"
|
||||
if(href_list["statpanel_item_ctrlclick"])
|
||||
paramslist["ctrl"] = "1"
|
||||
if(href_list["statpanel_item_altclick"])
|
||||
paramslist["alt"] = "1"
|
||||
if(href_list["statpanel_item_click"])
|
||||
// first of all make sure we valid
|
||||
var/mouseparams = list2params(paramslist)
|
||||
usr_client.Click(src, loc, null, mouseparams)
|
||||
|
||||
@@ -150,14 +150,14 @@ Credit where due:
|
||||
var/datum/team/clockcult/main_clockcult
|
||||
|
||||
/datum/game_mode/clockwork_cult/pre_setup() //Gamemode and job code is pain. Have fun codediving all of that stuff, whoever works on this next - Delta
|
||||
var/list/errorList = list()
|
||||
/*var/list/errorList = list()
|
||||
var/list/reebes = SSmapping.LoadGroup(errorList, "Reebe", "map_files/generic", "City_of_Cogs.dmm", default_traits = ZTRAITS_REEBE, silent = TRUE)
|
||||
if(errorList.len) // reebe failed to load
|
||||
message_admins("Reebe failed to load!")
|
||||
log_game("Reebe failed to load!")
|
||||
return FALSE
|
||||
for(var/datum/parsed_map/PM in reebes)
|
||||
PM.initTemplateBounds()
|
||||
for(var/datum/parsed_map/PM in reebes) //Temporarily commented because of z-level loading reliably segfaulting the server.
|
||||
PM.initTemplateBounds()*/
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
|
||||
+104
-123
@@ -22,17 +22,16 @@
|
||||
|
||||
//Used for logging people entering cryosleep and important items they are carrying.
|
||||
var/list/frozen_crew = list()
|
||||
var/list/frozen_items = list()
|
||||
|
||||
// Used for containing rare items traitors need to steal, so it's not
|
||||
// game-over if they get iced
|
||||
var/list/objective_items = list()
|
||||
// A cache of theft datums so you don't have to re-create them for
|
||||
// each item check
|
||||
var/list/theft_cache = list()
|
||||
var/list/obj/stored_packages = list()
|
||||
|
||||
var/allow_items = TRUE
|
||||
|
||||
/obj/machinery/computer/cryopod/deconstruct()
|
||||
. = ..()
|
||||
for(var/i in stored_packages)
|
||||
var/obj/O = i
|
||||
O.forceMove(drop_location())
|
||||
|
||||
/obj/machinery/computer/cryopod/attack_ai()
|
||||
attack_hand()
|
||||
|
||||
@@ -67,11 +66,11 @@
|
||||
if(3)
|
||||
dat += "<a href='byond://?src=[REF(src)];menu=1'><< Back</a><br><br>"
|
||||
dat += "<h3>Recently stored objects</h3><br/><hr/><br/>"
|
||||
if(!frozen_items.len)
|
||||
if(!stored_packages.len)
|
||||
dat += "There has been no storage usage at this terminal.<br/>"
|
||||
else
|
||||
for(var/obj/item/I in frozen_items)
|
||||
dat += "[I.name]<br/>"
|
||||
for(var/obj/O in stored_packages)
|
||||
dat += "[O.name]<br/>"
|
||||
dat += "<hr/>"
|
||||
|
||||
var/datum/browser/popup = new(user, "cryopod_console", "Cryogenic System Control")
|
||||
@@ -87,25 +86,27 @@
|
||||
add_fingerprint(user)
|
||||
|
||||
if(href_list["item"])
|
||||
if(!allowed(user))
|
||||
if(!allowed(user) && !(obj_flags & EMAGGED))
|
||||
to_chat(user, "<span class='warning'>Access Denied.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(!allow_items) return
|
||||
|
||||
if(frozen_items.len == 0)
|
||||
if(!allow_items)
|
||||
return
|
||||
|
||||
if(stored_packages.len == 0)
|
||||
to_chat(user, "<span class='notice'>There is nothing to recover from storage.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
var/obj/item/I = input(user, "Please choose which object to retrieve.","Object recovery",null) as null|anything in frozen_items
|
||||
var/obj/I = input(user, "Please choose which object to retrieve.","Object recovery",null) as null|anything in stored_packages
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
if(!I)
|
||||
return
|
||||
|
||||
if(!(I in frozen_items))
|
||||
if(!(I in stored_packages))
|
||||
to_chat(user, "<span class='notice'>\The [I] is no longer in storage.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
@@ -117,20 +118,21 @@
|
||||
I.forceMove(drop_location())
|
||||
if(user && Adjacent(user) && user.can_hold_items())
|
||||
user.put_in_hands(I)
|
||||
frozen_items -= I
|
||||
stored_packages -= I
|
||||
updateUsrDialog()
|
||||
|
||||
else if(href_list["allitems"])
|
||||
playsound(src, "terminal_type", 25, 0)
|
||||
if(!allowed(user))
|
||||
if(!allowed(user) && !(obj_flags & EMAGGED))
|
||||
to_chat(user, "<span class='warning'>Access Denied.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
if(!allow_items)
|
||||
return
|
||||
|
||||
if(frozen_items.len == 0)
|
||||
if(stored_packages.len == 0)
|
||||
to_chat(user, "<span class='notice'>There is nothing to recover from storage.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
return
|
||||
@@ -138,10 +140,10 @@
|
||||
visible_message("<span class='notice'>The console beeps happily as it disgorges the desired objects.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
for(var/obj/item/I in frozen_items)
|
||||
I.forceMove(drop_location())
|
||||
frozen_items -= I
|
||||
updateUsrDialog()
|
||||
for(var/obj/O in stored_packages)
|
||||
O.forceMove(get_turf(src))
|
||||
stored_packages.Cut()
|
||||
updateUsrDialog()
|
||||
|
||||
else if (href_list["menu"])
|
||||
src.menu = text2num(href_list["menu"])
|
||||
@@ -159,6 +161,13 @@
|
||||
/obj/machinery/computer/cryopod/contents_explosion()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/cryopod/contents_explosion()
|
||||
return //don't blow everyone's shit up.
|
||||
|
||||
/// The box
|
||||
/obj/item/storage/box/blue/cryostorage_items
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
|
||||
//Cryopods themselves.
|
||||
/obj/machinery/cryopod
|
||||
name = "cryogenic freezer"
|
||||
@@ -177,44 +186,9 @@
|
||||
var/despawn_world_time = null // Used to keep track of the safe period.
|
||||
|
||||
var/obj/machinery/computer/cryopod/control_computer
|
||||
var/item_storage_type = /obj/item/storage/box/blue/cryostorage_items //with how storage components work this can be anything the player can open or anything with a storage component.
|
||||
var/last_no_computer_message = 0
|
||||
|
||||
// These items are preserved when the process() despawn proc occurs.
|
||||
var/static/list/preserve_items = typecacheof(list(
|
||||
/obj/item/hand_tele,
|
||||
/obj/item/card/id/captains_spare,
|
||||
/obj/item/aicard,
|
||||
/obj/item/mmi,
|
||||
/obj/item/paicard,
|
||||
/obj/item/gun,
|
||||
/obj/item/pinpointer,
|
||||
/obj/item/clothing/shoes/magboots,
|
||||
/obj/item/areaeditor/blueprints,
|
||||
/obj/item/clothing/head/helmet/space,
|
||||
/obj/item/clothing/suit/space,
|
||||
/obj/item/clothing/suit/armor,
|
||||
/obj/item/defibrillator/compact,
|
||||
/obj/item/reagent_containers/hypospray/CMO,
|
||||
/obj/item/clothing/accessory/medal/gold/captain,
|
||||
/obj/item/clothing/gloves/krav_maga,
|
||||
/obj/item/nullrod,
|
||||
/obj/item/tank/jetpack,
|
||||
/obj/item/documents,
|
||||
/obj/item/nuke_core_container
|
||||
))
|
||||
// These items will NOT be preserved
|
||||
var/static/list/do_not_preserve_items = typecacheof(list(
|
||||
/obj/item/mmi/posibrain,
|
||||
/obj/item/gun/energy/laser/mounted,
|
||||
/obj/item/gun/energy/e_gun/advtaser/mounted,
|
||||
/obj/item/gun/ballistic/revolver/grenadelauncher/cyborg,
|
||||
/obj/item/gun/energy/disabler/cyborg,
|
||||
/obj/item/gun/energy/e_gun/advtaser/cyborg,
|
||||
/obj/item/gun/energy/printer,
|
||||
/obj/item/gun/energy/kinetic_accelerator/cyborg,
|
||||
/obj/item/gun/energy/laser/cyborg
|
||||
))
|
||||
|
||||
/obj/machinery/cryopod/Initialize(mapload)
|
||||
. = ..()
|
||||
update_icon()
|
||||
@@ -286,73 +260,89 @@
|
||||
|
||||
despawn_occupant()
|
||||
|
||||
#define CRYO_DESTROY 0
|
||||
#define CRYO_PRESERVE 1
|
||||
#define CRYO_OBJECTIVE 2
|
||||
#define CRYO_IGNORE 3
|
||||
#define CRYO_DESTROY_LATER 4
|
||||
|
||||
/obj/machinery/cryopod/proc/should_preserve_item(obj/item/I)
|
||||
for(var/datum/objective_item/steal/T in control_computer.theft_cache)
|
||||
if(istype(I, T.targetitem) && T.check_special_completion(I))
|
||||
return CRYO_OBJECTIVE
|
||||
if(preserve_items[I] && !do_not_preserve_items[I])
|
||||
return CRYO_PRESERVE
|
||||
return CRYO_DESTROY
|
||||
|
||||
// This function can not be undone; do not call this unless you are sure
|
||||
/obj/machinery/cryopod/proc/despawn_occupant()
|
||||
if(!control_computer)
|
||||
find_control_computer()
|
||||
|
||||
var/mob/living/mob_occupant = occupant
|
||||
var/list/obj/item/cryo_items = list()
|
||||
|
||||
var/list/obj/item/storing = list()
|
||||
var/list/obj/item/destroying = list()
|
||||
var/list/obj/item/destroy_later = list()
|
||||
|
||||
investigate_log("Despawning [key_name(mob_occupant)].", INVESTIGATE_CRYOGENICS)
|
||||
|
||||
//Handle Borg stuff first
|
||||
var/atom/target_store = (control_computer?.allow_items && control_computer) || src //the double control computer check makes it return the control computer.
|
||||
var/drop_to_ground = !istype(target_store, /obj/machinery/computer/cryopod)
|
||||
|
||||
var/mind_identity = mob_occupant.mind?.name
|
||||
var/occupant_identity = mob_occupant.real_name
|
||||
|
||||
if(iscyborg(mob_occupant))
|
||||
var/mob/living/silicon/robot/R = mob_occupant
|
||||
if(R.mmi?.brain)
|
||||
cryo_items[R.mmi] = CRYO_DESTROY_LATER
|
||||
cryo_items[R.mmi.brain] = CRYO_DESTROY_LATER
|
||||
for(var/obj/item/I in R.module) // the tools the borg has; metal, glass, guns etc
|
||||
for(var/obj/item/O in I) // the things inside the tools, if anything; mainly for janiborg trash bags
|
||||
cryo_items[O] = should_preserve_item(O)
|
||||
O.forceMove(src)
|
||||
R.module.remove_module(I, TRUE) //delete the module itself so it doesn't transfer over.
|
||||
|
||||
//Drop all items into the pod.
|
||||
for(var/obj/item/I in mob_occupant)
|
||||
if(cryo_items[I] == CRYO_IGNORE || cryo_items[I] ==CRYO_DESTROY_LATER)
|
||||
continue
|
||||
cryo_items[I] = should_preserve_item(I)
|
||||
mob_occupant.transferItemToLoc(I, src, TRUE)
|
||||
if(I.contents.len) //Make sure we catch anything not handled by qdel() on the items.
|
||||
if(cryo_items[I] != CRYO_DESTROY) // Don't remove the contents of things that need preservation
|
||||
destroy_later += R.mmi
|
||||
destroy_later += R.mmi.brain
|
||||
for(var/i in R.module)
|
||||
if(!isitem(i))
|
||||
destroying += i
|
||||
continue
|
||||
for(var/obj/item/O in I.contents)
|
||||
cryo_items[O] = should_preserve_item(O)
|
||||
O.forceMove(src)
|
||||
|
||||
for(var/A in cryo_items)
|
||||
var/obj/item/I = A
|
||||
if(QDELETED(I)) //edge cases and DROPDEL.
|
||||
continue
|
||||
var/preserve = cryo_items[I]
|
||||
if(preserve == CRYO_DESTROY_LATER)
|
||||
continue
|
||||
if(preserve != CRYO_IGNORE)
|
||||
if(preserve == CRYO_DESTROY)
|
||||
qdel(I)
|
||||
else if(control_computer?.allow_items)
|
||||
control_computer.frozen_items += I
|
||||
if(preserve == CRYO_OBJECTIVE)
|
||||
control_computer.objective_items += I
|
||||
I.moveToNullspace()
|
||||
var/obj/item/I = i
|
||||
// let's be honest we only care about the trash bag don't beat around the bush
|
||||
if(SEND_SIGNAL(I, COMSIG_CONTAINS_STORAGE))
|
||||
storing += I.contents
|
||||
for(var/atom/movable/AM in I.contents)
|
||||
AM.forceMove(src)
|
||||
R.module.remove_module(I, TRUE)
|
||||
else
|
||||
var/list/gear = list()
|
||||
if(iscarbon(mob_occupant)) // sorry simp-le-mobs deserve no mercy
|
||||
var/mob/living/carbon/C = mob_occupant
|
||||
gear = C.get_all_gear()
|
||||
for(var/i in gear)
|
||||
var/obj/item/I = i
|
||||
I.forceMove(src)
|
||||
if(!istype(I))
|
||||
destroying += I
|
||||
continue
|
||||
if(I.item_flags & (DROPDEL | ABSTRACT))
|
||||
destroying += I
|
||||
continue
|
||||
if(HAS_TRAIT(I, TRAIT_NODROP))
|
||||
destroying += I
|
||||
continue
|
||||
// WEE WOO SNOWFLAKE TIME
|
||||
if(istype(I, /obj/item/pda))
|
||||
var/obj/item/pda/P = I
|
||||
if((P.owner == mind_identity) || (P.owner == occupant_identity))
|
||||
destroying += P
|
||||
else
|
||||
storing += P
|
||||
else if(istype(I, /obj/item/card/id))
|
||||
var/obj/item/card/id/idcard = I
|
||||
if((idcard.registered_name == mind_identity) || (idcard.registered_name == occupant_identity))
|
||||
destroying += idcard
|
||||
else
|
||||
storing += idcard
|
||||
else
|
||||
I.forceMove(loc)
|
||||
cryo_items -= I
|
||||
storing += I
|
||||
|
||||
// get rid of mobs
|
||||
for(var/mob/living/L in mob_occupant.GetAllContents() - mob_occupant)
|
||||
L.forceMove(drop_location())
|
||||
|
||||
if(storing.len)
|
||||
var/obj/O = new item_storage_type
|
||||
O.name = "cryogenic retrieval package: [mob_occupant.real_name]"
|
||||
for(var/i in storing)
|
||||
var/obj/item/I = i
|
||||
I.forceMove(O)
|
||||
O.forceMove(drop_to_ground? target_store.drop_location() : target_store)
|
||||
if((target_store == control_computer) && !drop_to_ground)
|
||||
control_computer.stored_packages += O
|
||||
|
||||
QDEL_LIST(destroying)
|
||||
|
||||
//Update any existing objectives involving this mob.
|
||||
for(var/i in GLOB.objectives)
|
||||
@@ -414,22 +404,13 @@
|
||||
|
||||
// Ghost and delete the mob.
|
||||
if(!mob_occupant.get_ghost(1))
|
||||
mob_occupant.ghostize(FALSE, penalize = TRUE, voluntary = TRUE)
|
||||
mob_occupant.ghostize(FALSE, penalize = TRUE, voluntary = TRUE, cryo = TRUE)
|
||||
|
||||
QDEL_NULL(occupant)
|
||||
for(var/I in cryo_items) //only "CRYO_DESTROY_LATER" atoms are left)
|
||||
var/atom/A = I
|
||||
if(!QDELETED(A))
|
||||
qdel(A)
|
||||
QDEL_LIST(destroy_later)
|
||||
open_machine()
|
||||
name = initial(name)
|
||||
|
||||
#undef CRYO_DESTROY
|
||||
#undef CRYO_PRESERVE
|
||||
#undef CRYO_OBJECTIVE
|
||||
#undef CRYO_IGNORE
|
||||
#undef CRYO_DESTROY_LATER
|
||||
|
||||
/obj/machinery/cryopod/MouseDrop_T(mob/living/target, mob/user)
|
||||
if(!istype(target) || user.incapacitated() || !target.Adjacent(user) || !Adjacent(user) || !ismob(target) || (!ishuman(user) && !iscyborg(user)) || !istype(user.loc, /turf) || target.buckled)
|
||||
return
|
||||
|
||||
@@ -67,9 +67,9 @@
|
||||
/obj/machinery/door/window/proc/open_and_close()
|
||||
open()
|
||||
if(src.check_access(null))
|
||||
sleep(50)
|
||||
sleep(60)
|
||||
else //secure doors close faster
|
||||
sleep(20)
|
||||
sleep(40)
|
||||
close()
|
||||
|
||||
/obj/machinery/door/window/Bumped(atom/movable/AM)
|
||||
|
||||
@@ -377,10 +377,3 @@
|
||||
hitsound = 'sound/weapons/taserhit.ogg'
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
breakouttime = 60
|
||||
|
||||
/obj/item/restraints/legcuffs/bola/energy/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
if(iscarbon(hit_atom))
|
||||
var/obj/item/restraints/legcuffs/beartrap/B = new /obj/item/restraints/legcuffs/beartrap/energy/cyborg(get_turf(hit_atom))
|
||||
B.Crossed(hit_atom)
|
||||
qdel(src)
|
||||
..()
|
||||
|
||||
@@ -175,7 +175,7 @@
|
||||
|
||||
/obj/item/kitchen/knife/combat/survival/knuckledagger/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/butchering, 50, 120, 5) // it's good for butchering stuff
|
||||
AddComponent(/datum/component/butchering, 30, 130, 20) // it's good for butchering stuff
|
||||
|
||||
/obj/item/kitchen/knife/combat/survival/knuckledagger/ui_action_click(mob/user, actiontype)
|
||||
light_on = !light_on
|
||||
@@ -189,6 +189,11 @@
|
||||
else
|
||||
set_light(0)
|
||||
|
||||
/obj/item/kitchen/knife/combat/survival/knuckledagger/update_overlays()
|
||||
. = ..()
|
||||
if(light_on)
|
||||
. += "[icon_state]_lit"
|
||||
|
||||
/obj/item/kitchen/knife/combat/bone
|
||||
name = "bone dagger"
|
||||
item_state = "bone_dagger"
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
//--end of love :'(--
|
||||
|
||||
var/snowflake_id //if we set from a config snowflake plushie.
|
||||
/// wrapper, do not use, read only
|
||||
var/__ADMIN_SET_TO_ID
|
||||
var/can_random_spawn = TRUE //if this is FALSE, don't spawn this for random plushies.
|
||||
|
||||
/obj/item/toy/plush/random_snowflake/Initialize(mapload, set_snowflake_id)
|
||||
@@ -112,10 +114,21 @@
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/toy/plush/vv_get_var(var_name)
|
||||
if(var_name == NAMEOF(src, __ADMIN_SET_TO_ID))
|
||||
return debug_variable("__ADMIN: SET SNOWFLAKE ID", snowflake_id, 0, src)
|
||||
return ..()
|
||||
|
||||
/obj/item/toy/plush/vv_edit_var(var_name, var_value)
|
||||
if(var_name == NAMEOF(src, __ADMIN_SET_TO_ID))
|
||||
return set_snowflake_from_config(var_value)
|
||||
return ..()
|
||||
|
||||
/obj/item/toy/plush/proc/set_snowflake_from_config(id)
|
||||
var/list/configlist = CONFIG_GET(keyed_list/snowflake_plushies)
|
||||
var/list/jsonlist = configlist[id]
|
||||
ASSERT(jsonlist)
|
||||
if(!jsonlist)
|
||||
return FALSE
|
||||
jsonlist = json_decode(jsonlist)
|
||||
if(jsonlist["inherit_from"])
|
||||
var/path = text2path(jsonlist["inherit_from"])
|
||||
@@ -151,6 +164,7 @@
|
||||
var/datum/component/squeak/S = GetComponent(/datum/component/squeak)
|
||||
S?.override_squeak_sounds = squeak_override
|
||||
snowflake_id = id
|
||||
return TRUE
|
||||
|
||||
/obj/item/toy/plush/handle_atom_del(atom/A)
|
||||
if(A == grenade)
|
||||
|
||||
@@ -137,8 +137,7 @@
|
||||
AM.anchored = TRUE
|
||||
flick("laserbox_burn", AM)
|
||||
trigger()
|
||||
sleep(15)
|
||||
qdel(AM)
|
||||
QDEL_IN(src, 15)
|
||||
|
||||
// snowflake code until undertile elements
|
||||
/obj/item/pressure_plate/hologrid/hide()
|
||||
|
||||
@@ -23,14 +23,15 @@
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
var/self_fueling = FALSE //Do we refill ourselves or not
|
||||
var/nextrefueltick = 0 // How long it takes before we get a new fuel unit
|
||||
var/nextrefueltick = 0 //When is the next tick we refuel?
|
||||
var/refueling_interval = 10 //Every how many processing ticks does this refuel? (1 = every processing tick)
|
||||
|
||||
custom_materials = list(/datum/material/iron=70, /datum/material/glass=30)
|
||||
var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2)
|
||||
var/status = TRUE //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower)
|
||||
var/max_fuel = 20 //The max amount of fuel the welder can hold
|
||||
var/change_icons = 1
|
||||
var/can_off_process = 0
|
||||
var/can_off_process = FALSE
|
||||
var/light_intensity = 2 //how powerful the emitted light is when used.
|
||||
var/progress_flash_divisor = 10
|
||||
var/burned_fuel_for = 0 //when fuel was last removed
|
||||
@@ -66,6 +67,14 @@
|
||||
. += "[initial(icon_state)]-on"
|
||||
|
||||
/obj/item/weldingtool/process()
|
||||
//This handles refueling. Its looking at how much fuel the tool has and comparing that to how much it holds
|
||||
//This then looks if the refuel tick has come based on world time.
|
||||
//Then looks if we refuel ourselves or not.
|
||||
|
||||
if(self_fueling && get_fuel() < max_fuel && nextrefueltick <= world.time)
|
||||
nextrefueltick = world.time + refueling_interval
|
||||
reagents.add_reagent(/datum/reagent/fuel, 1)
|
||||
|
||||
switch(welding)
|
||||
if(0)
|
||||
force = 3
|
||||
@@ -86,14 +95,6 @@
|
||||
//This is to start fires. process() is only called if the welder is on.
|
||||
open_flame()
|
||||
|
||||
//This handles refueling. Its looking at how much fuel the tool has and comparing that to how much it holds
|
||||
//This then looks if the refuel tick has come based on world time.
|
||||
//Then looks if we refuel ourselves or not.
|
||||
|
||||
if(get_fuel() < max_fuel && nextrefueltick < world.time && self_fueling)
|
||||
nextrefueltick = world.time + 10
|
||||
reagents.add_reagent(/datum/reagent/fuel, 1)
|
||||
|
||||
/obj/item/weldingtool/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
return (FIRELOSS)
|
||||
@@ -367,7 +368,7 @@
|
||||
custom_materials = list(/datum/material/iron=70, /datum/material/glass=120)
|
||||
change_icons = 0
|
||||
self_fueling = TRUE
|
||||
can_off_process = 1
|
||||
can_off_process = TRUE
|
||||
light_intensity = 1
|
||||
toolspeed = 0.5
|
||||
|
||||
@@ -375,6 +376,7 @@
|
||||
name = "brass welding tool"
|
||||
desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch."
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
refueling_interval = 5
|
||||
icon_state = "clockwelder"
|
||||
item_state = "brasswelder"
|
||||
|
||||
@@ -384,16 +386,20 @@
|
||||
icon = 'icons/obj/abductor.dmi'
|
||||
icon_state = "welder"
|
||||
self_fueling = TRUE
|
||||
can_off_process = TRUE
|
||||
refueling_interval = 1
|
||||
toolspeed = 0.1
|
||||
light_intensity = 0
|
||||
change_icons = 0
|
||||
|
||||
/obj/item/weldingtool/advanced
|
||||
name = "advanced welding tool"
|
||||
desc = "A modern welding tool combined with an alien welding tool, it never runs out of fuel and works almost as fast."
|
||||
desc = "A modern welding tool combined with an alien welding tool, it almost never runs out of fuel and works nearly as fast."
|
||||
icon = 'icons/obj/advancedtools.dmi'
|
||||
icon_state = "welder"
|
||||
self_fueling = TRUE
|
||||
can_off_process = TRUE
|
||||
refueling_interval = 2
|
||||
toolspeed = 0.2
|
||||
light_intensity = 0
|
||||
change_icons = 0
|
||||
|
||||
@@ -446,8 +446,11 @@
|
||||
var/mob/living/L = O
|
||||
if(!issilicon(L))
|
||||
L.DefaultCombatKnockdown(40)
|
||||
O.forceMove(T)
|
||||
close()
|
||||
if(istype(src, /obj/structure/closet/supplypod/extractionpod))
|
||||
O.forceMove(src)
|
||||
else
|
||||
O.forceMove(T)
|
||||
close()
|
||||
else
|
||||
O.forceMove(T)
|
||||
return 1
|
||||
|
||||
@@ -47,6 +47,25 @@
|
||||
new /obj/item/clothing/glasses/hud/health(src)
|
||||
return
|
||||
|
||||
/obj/structure/closet/secure_closet/paramedic
|
||||
name = "paramedic's locker"
|
||||
req_access = list(ACCESS_MEDICAL)
|
||||
icon_state = "paramed_secure"
|
||||
|
||||
/obj/structure/closet/secure_closet/paramedic/PopulateContents()
|
||||
..()
|
||||
new /obj/item/clothing/suit/toggle/labcoat/paramedic(src)
|
||||
new /obj/item/clothing/under/rank/medical/paramedic(src)
|
||||
new /obj/item/clothing/under/rank/medical/paramedic/skirt(src)
|
||||
new /obj/item/radio/headset/headset_med(src)
|
||||
new /obj/item/defibrillator/loaded(src)
|
||||
new /obj/item/clothing/gloves/color/latex/nitrile(src)
|
||||
new /obj/item/storage/belt/medical(src)
|
||||
new /obj/item/clothing/glasses/hud/health(src)
|
||||
new /obj/item/pinpointer/crew(src)
|
||||
new /obj/item/sensor_device(src)
|
||||
return
|
||||
|
||||
/obj/structure/closet/secure_closet/CMO
|
||||
name = "\proper chief medical officer's locker"
|
||||
req_access = list(ACCESS_CMO)
|
||||
|
||||
+3
-3
@@ -98,11 +98,11 @@ GLOBAL_LIST_INIT(freqtospan, list(
|
||||
|
||||
/// Converts specific characters, like +, |, and _ to formatted output.
|
||||
/atom/movable/proc/say_emphasis(input)
|
||||
var/static/regex/italics = regex(@"\|(\S[\w\W]*?\S)\|", "g")
|
||||
var/static/regex/italics = regex(@"\|((?=\S)[\w\W]*?(?<=\S))\|", "g")
|
||||
input = italics.Replace_char(input, "<i>$1</i>")
|
||||
var/static/regex/bold = regex(@"\+(\S[\w\W]*?\S)\+", "g")
|
||||
var/static/regex/bold = regex(@"\+((?=\S)[\w\W]*?(?<=\S))\+", "g")
|
||||
input = bold.Replace_char(input, "<b>$1</b>")
|
||||
var/static/regex/underline = regex(@"_(\S[\w\W]*?\S)_", "g")
|
||||
var/static/regex/underline = regex(@"_((?=\S)[\w\W]*?(?<=\S))_", "g")
|
||||
input = underline.Replace_char(input, "<u>$1</u>")
|
||||
return input
|
||||
|
||||
|
||||
@@ -163,6 +163,8 @@
|
||||
|
||||
while (pulling != null)
|
||||
var/next_pulling = pulling.pulling
|
||||
if(next_pulling == pulling)
|
||||
break // no loops
|
||||
|
||||
var/turf/T = get_step(puller.loc, turn(puller.dir, 180))
|
||||
pulling.can_be_z_moved = FALSE
|
||||
|
||||
@@ -679,8 +679,8 @@
|
||||
set category = "Server"
|
||||
set desc="Respawn basically"
|
||||
set name="Toggle Respawn"
|
||||
var/new_nores = !CONFIG_GET(flag/norespawn)
|
||||
CONFIG_SET(flag/norespawn, new_nores)
|
||||
var/new_nores = CONFIG_GET(flag/respawns_enabled)
|
||||
CONFIG_SET(flag/respawns_enabled, !new_nores)
|
||||
if (!new_nores)
|
||||
to_chat(world, "<B>You may now respawn.</B>", confidential = TRUE)
|
||||
else
|
||||
|
||||
@@ -44,6 +44,11 @@ GLOBAL_PROTECT(protected_ranks)
|
||||
/datum/admin_rank/vv_edit_var(var_name, var_value)
|
||||
return FALSE
|
||||
|
||||
/datum/admin_rank/CanProcCall(procname)
|
||||
. = ..()
|
||||
if(!check_rights(R_SENSITIVE))
|
||||
return FALSE
|
||||
|
||||
/proc/admin_keyword_to_flag(word, previous_rights=0)
|
||||
var/flag = 0
|
||||
switch(ckey(word))
|
||||
@@ -79,6 +84,8 @@ GLOBAL_PROTECT(protected_ranks)
|
||||
flag = R_AUTOLOGIN
|
||||
if("dbranks")
|
||||
flag = R_DBRANKS
|
||||
if("sensitive")
|
||||
flag = R_SENSITIVE
|
||||
if("@","prev")
|
||||
flag = previous_rights
|
||||
return flag
|
||||
|
||||
@@ -78,8 +78,11 @@ GLOBAL_PROTECT(admin_verbs_admin)
|
||||
/client/proc/mark_datum_mapview,
|
||||
/client/proc/hide_verbs, /*hides all our adminverbs*/
|
||||
/client/proc/hide_most_verbs, /*hides all our hideable adminverbs*/
|
||||
/datum/admins/proc/open_borgopanel
|
||||
/datum/admins/proc/open_borgopanel,
|
||||
/client/proc/admin_cmd_respawn_return_to_lobby,
|
||||
/client/proc/admin_cmd_remove_ghost_respawn_timer
|
||||
)
|
||||
|
||||
GLOBAL_LIST_INIT(admin_verbs_ban, list(/client/proc/unban_panel, /client/proc/DB_ban_panel, /client/proc/stickybanpanel))
|
||||
GLOBAL_PROTECT(admin_verbs_ban)
|
||||
GLOBAL_LIST_INIT(admin_verbs_sounds, list(/client/proc/play_local_sound, /client/proc/play_sound, /client/proc/manual_play_web_sound, /client/proc/set_round_end_sound))
|
||||
|
||||
@@ -28,6 +28,11 @@ GLOBAL_PROTECT(href_token)
|
||||
|
||||
var/deadmined
|
||||
|
||||
/datum/admins/CanProcCall(procname)
|
||||
. = ..()
|
||||
if(!check_rights(R_SENSITIVE))
|
||||
return FALSE
|
||||
|
||||
/datum/admins/New(datum/admin_rank/R, ckey, force_active = FALSE, protected)
|
||||
if(IsAdminAdvancedProcCall())
|
||||
var/msg = " has tried to elevate permissions!"
|
||||
@@ -147,6 +152,8 @@ GLOBAL_PROTECT(href_token)
|
||||
return 0
|
||||
|
||||
/datum/admins/vv_edit_var(var_name, var_value)
|
||||
if(var_name == NAMEOF(src, fakekey))
|
||||
return ..()
|
||||
return FALSE //nice try trialmin
|
||||
|
||||
/*
|
||||
|
||||
@@ -298,7 +298,9 @@
|
||||
browse_messages(target_ckey = ckey(target_key), agegate = TRUE)
|
||||
qdel(query_find_message_secret)
|
||||
|
||||
/proc/browse_messages(type, target_ckey, index, linkless = FALSE, filter, agegate = FALSE)
|
||||
/proc/browse_messages(type, target_ckey, index, linkless = FALSE, filter, agegate = FALSE, override = FALSE)
|
||||
if((!override || IsAdminAdvancedProcCall()) && !check_rights(R_SENSITIVE))
|
||||
return
|
||||
if(!SSdbcore.Connect())
|
||||
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
return
|
||||
|
||||
@@ -936,6 +936,12 @@
|
||||
else
|
||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=[ROLE_MIND_TRANSFER];jobban4=[REF(M)]'>Mind Transfer Potion</a></td>"
|
||||
|
||||
//Respawns
|
||||
if(jobban_isbanned(M, ROLE_RESPAWN))
|
||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=[ROLE_RESPAWN];jobban4=[REF(M)]'><font color=red>Respawns</font></a></td>"
|
||||
else
|
||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=[ROLE_RESPAWN];jobban4=[REF(M)]'>Respawns</a></td>"
|
||||
|
||||
dat += "</tr></table>"
|
||||
usr << browse(dat, "window=jobban2;size=800x450")
|
||||
return
|
||||
@@ -1799,12 +1805,15 @@
|
||||
if(alert(usr, "Send [key_name(M)] back to Lobby?", "Message", "Yes", "No") != "Yes")
|
||||
return
|
||||
|
||||
log_admin("[key_name(usr)] has sent [key_name(M)] back to the Lobby.")
|
||||
message_admins("[key_name(usr)] has sent [key_name(M)] back to the Lobby.")
|
||||
log_admin("[key_name(usr)] has sent [key_name(M)] back to the Lobby, removing their respawn restrictions if they existed.")
|
||||
message_admins("[key_name(usr)] has sent [key_name(M)] back to the Lobby, removing their respawn restrictions if they existed.")
|
||||
|
||||
var/mob/dead/new_player/NP = new()
|
||||
NP.ckey = M.ckey
|
||||
qdel(M)
|
||||
if(GLOB.preferences_datums[NP.ckey])
|
||||
var/datum/preferences/P = GLOB.preferences_datums[NP.ckey]
|
||||
P.respawn_restrictions_active = FALSE
|
||||
|
||||
else if(href_list["tdome1"])
|
||||
if(!check_rights(R_FUN))
|
||||
|
||||
@@ -23,13 +23,6 @@
|
||||
|
||||
var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>[uppertext(holder.rank)]([src.holder.fakekey ? pick(nicknames) : src.key])</span> says, <span class='message'>\"[emoji_parse(msg)]\"</span></span>"
|
||||
|
||||
// var/rank_name = holder.rank
|
||||
// var/admin_name = key
|
||||
// if(holder.fakekey)
|
||||
// rank_name = pick(strings("admin_nicknames.json", "ranks", "config")) please use this soon.
|
||||
// admin_name = pick(strings("admin_nicknames.json", "names", "config"))
|
||||
// var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>[rank_name]([admin_name])</span> says, <span class='message'>\"[emoji_parse(msg)]\"</span></span>"
|
||||
|
||||
for (var/mob/M in GLOB.player_list)
|
||||
if(isnewplayer(M))
|
||||
continue
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
browseserverlogs("[GLOB.log_directory]/")
|
||||
|
||||
/client/proc/browseserverlogs(path = "data/logs/")
|
||||
if(!check_rights(R_SENSITIVE))
|
||||
return
|
||||
path = browse_files(path)
|
||||
if(!path)
|
||||
return
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
L.adjustFireLoss(amount)
|
||||
newamt = L.getFireLoss()
|
||||
if("toxin")
|
||||
L.adjustToxLoss(amount, toxins_type = TOX_OMNI)
|
||||
L.adjustToxLoss(amount, toxins_type = TOX_OMNI, forced = TRUE)
|
||||
newamt = L.getToxLoss()
|
||||
if("oxygen")
|
||||
L.adjustOxyLoss(amount)
|
||||
|
||||
@@ -120,9 +120,14 @@
|
||||
if(bruteheal + fireheal + toxinheal > 0) // Just a check? Don't heal/spend, and return.
|
||||
if(mult == 0)
|
||||
return TRUE
|
||||
|
||||
// We have damage. Let's heal (one time)
|
||||
C.adjustBruteLoss(-bruteheal * mult, forced = TRUE)// Heal BRUTE / BURN in random portions throughout the body.
|
||||
C.adjustFireLoss(-fireheal * mult, forced = TRUE)
|
||||
var/list/damaged_parts = C.get_damaged_bodyparts(TRUE,TRUE, status = list(BODYPART_ORGANIC, BODYPART_HYBRID, BODYPART_NANITES))
|
||||
if(damaged_parts.len)
|
||||
for(var/obj/item/bodypart/part in damaged_parts) // Heal BRUTE / BURN equally distibuted over all damaged bodyparts.
|
||||
part.heal_damage((bruteheal * mult)/damaged_parts.len, (fireheal * mult)/damaged_parts.len, only_organic = FALSE, updating_health = FALSE)
|
||||
C.updatehealth()
|
||||
C.update_damage_overlays()
|
||||
C.adjustToxLoss(-toxinheal * mult * 2, forced = TRUE) //Toxin healing because vamps arent immune
|
||||
//C.heal_overall_damage(bruteheal * mult, fireheal * mult) // REMOVED: We need to FORCE this, because otherwise, vamps won't heal EVER. Swapped to above.
|
||||
AddBloodVolume((bruteheal * -0.5 + fireheal * -1 + toxinheal * -0.2) / mult * costMult) // Costs blood to heal
|
||||
@@ -276,7 +281,7 @@
|
||||
/datum/antagonist/bloodsucker/proc/FinalDeath()
|
||||
//Dont bother if we are already supposed to be dead
|
||||
if(FinalDeath)
|
||||
return
|
||||
return
|
||||
FinalDeath = TRUE //We are now supposed to die. Lets not spam it.
|
||||
if(!iscarbon(owner.current)) //Check for non carbons.
|
||||
owner.current.gib()
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
var/can_be_staked = FALSE // Only Feed can happen with a stake in you.
|
||||
var/cooldown_static = FALSE // Feed, Masquerade, and One-Shot powers don't improve their cooldown.
|
||||
//var/not_bloodsucker = FALSE // This goes to Vassals or Hunters, but NOT bloodsuckers.
|
||||
var/must_be_concious = TRUE //Can't use this ability while unconcious.
|
||||
|
||||
/datum/action/bloodsucker/New()
|
||||
if(bloodcost > 0)
|
||||
@@ -101,6 +102,11 @@
|
||||
if(display_error)
|
||||
to_chat(owner, "<span class='warning'>Garlic in your blood is interfering with your powers!</span>")
|
||||
return FALSE
|
||||
if(must_be_concious)
|
||||
if(owner.stat != CONSCIOUS)
|
||||
if(display_error)
|
||||
to_chat(owner, "<span class='warning'>You can't do this while you are unconcious!</span>")
|
||||
return FALSE
|
||||
// Incap?
|
||||
if(must_be_capacitated)
|
||||
var/mob/living/L = owner
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
can_use_in_torpor = TRUE
|
||||
must_be_capacitated = TRUE
|
||||
can_be_immobilized = TRUE
|
||||
must_be_concious = FALSE
|
||||
|
||||
/datum/action/bloodsucker/gohome/CheckCanUse(display_error)
|
||||
. = ..()
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
warn_constant_cost = TRUE
|
||||
can_use_in_torpor = TRUE // Masquerade is maybe the only one that can do this. It stops your healing.
|
||||
cooldown_static = TRUE
|
||||
must_be_concious = FALSE
|
||||
|
||||
// NOTE: Firing off vulgar powers disables your Masquerade!
|
||||
|
||||
|
||||
@@ -689,8 +689,8 @@
|
||||
wound_enhancement = 6
|
||||
var/fast_enhancement = 6
|
||||
var/fast_wound_enhancement = 6
|
||||
var/slow_enhancement = 20
|
||||
var/slow_wound_enhancement = 20
|
||||
var/slow_enhancement = 12
|
||||
var/slow_wound_enhancement = 15
|
||||
silent = TRUE
|
||||
inherited_trait = TRAIT_CHUNKYFINGERS // how do you expect to shoot anyone with bone covered hands
|
||||
secondary_trait = TRAIT_MAULER // just punch them idiot
|
||||
|
||||
@@ -445,7 +445,7 @@
|
||||
if(L.move_resist < MOVE_FORCE_STRONG)
|
||||
var/atom/throw_target = get_edge_target_turf(L, user.dir)
|
||||
L.throw_at(throw_target, 7, 1, user)
|
||||
else if(!iscultist(L))
|
||||
else if(!is_servant_of_ratvar(L))
|
||||
L.DefaultCombatKnockdown(160)
|
||||
L.adjustStaminaLoss(140) //Ensures hard stamcrit
|
||||
L.flash_act(1,1)
|
||||
@@ -465,7 +465,7 @@
|
||||
C.drowsyness = max(10, C.drowsyness)
|
||||
C.confused += clamp(20 - C.confused, 0, 10)
|
||||
L.adjustBruteLoss(15)
|
||||
to_chat(user, "<span class='cultitalic'>In an brilliant flash of red, [L] [iscultist(L) ? "writhes in pain" : "falls to the ground!"]</span>")
|
||||
to_chat(user, "<span class='cultitalic'>In an brilliant flash of red, [L] [is_servant_of_ratvar(L) ? "writhes in pain!" : "falls to the ground!"]</span>")
|
||||
uses--
|
||||
..()
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
var/pck = pick("assasinate","protect")
|
||||
switch(pck)
|
||||
if("assasinate")
|
||||
var/datum/objective/assassinate/A = new
|
||||
var/datum/objective/assassinate/once/A = new
|
||||
A.owner = owner
|
||||
var/list/owners = A.get_owners()
|
||||
A.find_target(owners,protection)
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
var/mob/living/living_user = user
|
||||
living_user.adjustBruteLoss(-3, FALSE)
|
||||
living_user.adjustFireLoss(-3, FALSE)
|
||||
living_user.adjustToxLoss(-3, FALSE)
|
||||
living_user.adjustToxLoss(-3, FALSE, TRUE)
|
||||
living_user.adjustOxyLoss(-1, FALSE)
|
||||
living_user.adjustStaminaLoss(-6)
|
||||
|
||||
|
||||
@@ -34,10 +34,55 @@
|
||||
|
||||
/datum/supply_pack/critter/parrot/generate()
|
||||
. = ..()
|
||||
for(var/i in 1 to 4)
|
||||
new /mob/living/simple_animal/parrot(.)
|
||||
if(prob(1))
|
||||
new /mob/living/simple_animal/parrot/clock_hawk(.)
|
||||
for(var/i in 1 to 5)
|
||||
switch(rand(1, 23))
|
||||
if(1)
|
||||
new /mob/living/simple_animal/parrot(.)
|
||||
if(2)
|
||||
new /mob/living/simple_animal/parrot/clock_hawk(.)
|
||||
if(3)
|
||||
new /mob/living/simple_animal/parrot/kea(.)
|
||||
if(4)
|
||||
new /mob/living/simple_animal/parrot/eclectus(.)
|
||||
if(5)
|
||||
new /mob/living/simple_animal/parrot/eclectusf(.)
|
||||
if(6)
|
||||
new /mob/living/simple_animal/parrot/greybird(.)
|
||||
if(7)
|
||||
new /mob/living/simple_animal/parrot/blue_caique(.)
|
||||
if(8)
|
||||
new /mob/living/simple_animal/parrot/white_caique(.)
|
||||
if(9)
|
||||
new /mob/living/simple_animal/parrot/green_budgerigar(.)
|
||||
if(10)
|
||||
new /mob/living/simple_animal/parrot/blue_Budgerigar(.)
|
||||
if(11)
|
||||
new /mob/living/simple_animal/parrot/bluegreen_Budgerigar(.)
|
||||
if(12)
|
||||
new /mob/living/simple_animal/parrot/commonblackbird(.)
|
||||
if(13)
|
||||
new /mob/living/simple_animal/parrot/azuretit(.)
|
||||
if(14)
|
||||
new /mob/living/simple_animal/parrot/europeanrobin(.)
|
||||
if(15)
|
||||
new /mob/living/simple_animal/parrot/goldcrest(.)
|
||||
if(16)
|
||||
new /mob/living/simple_animal/parrot/ringneckdove(.)
|
||||
if(17)
|
||||
new /mob/living/simple_animal/parrot/cockatiel(.)
|
||||
if(18)
|
||||
new /mob/living/simple_animal/parrot/white_cockatiel(.)
|
||||
if(19)
|
||||
new /mob/living/simple_animal/parrot/yellowish_cockatiel(.)
|
||||
if(20)
|
||||
new /mob/living/simple_animal/parrot/grey_cockatiel(.)
|
||||
if(21)
|
||||
new /mob/living/simple_animal/parrot/too(.)
|
||||
if(22)
|
||||
new /mob/living/simple_animal/parrot/hooded_too(.)
|
||||
if(23)
|
||||
new /mob/living/simple_animal/parrot/pink_too(.)
|
||||
|
||||
|
||||
/datum/supply_pack/critter/butterfly
|
||||
name = "Butterflies Crate"
|
||||
|
||||
@@ -101,6 +101,10 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
keyUp(keycode)
|
||||
return
|
||||
|
||||
if(href_list["statpanel_item_target"])
|
||||
handle_statpanel_click(href_list)
|
||||
return
|
||||
|
||||
// Tgui Topic middleware
|
||||
if(tgui_Topic(href_list))
|
||||
return
|
||||
@@ -141,6 +145,10 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
|
||||
..() //redirect to hsrc.Topic()
|
||||
|
||||
/client/proc/handle_statpanel_click(list/href_list)
|
||||
var/atom/target = locate(href_list["statpanel_item_target"])
|
||||
Click(target, target.loc, null, "[href_list["statpanel_item_shiftclick"]?"shift=1;":null][href_list["statpanel_item_ctrlclick"]?"ctrl=1;":null]&alt=[href_list["statpanel_item_altclick"]?"alt=1;":null]", FALSE, "statpanel")
|
||||
|
||||
/client/proc/is_content_unlocked()
|
||||
if(!prefs.unlock_content)
|
||||
to_chat(src, "Become a BYOND member to access member-perks and features, as well as support the engine that makes this game possible. Only 10 bucks for 3 months! <a href=\"https://secure.byond.com/membership\">Click Here to find out more</a>.")
|
||||
@@ -798,7 +806,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
message_admins("<span class='adminnotice'>Proxy Detection: [key_name_admin(src)] IP intel rated [res.intel*100]% likely to be a Proxy/VPN.</span>")
|
||||
ip_intel = res.intel
|
||||
|
||||
/client/Click(atom/object, atom/location, control, params, ignore_spam = FALSE)
|
||||
/client/Click(atom/object, atom/location, control, params, ignore_spam = FALSE, extra_info)
|
||||
if(last_click > world.time - world.tick_lag)
|
||||
return
|
||||
last_click = world.time
|
||||
@@ -851,7 +859,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
return
|
||||
|
||||
if(prefs.log_clicks)
|
||||
log_click(object, location, control, params, src)
|
||||
log_click(object, location, control, params, src, extra_info? "clicked ([extra_info])" : null)
|
||||
|
||||
if (prefs.hotkeys)
|
||||
// If hotkey mode is enabled, then clicking the map will automatically
|
||||
@@ -921,8 +929,22 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
if (NAMEOF(src, view))
|
||||
view_size.setDefault(var_value)
|
||||
return TRUE
|
||||
if(NAMEOF(src, computer_id))
|
||||
return FALSE
|
||||
if(NAMEOF(src, address))
|
||||
return FALSE
|
||||
. = ..()
|
||||
|
||||
/client/vv_get_var(var_name)
|
||||
. = ..()
|
||||
switch(var_name)
|
||||
if(NAMEOF(src, computer_id))
|
||||
if(!check_rights(R_SENSITIVE, FALSE))
|
||||
return "SENSITIVE"
|
||||
if(NAMEOF(src, address))
|
||||
if(!check_rights(R_SENSITIVE, FALSE))
|
||||
return "SENSITIVE"
|
||||
|
||||
/client/proc/rescale_view(change, min, max)
|
||||
var/viewscale = getviewsize(view)
|
||||
var/x = viewscale[1]
|
||||
|
||||
@@ -12,11 +12,29 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used
|
||||
var/max_save_slots = 24
|
||||
|
||||
//non-preference stuff
|
||||
var/muted = 0
|
||||
// Intra-round persistence begin
|
||||
/// Flags for admin mutes
|
||||
var/muted = NONE
|
||||
/// Last IP the person was seen on
|
||||
var/last_ip
|
||||
/// Last CID the person was seen on
|
||||
var/last_id
|
||||
/// Do we log their clicks to disk?
|
||||
var/log_clicks = FALSE
|
||||
/// Characters they have joined the round under - Lazylist of names
|
||||
var/list/characters_joined_as
|
||||
/// Slots they have joined the round under - Lazylist of numbers
|
||||
var/list/slots_joined_as
|
||||
/// Are we currently subject to respawn restrictions? Usually set by us using the "respawn" verb, but can be lifted by admins.
|
||||
var/respawn_restrictions_active = FALSE
|
||||
/// time of death we consider for respawns
|
||||
var/respawn_time_of_death = -INFINITY
|
||||
/// did they DNR? used to prevent respawns.
|
||||
var/dnr_triggered = FALSE
|
||||
/// did they cryo on their last ghost?
|
||||
var/respawn_did_cryo = FALSE
|
||||
|
||||
// Intra-round persistence end
|
||||
|
||||
var/icon/custom_holoform_icon
|
||||
var/list/cached_holoform_icons
|
||||
|
||||
@@ -179,7 +179,7 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8")
|
||||
to_chat(usr, "<span class='notice'>Sorry, that function is not enabled on this server.</span>")
|
||||
return
|
||||
|
||||
browse_messages(null, usr.ckey, null, TRUE)
|
||||
browse_messages(null, usr.ckey, null, TRUE, override = TRUE)
|
||||
|
||||
/client/proc/self_playtime()
|
||||
set name = "View tracked playtime"
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
body_parts_covered = ARMS
|
||||
cold_protection = ARMS
|
||||
strip_delay = 300 //you can't just yank them off
|
||||
obj_flags = UNIQUE_RENAME
|
||||
/// did you ever get around to wearing these or no
|
||||
var/wornonce = FALSE
|
||||
///Extra damage through the punch.
|
||||
|
||||
@@ -873,9 +873,9 @@
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/lavaknight
|
||||
name = "cydonian helmet"
|
||||
desc = "A helmet designed with both form and function in mind, it protects the user against physical trauma and hazardous conditions while also having polychromic light strips."
|
||||
icon_state = "knight_cydonia"
|
||||
icon_state = "hardsuit0-knight_cydonia"
|
||||
item_state = "knight_yellow"
|
||||
hardsuit_type = null
|
||||
hardsuit_type = "knight_cydonia"
|
||||
max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
|
||||
resistance_flags = FIRE_PROOF | LAVA_PROOF
|
||||
heat_protection = HEAD
|
||||
|
||||
@@ -256,7 +256,7 @@ Contains:
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/alert
|
||||
armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 50)
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_SNEK_TAURIC
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_SNEK_TAURIC|STYLE_PAW_TAURIC
|
||||
|
||||
//ERT Security
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/ert/alert/sec
|
||||
|
||||
@@ -554,7 +554,7 @@ Since Ramadan is an entire month that lasts 29.5 days on average, the start and
|
||||
|
||||
/datum/holiday/xmas
|
||||
name = CHRISTMAS
|
||||
begin_day = 10
|
||||
begin_day = 18
|
||||
begin_month = DECEMBER
|
||||
end_day = 27
|
||||
drone_hat = /obj/item/clothing/head/santa
|
||||
|
||||
@@ -73,6 +73,12 @@
|
||||
/// Starting skill modifiers.
|
||||
var/list/starting_modifiers
|
||||
|
||||
// These can be flags but I don't care because they're never changed
|
||||
/// Can you always join as this job even while respawning (should probably only be on for assistant)
|
||||
var/always_can_respawn_as = FALSE
|
||||
/// Is this job considered a combat role for respawning? (usually sec/command)
|
||||
var/considered_combat_role = FALSE
|
||||
|
||||
/**
|
||||
* Checks if we should be created on a certain map
|
||||
*/
|
||||
@@ -118,15 +124,21 @@
|
||||
|
||||
//Used for a special check of whether to allow a client to latejoin as this job.
|
||||
/datum/job/proc/special_check_latejoin(client/C)
|
||||
var/joined = LAZYLEN(C.prefs?.characters_joined_as)
|
||||
if(C.prefs?.respawn_restrictions_active && (joined || CONFIG_GET(flag/respawn_penalty_includes_observe)))
|
||||
if(!CONFIG_GET(flag/allow_non_assistant_respawn) && !always_can_respawn_as)
|
||||
return FALSE
|
||||
if(!CONFIG_GET(flag/allow_combat_role_respawn) && considered_combat_role)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/job/proc/GetAntagRep()
|
||||
. = CONFIG_GET(keyed_list/antag_rep)[lowertext(title)]
|
||||
. = CONFIG_GET(keyed_list/antag_rep)[ckey(title)]
|
||||
if(. == null)
|
||||
return antag_rep
|
||||
|
||||
/datum/job/proc/GetThreat()
|
||||
. = CONFIG_GET(keyed_list/job_threat)[lowertext(title)]
|
||||
. = CONFIG_GET(keyed_list/job_threat)[ckey(title)]
|
||||
if(. == null)
|
||||
return threat
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
display_order = JOB_DISPLAY_ORDER_AI
|
||||
var/do_special_check = TRUE
|
||||
threat = 5
|
||||
considered_combat_role = TRUE
|
||||
|
||||
starting_modifiers = list(/datum/skill_modifier/job/level/wiring/basic)
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ Assistant
|
||||
paycheck_department = ACCOUNT_CIV
|
||||
display_order = JOB_DISPLAY_ORDER_ASSISTANT
|
||||
dresscodecompliant = FALSE
|
||||
always_can_respawn_as = TRUE
|
||||
threat = 0.2
|
||||
|
||||
/datum/job/assistant/get_access()
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
exp_requirements = 180
|
||||
exp_type = EXP_TYPE_COMMAND
|
||||
exp_type_department = EXP_TYPE_COMMAND
|
||||
considered_combat_role = TRUE
|
||||
|
||||
|
||||
outfit = /datum/outfit/job/captain
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
exp_requirements = 180
|
||||
exp_type = EXP_TYPE_CREW
|
||||
exp_type_department = EXP_TYPE_ENGINEERING
|
||||
considered_combat_role = TRUE
|
||||
|
||||
outfit = /datum/outfit/job/ce
|
||||
plasma_outfit = /datum/outfit/plasmaman/ce
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
exp_requirements = 180
|
||||
exp_type = EXP_TYPE_CREW
|
||||
exp_type_department = EXP_TYPE_MEDICAL
|
||||
considered_combat_role = TRUE
|
||||
|
||||
outfit = /datum/outfit/job/cmo
|
||||
plasma_outfit = /datum/outfit/plasmaman/cmo
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
minimal_player_age = 21
|
||||
exp_requirements = 120
|
||||
exp_type = EXP_TYPE_CREW
|
||||
considered_combat_role = TRUE
|
||||
|
||||
starting_modifiers = list(/datum/skill_modifier/job/level/wiring/basic)
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
outfit = /datum/outfit/job/detective
|
||||
plasma_outfit = /datum/outfit/plasmaman/detective
|
||||
considered_combat_role = TRUE
|
||||
|
||||
access = list(ACCESS_SEC_DOORS, ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_COURT, ACCESS_BRIG, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM)
|
||||
minimal_access = list(ACCESS_SEC_DOORS, ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_COURT, ACCESS_BRIG, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
exp_requirements = 180
|
||||
exp_type = EXP_TYPE_CREW
|
||||
exp_type_department = EXP_TYPE_SERVICE
|
||||
|
||||
considered_combat_role = TRUE
|
||||
outfit = /datum/outfit/job/hop
|
||||
plasma_outfit = /datum/outfit/plasmaman/hop
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
minimal_player_age = 10
|
||||
exp_requirements = 300
|
||||
exp_type = EXP_TYPE_CREW
|
||||
considered_combat_role = TRUE
|
||||
exp_type_department = EXP_TYPE_SECURITY
|
||||
|
||||
outfit = /datum/outfit/job/hos
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
exp_requirements = 180
|
||||
exp_type = EXP_TYPE_CREW
|
||||
exp_type_department = EXP_TYPE_SUPPLY
|
||||
considered_combat_role = TRUE
|
||||
|
||||
outfit = /datum/outfit/job/quartermaster
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
exp_type_department = EXP_TYPE_SCIENCE
|
||||
exp_requirements = 180
|
||||
exp_type = EXP_TYPE_CREW
|
||||
considered_combat_role = TRUE
|
||||
|
||||
outfit = /datum/outfit/job/rd
|
||||
plasma_outfit = /datum/outfit/plasmaman/rd
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
minimal_player_age = 7
|
||||
exp_requirements = 300
|
||||
exp_type = EXP_TYPE_CREW
|
||||
considered_combat_role = TRUE
|
||||
|
||||
outfit = /datum/outfit/job/security
|
||||
plasma_outfit = /datum/outfit/plasmaman/security
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
minimal_player_age = 7
|
||||
exp_requirements = 300
|
||||
exp_type = EXP_TYPE_CREW
|
||||
considered_combat_role = TRUE
|
||||
|
||||
outfit = /datum/outfit/job/warden
|
||||
plasma_outfit = /datum/outfit/plasmaman/warden
|
||||
|
||||
@@ -124,7 +124,8 @@
|
||||
return TRUE
|
||||
|
||||
/datum/keybinding/living/hold_sprint
|
||||
hotkey_keys = list("Shift")
|
||||
hotkey_keys = list()
|
||||
classic_keys = list()
|
||||
name = "hold_sprint"
|
||||
full_name = "Sprint (hold down)"
|
||||
description = "Hold down to sprint"
|
||||
@@ -144,7 +145,8 @@
|
||||
return TRUE
|
||||
|
||||
/datum/keybinding/living/toggle_sprint
|
||||
hotkey_keys = list()
|
||||
hotkey_keys = list("Shift")
|
||||
classic_keys = list("Shift")
|
||||
name = "toggle_sprint"
|
||||
full_name = "Sprint (toggle)"
|
||||
description = "Press to toggle sprint"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
/datum/proc/keyLoop(client/user) // Called once every frame
|
||||
//SHOULD_NOT_SLEEP(TRUE)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
/client/verb/fix_macros()
|
||||
set name = "Fix Keybindings"
|
||||
|
||||
@@ -81,11 +81,10 @@
|
||||
STOP_PROCESSING(SSmachines, src)
|
||||
icon_state = "coinpress0"
|
||||
|
||||
/obj/machinery/mineral/mint/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/mineral/mint/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "Mint", name, ui_x, ui_y, master_ui, state)
|
||||
ui = new(user, src, "Mint", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/mineral/mint/ui_data()
|
||||
|
||||
@@ -375,7 +375,9 @@
|
||||
ready = PLAYER_NOT_READY
|
||||
return FALSE
|
||||
|
||||
var/this_is_like_playing_right = alert(src,"Are you sure you wish to observe? You will not be able to play this round!","Player Setup","Yes","No")
|
||||
var/mintime = max(CONFIG_GET(number/respawn_delay), (SSticker.round_start_time + (CONFIG_GET(number/respawn_minimum_delay_roundstart) * 600)) - world.time, 0)
|
||||
|
||||
var/this_is_like_playing_right = alert(src,"Are you sure you wish to observe? You will not be able to respawn for [round(mintime / 600, 0.1)] minutes!!","Player Setup","Yes","No")
|
||||
|
||||
if(QDELETED(src) || !src.client || this_is_like_playing_right != "Yes")
|
||||
ready = PLAYER_NOT_READY
|
||||
@@ -397,6 +399,7 @@
|
||||
stack_trace("There's no freaking observer landmark available on this map or you're making observers before the map is initialised")
|
||||
transfer_ckey(observer, FALSE)
|
||||
observer.client = client
|
||||
observer.client.prefs?.respawn_time_of_death = world.time
|
||||
observer.set_ghost_appearance()
|
||||
if(observer.client && observer.client.prefs)
|
||||
observer.real_name = observer.client.prefs.real_name
|
||||
@@ -463,6 +466,9 @@
|
||||
alert(src, "An administrator has disabled late join spawning.")
|
||||
return FALSE
|
||||
|
||||
if(!respawn_latejoin_check(notify = TRUE))
|
||||
return FALSE
|
||||
|
||||
var/arrivals_docked = TRUE
|
||||
if(SSshuttle.arrivals)
|
||||
close_spawn_windows() //In case we get held up
|
||||
@@ -526,6 +532,8 @@
|
||||
|
||||
GLOB.joined_player_list += character.ckey
|
||||
GLOB.latejoiners += character
|
||||
LAZYOR(character.client.prefs.slots_joined_as, character.client.prefs.default_slot)
|
||||
LAZYOR(character.client.prefs.characters_joined_as, character.real_name)
|
||||
|
||||
if(CONFIG_GET(flag/allow_latejoin_antagonists) && humanc) //Borgs aren't allowed to be antags. Will need to be tweaked if we get true latejoin ais.
|
||||
if(SSshuttle.emergency)
|
||||
|
||||
@@ -264,7 +264,7 @@ Transfer_mind is there to check if mob is being deleted/not going to have a body
|
||||
Works together with spawning an observer, noted above.
|
||||
*/
|
||||
|
||||
/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE, voluntary = FALSE)
|
||||
/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE, voluntary = FALSE, cryo = FALSE)
|
||||
var/sig_flags = SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse, special, penalize)
|
||||
penalize = !(sig_flags & COMPONENT_DO_NOT_PENALIZE_GHOSTING) && (suiciding || penalize) // suicide squad.
|
||||
voluntary_ghosted = voluntary
|
||||
@@ -277,6 +277,12 @@ Works together with spawning an observer, noted above.
|
||||
if (client && client.prefs && client.prefs.auto_ooc)
|
||||
if (!(client.prefs.chat_toggles & CHAT_OOC))
|
||||
client.prefs.chat_toggles ^= CHAT_OOC
|
||||
if(ckey && penalize)
|
||||
var/datum/preferences/P = GLOB.preferences_datums[ckey]
|
||||
if(P)
|
||||
P.respawn_restrictions_active = TRUE
|
||||
P.respawn_time_of_death = world.time
|
||||
P.respawn_did_cryo = cryo
|
||||
transfer_ckey(ghost, FALSE)
|
||||
ghost.client.init_verbs()
|
||||
if(penalize)
|
||||
@@ -423,12 +429,14 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
to_chat(usr, "<span class='warning'>You're already stuck out of your body!</span>")
|
||||
return FALSE
|
||||
|
||||
var/response = alert(src, "Are you sure you want to prevent (almost) all means of resuscitation? This cannot be undone. ","Are you sure you want to stay dead?","Yes","No")
|
||||
var/response = alert(src, "Are you sure you want to prevent (almost) all means of resuscitation? This cannot be undone. THIS WILL ALSO STOP YOU FROM RESPAWNING!!!","Are you sure you want to stay dead and never respawn?","Yes","No")
|
||||
|
||||
if(response != "Yes")
|
||||
return
|
||||
|
||||
can_reenter_corpse = FALSE
|
||||
to_chat(src, "You can no longer be brought back into your body.")
|
||||
client.prefs?.dnr_triggered = TRUE
|
||||
to_chat(src, "You can no longer be brought back into your body or respawn.")
|
||||
return TRUE
|
||||
|
||||
/mob/dead/observer/proc/notify_cloning(var/message, var/sound, var/atom/source, flashwindow = TRUE)
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
// ADMIN VERBS BEGIN
|
||||
/**
|
||||
* Fully returns a player to lobby, allowing them to bypass all respawn restrictions
|
||||
* Works on ghosts or new players (lobby players)
|
||||
* If a lobby player is selected, their restrictions are removed.
|
||||
*/
|
||||
/client/proc/admin_cmd_respawn_return_to_lobby()
|
||||
set name = "Respawn Player (Unrestricted)"
|
||||
set desc = "Gives a player an unrestricted respawn, resetting all respawn restrictions for them."
|
||||
set category = "Admin"
|
||||
|
||||
var/list/mob/valid = list()
|
||||
for(var/mob/dead/observer/I in GLOB.dead_mob_list)
|
||||
if(!I.client)
|
||||
continue
|
||||
valid["[I.ckey] - Observing: [I]"] = I.ckey
|
||||
for(var/mob/dead/new_player/I in GLOB.dead_mob_list)
|
||||
if(!I.client || !I.client.prefs.respawn_restrictions_active)
|
||||
continue
|
||||
valid["[I.ckey] - IN LOBBY"] = I.ckey
|
||||
if(!valid.len)
|
||||
to_chat(src, "<span class='warning'>No player found that is either a ghost or is in lobby with restrictions active.</span>")
|
||||
return
|
||||
var/ckey = valid[input(src, "Choose a player (only showing logged in players who have restrictions)", "Unrestricted Respawn") as null|anything in valid]
|
||||
var/client/player = GLOB.directory[ckey]
|
||||
if(!player)
|
||||
to_chat(src, "<span class='warning'>Client not found.</span>")
|
||||
return
|
||||
var/mob/M = player.mob
|
||||
if(istype(M, /mob/dead/observer))
|
||||
var/mob/dead/observer/O = M
|
||||
var/confirm = alert(src, "Send [O]([ckey]) back to the lobby without respawn restrictions?", "Send to Lobby", "Yes", "No")
|
||||
if(confirm != "Yes")
|
||||
return
|
||||
message_admins("[key_name_admin(src)] gave [key_name_admin(O)] a full respawn and sent them back to the lobby.")
|
||||
log_admin("[key_name(src)] gave [key_name(O)] a full respawn and sent them back to the lobby.")
|
||||
to_chat(O, "<span class='userdanger'>You have been given a full respawn.</span>")
|
||||
O.do_respawn(FALSE)
|
||||
O.client.prefs.dnr_triggered = FALSE
|
||||
else if(istype(M, /mob/dead/new_player))
|
||||
var/mob/dead/new_player/NP = M
|
||||
var/confirm = alert(src, "Remove [NP]'s respawn restrictions?", "Remove Restrictions", "Yes", "No")
|
||||
if(confirm != "Yes")
|
||||
return
|
||||
message_admins("[key_name_admin(src)] removed [ckey]'s respawn restrictions.")
|
||||
log_admin("[key_name(src)] removed [ckey]'s respawn restrictions")
|
||||
NP.client.prefs.respawn_restrictions_active = FALSE
|
||||
NP.client.prefs.dnr_triggered = FALSE
|
||||
to_chat(NP, "<span class='boldnotie'>Your respawn restrictions have been removed.")
|
||||
else
|
||||
CRASH("Invalid mobtype")
|
||||
|
||||
/**
|
||||
* Allows a ghost to bypass respawn delay without lifting respawn restrictions
|
||||
*/
|
||||
/client/proc/admin_cmd_remove_ghost_respawn_timer()
|
||||
set name = "Remove Respawn Timer for Player"
|
||||
set desc = "Removes a player's respawn timer without removing their respawning restrictions."
|
||||
set category = "Admin"
|
||||
|
||||
var/list/mob/dead/observer/valid = list()
|
||||
for(var/mob/dead/observer/I in GLOB.dead_mob_list)
|
||||
if(!I.client)
|
||||
continue
|
||||
valid["[I.ckey] - [I.name]"] = I
|
||||
|
||||
if(!valid.len)
|
||||
to_chat(src, "<span class='warning'>No logged in ghosts found.</span>")
|
||||
return
|
||||
var/mob/dead/observer/O = valid[input(src, "Choose a player (only showing logged in)", "Remove Respawn Timer") as null|anything in valid]
|
||||
|
||||
if(!O.client)
|
||||
to_chat(src, "<span class='warning'>[O] has no client.</span>")
|
||||
return
|
||||
var/timeleft = O.time_left_to_respawn()
|
||||
if(!timeleft)
|
||||
to_chat(src, "<span class='warning'>[O] can already respawn.")
|
||||
return
|
||||
message_admins("[key_name_admin(src)] removed [key_name_admin(O)]'s respawn timer.")
|
||||
log_admin("[key_name(src)] removed [key_name(O)]'s respawn timer.")
|
||||
O.client.prefs.respawn_time_of_death = -INFINITY
|
||||
to_chat(O, "<span class='boldnotice'>Your respawn timer has been removed.")
|
||||
|
||||
// ADMIN VERBS END
|
||||
|
||||
/**
|
||||
* Checks if we can latejoin on the currently selected slot, taking into account respawn status.
|
||||
*/
|
||||
/mob/dead/new_player/proc/respawn_latejoin_check(notify = FALSE)
|
||||
if(!client.prefs.respawn_restrictions_active)
|
||||
return TRUE
|
||||
var/can_same_person = CONFIG_GET(flag/allow_same_character_respawn)
|
||||
if(can_same_person)
|
||||
return TRUE
|
||||
var/nameless = client.prefs.nameless
|
||||
var/randomname = client.prefs.be_random_name
|
||||
var/randombody = client.prefs.be_random_body
|
||||
if(randombody && (nameless || randomname))
|
||||
return TRUE // somewhat unrecognizable
|
||||
if(client.prefs.slots_joined_as && (client.prefs.default_slot in client.prefs.slots_joined_as))
|
||||
if(notify)
|
||||
to_chat(src, "<span class='userdanger'>You cannot respawn on the same slot. Joined slots: [english_list(client.prefs.slots_joined_as)].")
|
||||
return FALSE
|
||||
if((!nameless && !randomname) && (client.prefs.characters_joined_as && (client.prefs.real_name in client.prefs.characters_joined_as)))
|
||||
if(notify)
|
||||
to_chat(src, "<span class='userdanger'>You cannot respawn on the same character. Joined slots: [english_list(client.prefs.characters_joined_as)].")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Attempts to respawn.
|
||||
*/
|
||||
/mob/dead/observer/verb/respawn()
|
||||
set name = "Respawn"
|
||||
set category = "OOC"
|
||||
|
||||
if(!CONFIG_GET(flag/respawns_enabled))
|
||||
to_chat(src, "<span class='warning'>Respawns are disabled in configuration.</span>")
|
||||
return
|
||||
|
||||
if(client.prefs.dnr_triggered)
|
||||
to_chat(src, "<span class='danger'>You cannot respawn as you have enabled DNR.</span>")
|
||||
return
|
||||
|
||||
var/roundstart_timeleft = (SSticker.round_start_time + (CONFIG_GET(number/respawn_minimum_delay_roundstart) * 600)) - world.time
|
||||
if(roundstart_timeleft > 0)
|
||||
to_chat(src, "<span class='warning'>It's been too short of a time since the round started! Please wait [CEILING(roundstart_timeleft / 600, 0.1)] more minutes.</span>")
|
||||
return
|
||||
|
||||
var/list/banned_modes = CONFIG_GET(keyed_list/respawn_chaos_gamemodes)
|
||||
if(SSticker.mode && banned_modes[lowertext(SSticker.mode.config_tag)])
|
||||
to_chat(src, "<span class='warning'>The current mode tag, [SSticker.mode.config_tag], is not eligible for respawn.</span>")
|
||||
return
|
||||
|
||||
var/timeleft = time_left_to_respawn()
|
||||
if(timeleft)
|
||||
to_chat(src, "<span class='warning'>It's been too short of a time since you died/observed! Please wait [round(timeleft / 600, 0.1)] more minutes.</span>")
|
||||
return
|
||||
do_respawn(TRUE)
|
||||
|
||||
/**
|
||||
* Gets time left until we can respawn. Returns 0 if we can respawn now.
|
||||
*/
|
||||
/mob/dead/observer/verb/time_left_to_respawn()
|
||||
ASSERT(client)
|
||||
return max(0, ((client.prefs.respawn_did_cryo? CONFIG_GET(number/respawn_delay_cryo) : CONFIG_GET(number/respawn_delay)) MINUTES + client.prefs.respawn_time_of_death) - world.time)
|
||||
|
||||
/**
|
||||
* Handles respawning
|
||||
*/
|
||||
/mob/dead/observer/proc/do_respawn(penalize)
|
||||
if(!client)
|
||||
return
|
||||
if(isnull(penalize))
|
||||
penalize = client.prefs.respawn_restrictions_active
|
||||
client.prefs.respawn_restrictions_active = penalize
|
||||
|
||||
message_admins("[key_name_admin(src)] was respawned to lobby [penalize? "with" : "without"] restrictions.")
|
||||
log_game("[key_name(src)] was respawned to lobby [penalize? "with" : "without"] restrictions.")
|
||||
var/mob/dead/new_player/N = transfer_to_lobby()
|
||||
|
||||
to_chat(N, "<span class='userdanger'>You have been respawned to the lobby. \
|
||||
Remember to take heed of rules regarding round knowledge - notably, that ALL past lives are forgotten. \
|
||||
Any character you join as has NO knowledge of round events unless specified otherwise by an admin.</span>")
|
||||
|
||||
/**
|
||||
* Actual proc that removes us and puts us back on lobby
|
||||
*
|
||||
* Returns the new mob.
|
||||
*/
|
||||
/mob/dead/observer/proc/transfer_to_lobby()
|
||||
if(!client) // if no one's in us we can just be deleted
|
||||
qdel(src)
|
||||
return
|
||||
client.screen.Cut()
|
||||
client.view_size.resetToDefault()
|
||||
client.generate_clickcatcher()
|
||||
client.apply_clickcatcher()
|
||||
client.view_size.setDefault(getScreenSize(client.prefs.widescreenpref))
|
||||
client.view_size.resetToDefault()
|
||||
|
||||
var/mob/dead/new_player/M = new /mob/dead/new_player
|
||||
M.ckey = ckey
|
||||
return M
|
||||
@@ -5,7 +5,7 @@
|
||||
silent = FALSE
|
||||
losebreath = 0
|
||||
|
||||
if(!gibbed)
|
||||
if(!gibbed && !HAS_TRAIT(src, TRAIT_DEATHCOMA))
|
||||
emote("deathgasp")
|
||||
|
||||
. = ..()
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
AddComponent(/datum/component/mood)
|
||||
AddComponent(/datum/component/combat_mode)
|
||||
AddElement(/datum/element/flavor_text/carbon, _name = "Flavor Text", _save_key = "flavor_text")
|
||||
AddElement(/datum/element/flavor_text, "", "Temporary Flavor Text", "This should be used only for things pertaining to the current round!")
|
||||
AddElement(/datum/element/flavor_text/carbon/temporary, "", "Set Pose (Temporary Flavor Text)", "This should be used only for things pertaining to the current round!", _save_key = null)
|
||||
AddElement(/datum/element/flavor_text, _name = "OOC Notes", _addendum = "Put information on ERP/vore/lewd-related preferences here. THIS SHOULD NOT CONTAIN REGULAR FLAVORTEXT!!", _always_show = TRUE, _save_key = "ooc_notes", _examine_no_preview = TRUE)
|
||||
|
||||
/mob/living/carbon/human/Destroy()
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
blocks_emissive = EMISSIVE_BLOCK_UNIQUE
|
||||
|
||||
block_parry_data = /datum/block_parry_data/unarmed/human
|
||||
default_block_parry_data = /datum/block_parry_data/unarmed/human
|
||||
|
||||
//Hair colour and style
|
||||
var/hair_color = "000"
|
||||
@@ -98,20 +99,54 @@
|
||||
parry_failed_clickcd_duration = 0.4
|
||||
|
||||
parry_data = list( // yeah it's snowflake
|
||||
"HUMAN_PARRY_STAGGER" = 3 SECONDS,
|
||||
"HUMAN_PARRY_PUNCH" = TRUE,
|
||||
"HUMAN_PARRY_MININUM_EFFICIENCY" = 0.9
|
||||
"UNARMED_PARRY_STAGGER" = 3 SECONDS,
|
||||
"UNARMED_PARRY_PUNCH" = TRUE,
|
||||
"UNARMED_PARRY_MININUM_EFFICIENCY" = 90
|
||||
)
|
||||
|
||||
/mob/living/carbon/human/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
|
||||
/mob/living/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
|
||||
var/datum/block_parry_data/D = return_block_parry_datum(block_parry_data)
|
||||
. = ..()
|
||||
if(!owner.Adjacent(attacker))
|
||||
return ..()
|
||||
if(parry_efficiency < D.parry_data["HUMAN_PARRY_MINIMUM_EFFICIENCY"])
|
||||
return ..()
|
||||
return
|
||||
if(parry_efficiency < D.parry_data["UNARMED_PARRY_MINIMUM_EFFICIENCY"])
|
||||
return
|
||||
visible_message("<span class='warning'>[src] strikes back perfectly at [attacker], staggering them!</span>")
|
||||
if(D.parry_data["HUMAN_PARRY_PUNCH"])
|
||||
if(D.parry_data["UNARMED_PARRY_PUNCH"])
|
||||
UnarmedAttack(attacker, TRUE, INTENT_HARM, ATTACK_IS_PARRY_COUNTERATTACK | ATTACK_IGNORE_ACTION | ATTACK_IGNORE_CLICKDELAY | NO_AUTO_CLICKDELAY_HANDLING)
|
||||
var/mob/living/L = attacker
|
||||
if(istype(L))
|
||||
L.Stagger(D.parry_data["HUMAN_PARRY_STAGGER"])
|
||||
L.Stagger(D.parry_data["UNARMED_PARRY_STAGGER"])
|
||||
|
||||
/// Unarmed parry data for pugilists
|
||||
/datum/block_parry_data/unarmed/pugilist
|
||||
parry_respect_clickdelay = FALSE
|
||||
parry_stamina_cost = 4
|
||||
parry_attack_types = ATTACK_TYPE_UNARMED | ATTACK_TYPE_PROJECTILE | ATTACK_TYPE_TACKLE | ATTACK_TYPE_THROWN | ATTACK_TYPE_MELEE
|
||||
parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING
|
||||
|
||||
parry_time_windup = 0
|
||||
parry_time_spindown = 0
|
||||
parry_time_active = 5
|
||||
|
||||
parry_time_perfect = 1.5
|
||||
parry_time_perfect_leeway = 1.5
|
||||
parry_imperfect_falloff_percent = 20
|
||||
parry_efficiency_perfect = 100
|
||||
parry_efficiency_perfect_override = list(
|
||||
ATTACK_TYPE_PROJECTILE_TEXT = 60,
|
||||
)
|
||||
|
||||
parry_efficiency_considered_successful = 0.01
|
||||
parry_efficiency_to_counterattack = 0.01
|
||||
parry_max_attacks = INFINITY
|
||||
parry_failed_cooldown_duration = 1.5 SECONDS
|
||||
parry_failed_stagger_duration = 0
|
||||
parry_cooldown = 0
|
||||
parry_failed_clickcd_duration = 0.8
|
||||
|
||||
parry_data = list( // yeah it's snowflake
|
||||
"UNARMED_PARRY_STAGGER" = 3 SECONDS,
|
||||
"UNARMED_PARRY_PUNCH" = TRUE,
|
||||
"UNARMED_PARRY_MININUM_EFFICIENCY" = 90
|
||||
)
|
||||
|
||||
@@ -62,7 +62,6 @@
|
||||
|
||||
H.add_movespeed_modifier(/datum/movespeed_modifier/slime_puddle)
|
||||
|
||||
H.layer -= 1 //go one layer down so people go over you
|
||||
ENABLE_BITFIELD(H.pass_flags, PASSMOB) //this actually lets people pass over you
|
||||
squeak = H.AddComponent(/datum/component/squeak, custom_sounds = list('sound/effects/blobattack.ogg')) //blorble noise when people step on you
|
||||
|
||||
@@ -103,7 +102,6 @@
|
||||
REMOVE_TRAIT(H, TRAIT_HUMAN_NO_RENDER, SLIMEPUDDLE_TRAIT)
|
||||
H.update_disabled_bodyparts(silent = TRUE)
|
||||
H.remove_movespeed_modifier(/datum/movespeed_modifier/slime_puddle)
|
||||
H.layer += 1 //go one layer back above!
|
||||
DISABLE_BITFIELD(H.pass_flags, PASSMOB)
|
||||
is_puddle = FALSE
|
||||
if(squeak)
|
||||
|
||||
@@ -139,6 +139,18 @@
|
||||
if(E.web_ready == FALSE)
|
||||
to_chat(H, "<span class='warning'>You need to wait awhile to regenerate web fluid.</span>")
|
||||
return
|
||||
if(!H.Adjacent(A)) //No.
|
||||
return
|
||||
if(!isliving(A) && A.anchored)
|
||||
to_chat(H, "<span class='warning'>[A] is bolted to the floor!</span>")
|
||||
return
|
||||
if(istype(A, /obj/structure/arachnid))
|
||||
to_chat(H, "<span class='warning'>No double wrapping.</span>")
|
||||
return
|
||||
if(istype(A, /obj/effect))
|
||||
to_chat(H, "<span class='warning'>You cannot wrap this.</span>")
|
||||
return
|
||||
H.visible_message("<span class='danger'>[H] starts to wrap [A] into a cocoon!</span>","<span class='warning'>You start to wrap [A] into a cocoon.</span>")
|
||||
if(!do_after(H, 10 SECONDS, 1, A))
|
||||
to_chat(H, "<span class='warning'>Your web spinning was interrupted!</span>")
|
||||
return
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
/datum/species/dullahan/check_roundstart_eligible()
|
||||
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
|
||||
return TRUE
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/species/dullahan/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
|
||||
. = ..()
|
||||
|
||||
@@ -66,6 +66,10 @@
|
||||
GLOB.alive_mob_list -= src
|
||||
if(!gibbed)
|
||||
GLOB.dead_mob_list += src
|
||||
if(ckey)
|
||||
var/datum/preferences/P = GLOB.preferences_datums[ckey]
|
||||
if(P)
|
||||
P.respawn_time_of_death = world.time
|
||||
set_drugginess(0)
|
||||
set_disgust(0)
|
||||
SetSleeping(0, 0)
|
||||
|
||||
@@ -264,9 +264,9 @@
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/has_tail()
|
||||
if(!dna || !dna.features)
|
||||
if(!dna || !dna.species)
|
||||
return ..()
|
||||
var/list/L = dna.features // caches list because i refuse to type it out and because performance
|
||||
var/list/L = dna.species.mutant_bodyparts // caches list because i refuse to type it out and because performance
|
||||
return (L["mam_tail"] && (L["mam_tail"] != "None")) || (L["tail_human"] && (L["tail_human"] != "None")) || (L["tail_lizard"] && (L["tail_lizard"] != "None"))
|
||||
|
||||
/mob/living/start_pulling(atom/movable/AM, state, force = pull_force, supress_message = FALSE)
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
handle_parry_ending_effects(data, effect_text)
|
||||
parrying = NOT_PARRYING
|
||||
parry_start_time = 0
|
||||
parry_end_time_last = world.time
|
||||
parry_end_time_last = world.time + (successful? 0 : data.parry_failed_cooldown_duration)
|
||||
successful_parries = null
|
||||
|
||||
/**
|
||||
|
||||
@@ -154,6 +154,8 @@ GLOBAL_LIST_EMPTY(block_parry_data)
|
||||
var/parry_failed_stagger_duration = 3.5 SECONDS
|
||||
/// Clickdelay duration post-parry if you fail to parry an attack
|
||||
var/parry_failed_clickcd_duration = 2 SECONDS
|
||||
/// Parry cooldown post-parry if failed. This is ADDED to parry_cooldown!!!
|
||||
var/parry_failed_cooldown_duration = 0 SECONDS
|
||||
|
||||
/**
|
||||
* Quirky proc to get average of flags in list that are in attack_type because why is attack_type a flag.
|
||||
|
||||
@@ -32,6 +32,10 @@
|
||||
// Combat - Blocking/Parrying system
|
||||
/// Our block_parry_data for unarmed blocks/parries. Currently only used for parrying, as unarmed block isn't implemented yet. YOU MUST RUN [get_block_parry_data(this)] INSTEAD OF DIRECTLY ACCESSING!
|
||||
var/datum/block_parry_data/block_parry_data = /datum/block_parry_data // defaults to *something* because [combat_flags] dictates whether or not we can unarmed block/parry.
|
||||
/// Default
|
||||
var/datum/block_parry_data/default_block_parry_data = /datum/block_parry_data
|
||||
/// If we're a pugilist
|
||||
var/datum/block_parry_data/pugilist_block_parry_data = /datum/block_parry_data/unarmed/pugilist
|
||||
// Blocking
|
||||
/// The item the user is actively blocking with if any.
|
||||
var/obj/item/active_block_item
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
/// IN THE FUTURE, WE WILL PROBABLY REFACTOR TO LESSEN THE NEED FOR UPDATE_MOBILITY, BUT FOR NOW.. WE CAN START DOING THIS.
|
||||
/// FOR BLOCKING MOVEMENT, USE TRAIT_MOBILITY_NOMOVE AS MUCH AS POSSIBLE. IT WILL MAKE REFACTORS IN THE FUTURE EASIER.
|
||||
/mob/living/ComponentInitialize()
|
||||
. = ..()
|
||||
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOMOVE), .proc/update_mobility)
|
||||
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOPICKUP), .proc/update_mobility)
|
||||
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOUSE), .proc/update_mobility)
|
||||
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOREST), .proc/update_mobility)
|
||||
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_LIVING_NO_DENSITY), .proc/update_density)
|
||||
|
||||
//Stuff like mobility flag updates, resting updates, etc.
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/// IN THE FUTURE, WE WILL PROBABLY REFACTOR TO LESSEN THE NEED FOR UPDATE_MOBILITY, BUT FOR NOW.. WE CAN START DOING THIS.
|
||||
/// FOR BLOCKING MOVEMENT, USE TRAIT_MOBILITY_NOMOVE AS MUCH AS POSSIBLE. IT WILL MAKE REFACTORS IN THE FUTURE EASIER.
|
||||
/mob/living/ComponentInitialize()
|
||||
. = ..()
|
||||
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOMOVE), .proc/update_mobility)
|
||||
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOPICKUP), .proc/update_mobility)
|
||||
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOUSE), .proc/update_mobility)
|
||||
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOREST), .proc/update_mobility)
|
||||
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_LIVING_NO_DENSITY), .proc/update_density)
|
||||
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_PUGILIST), .proc/update_pugilism)
|
||||
|
||||
/mob/living/proc/update_pugilism()
|
||||
if(HAS_TRAIT(src, TRAIT_PUGILIST))
|
||||
combat_flags |= COMBAT_FLAG_UNARMED_PARRY
|
||||
block_parry_data = pugilist_block_parry_data
|
||||
else
|
||||
var/initial_combat_flags = initial(combat_flags)
|
||||
if(!(initial_combat_flags & COMBAT_FLAG_UNARMED_PARRY))
|
||||
combat_flags &= ~COMBAT_FLAG_UNARMED_PARRY
|
||||
block_parry_data = default_block_parry_data
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user