diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 192c91ecc5..a4d6c07526 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -312,7 +312,7 @@ var/list/bag_of_items = list(sword, apple, coinpouch, sword, sword) var/obj/item/sword/best_sword for(var/obj/item/sword/S in bag_of_items) if(!best_sword || S.damage > best_sword.damage) - best_sword = S + best_sword = S ``` The above is a simple proc for checking all swords in a container and returning the one with the highest damage, and it uses DM's standard syntax for a for-loop by specifying a type in the variable of the for's header that DM interprets as a type to filter by. It performs this filter using ```istype()``` (or some internal-magic similar to ```istype()``` - this is BYOND, after all). This is fine in its current state for ```bag_of_items```, but if ```bag_of_items``` contained ONLY swords, or only SUBTYPES of swords, then the above is inefficient. For example: ```DM @@ -320,7 +320,7 @@ var/list/bag_of_swords = list(sword, sword, sword, sword) var/obj/item/sword/best_sword for(var/obj/item/sword/S in bag_of_swords) if(!best_sword || S.damage > best_sword.damage) - best_sword = S + best_sword = S ``` specifies a type for DM to filter by. @@ -332,7 +332,7 @@ var/obj/item/sword/best_sword for(var/s in bag_of_swords) var/obj/item/sword/S = s if(!best_sword || S.damage > best_sword.damage) - best_sword = S + best_sword = S ``` Of course, if the list contains data of a mixed type then the above optimisation is DANGEROUS, as it will blindly typecast all data in the list as the specified type, even if it isn't really that type, causing runtime errors. @@ -355,9 +355,9 @@ DM has a var keyword, called global. This var keyword is for vars inside of type ```DM mob - var - global - thing = TRUE + var + global + thing = TRUE ``` This does NOT mean that you can access it everywhere like a global var. Instead, it means that that var will only exist once for all instances of its type, in this case that var will only exist once for all mobs - it's shared across everything in its type. (Much more like the keyword `static` in other languages like PHP/C++/C#/Java) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7855fd5782..1332358e04 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,4 +1,5 @@ -[Changelogs]: # (Your PR should contain a detailed changelog of notable changes, titled and categorized appropriately. This includes, new features, sprites, sounds, balance changes, admin tools, map edits, removals, big refactors, config changes, hosting changes and important fixes. An example changelog has been provided below for you to edit. If you need additional help, read https://github.com/tgstation/tgstation/wiki/Changelogs) +[Changelogs]: # (Please make a changelog if you're adding, removing or changing content that'll affect players. This includes, but is not limited to, new features, sprites, sounds; balance changes; map edits and important fixes. An example changelog has been provided below for you to edit or remove. If you need help, read https://github.com/tgstation/tgstation/wiki/Changelogs) + :cl: optional name here add: Added new things @@ -7,16 +8,13 @@ del: Removed old things tweak: tweaked a few things balance: rebalanced something fix: fixed a few things +wip: added a few works in progress soundadd: added a new sound thingy sounddel: removed an old sound thingy imageadd: added some icons and images imagedel: deleted some icons and images spellcheck: fixed a few typos -code: changed some code -refactor: refactored some code -config: changed some config setting -admin: messed with admin stuff -server: something server ops should know +experiment: added an experimental thingy /:cl: [why]: # (Please add a short description [two lines down] of why you think these changes would benefit the game. If you can't justify it in words, it might not be worth adding.) diff --git a/README.md b/README.md index cdf07dab25..e2b9bbfbbc 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,21 @@ -## Citadel Station 13 codebase +<<<<<<< HEAD +##Citadel Station 13
+Based and maintained from /tg/station.
+======= [![Build Status](https://travis-ci.org/tgstation/tgstation.png)](https://travis-ci.org/tgstation/tgstation) [![Krihelimeter](https://www.krihelinator.xyz/badge/tgstation/tgstation)](https://www.krihelinator.xyz) [![Percentage of issues still open](https://isitmaintained.com/badge/open/tgstation/tgstation.svg)](https://isitmaintained.com/project/tgstation/tgstation "Percentage of issues still open") [![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/tgstation/tgstation.svg)](https://isitmaintained.com/project/tgstation/tgstation "Average time to resolve an issue") ![Coverage](https://img.shields.io/badge/coverage---2%25-red.svg) [![forthebadge](https://forthebadge.com/images/badges/built-with-resentment.svg)](https://forthebadge.com) [![forthebadge](https://forthebadge.com/images/badges/contains-technical-debt.svg)](https://forthebadge.com) [![forinfinityandbyond](https://user-images.githubusercontent.com/5211576/29499758-4efff304-85e6-11e7-8267-62919c3688a9.gif)](https://www.reddit.com/r/SS13/comments/5oplxp/what_is_the_main_problem_with_byond_as_an_engine/dclbu1a) +>>>>>>> c47dde9... Merge pull request #33172 from praisenarsie/patch-12 [![Build Status](https://api.travis-ci.org/Citadel-Station-13/Citadel-Station-13.png)](https://travis-ci.org/Citadel-Station-13/Citadel-Station-13) [![Krihelimeter](http://www.krihelinator.xyz/badge/Citadel-Station-13/Citadel-Station-13)](http://www.krihelinator.xyz) [![Percentage of issues still open](http://isitmaintained.com/badge/open/Citadel-Station-13/Citadel-Station-13.svg)](http://isitmaintained.com/project/Citadel-Station-13/Citadel-Station-13 "Percentage of issues still open") [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/Citadel-Station-13/Citadel-Station-13.svg)](http://isitmaintained.com/project/Citadel-Station-13/Citadel-Station-13 "Average time to resolve an issue") **Upstream Information**
-**Website:** https://www.tgstation13.org
+**Website:** http://www.tgstation13.org
**Code:** https://github.com/tgstation/tgstation
-**Wiki** https://tgstation13.org/wiki/Main_Page
+**Wiki** http://tgstation13.org/wiki/Main_Page
**IRC:** irc://irc.rizon.net/coderbus or if you dont have an IRC client, you can click [here](https://kiwiirc.com/client/irc.rizon.net:6667/?&theme=cli#coderbus).
**Citadel Station Information**
@@ -22,10 +26,10 @@ ## 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 https://www.tgstation13.org/wiki/Downloading_the_source_code +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: https://www.tgstation13.org/wiki/Setting_up_git +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 @@ -99,7 +103,7 @@ https://github.com/tgstation/tgstation-server /tg/station currently comes equipped with five maps. -* [BoxStation (default)](https://tgstation13.org/wiki/Boxstation) +* [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) @@ -112,7 +116,7 @@ The map that will be loaded for the upcoming round is determined by reading data 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](https://tgstation13.org/wiki/Map_Merger) +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 @@ -126,7 +130,6 @@ To enable an away mission open `config/awaymissionconfig.txt` and uncomment one 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 - ## IRC BOT SETUP Included in the repository is a python3 compatible IRC bot capable of relaying adminhelps to a specified @@ -138,7 +141,7 @@ 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](https://www.gnu.org/licenses/agpl-3.0.html). +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.) @@ -147,11 +150,11 @@ See LICENSE and GPLv3.txt for more details. 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](https://creativecommons.org/licenses/by-sa/4.0/). +tgui assets are licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/). The TGS3 API is licensed as a subproject under the MIT license. See tgui/LICENSE.md for the MIT license. See tgui/assets/fonts/SIL-OFL-1.1-LICENSE.md for the SIL Open Font 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. -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. +All assets including icons and sound are under a [Creative Commons 3.0 BY-SA license](http://creativecommons.org/licenses/by-sa/3.0/) unless otherwise indicated. diff --git a/SQL/database_changelog.txt b/SQL/database_changelog.txt index 9f0f2c50c0..e2a172e107 100644 --- a/SQL/database_changelog.txt +++ b/SQL/database_changelog.txt @@ -383,4 +383,4 @@ UPDATE erro_library SET deleted = 1 WHERE id = someid (Replace someid with the id of the book you want to soft delete.) ----------------------------------------------------- +---------------------------------------------------- \ No newline at end of file diff --git a/SQL/errofreedatabase.sql b/SQL/errofreedatabase.sql index 7f23fcc861..7d6ea4561c 100644 --- a/SQL/errofreedatabase.sql +++ b/SQL/errofreedatabase.sql @@ -12,4 +12,4 @@ ALTER TABLE erro_poll_option RENAME TO SS13_poll_option; ALTER TABLE erro_poll_question RENAME TO SS13_poll_question; ALTER TABLE erro_poll_textreply RENAME TO SS13_poll_textreply; ALTER TABLE erro_poll_vote RENAME TO SS13_poll_vote; -ALTER TABLE erro_watch RENAME TO SS13_watch; +ALTER TABLE erro_watch RENAME TO SS13_watch; \ No newline at end of file diff --git a/SQL/feedback_conversion_2017-11-12.py b/SQL/feedback_conversion_2017-11-12.py index 8a60e10b7e..b8577460b3 100644 --- a/SQL/feedback_conversion_2017-11-12.py +++ b/SQL/feedback_conversion_2017-11-12.py @@ -5,10 +5,6 @@ #It can be downloaded from command line with pip: #pip install mysqlclient # -#tgstation no longer supports MySQL which has been superseded by MariaDB, a drop-in replacement. -#Before running this script you will need to migrate to MariaDB. -#Migrating is very easy to do, for details on how see: https://mariadb.com/kb/en/library/upgrading-from-mysql-to-mariadb/ -# #You will also have to create a new feedback table for inserting converted data to per the schema: #CREATE TABLE `feedback_new` ( # `id` int(11) unsigned NOT NULL AUTO_INCREMENT, @@ -480,25 +476,11 @@ parser.add_argument("newtable", help="Name of the new table to insert to, can't args = parser.parse_args() db=MySQLdb.connect(host=args.address, user=args.username, passwd=args.password, db=args.database) cursor=db.cursor() -cursor.execute("SELECT @@GLOBAL.version_comment") -db_version = "".join([x for x in cursor.fetchone()]) -database_mysql = False -if 'MySQL' in db_version: - database_mysql = True -elif 'mariadb' not in db_version: - choice = input("Unable to determine database version installed, are you using MySQL? Type Yes or No and press enter...").lower() - if choice == "yes": - database_mysql = True -if database_mysql == True: - print("WARNING Database detected to be MySQL: tgstation no longer supports MySQL which has been superseded by MariaDB, a drop-in replacement.\nBefore running this script you will need to migrate to MariaDB.\nMigrating is very easy to do, for details on how see: https://mariadb.com/kb/en/library/upgrading-from-mysql-to-mariadb/") - input("Press enter to quit...") - quit() current_table = args.curtable new_table = args.newtable -cursor.execute("SELECT max(id), max(round_id) FROM {0}".format(current_table)) +cursor.execute("SELECT max(id) FROM {0}".format(current_table)) query_id = cursor.fetchone() max_id = query_id[0] -max_round_id = query_id[1] start_time = datetime.now() print("Beginning conversion at {0}".format(start_time.strftime("%Y-%m-%d %H:%M:%S"))) try: @@ -511,7 +493,7 @@ try: if not query_row: continue else: - if current_round != query_row[2] or current_round == max_round_id: + if current_round != query_row[2]: multirows_completed.clear() if query_values: query_values = query_values[:-1] @@ -542,11 +524,8 @@ try: print("Conversion completed at {0}".format(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) print("Script duration: {0}".format(end_time - start_time)) except Exception as e: - cursor.execute("SELECT round_id FROM {0} WHERE id = {1}".format(current_table, current_id-1)) - query_round_id = cursor.fetchone() end_time = datetime.now() print("Error encountered on row ID {0} at {1}".format(current_id, datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) - print("Note SQL insertion errors will be due to data from round ID {0}".format(query_round_id[0])) #since data is inserted when the round id changes on a new row print("Script duration: {0}".format(end_time - start_time)) cursor.execute("TRUNCATE {0} ".format(new_table)) raise e diff --git a/SQL/optimisations_2017-02-19.sql b/SQL/optimisations_2017-02-19.sql index 1bb19cc667..b9017497ed 100644 --- a/SQL/optimisations_2017-02-19.sql +++ b/SQL/optimisations_2017-02-19.sql @@ -226,4 +226,4 @@ ALTER TABLE `poll_vote` , ADD INDEX `idx_pvote_optionid_ckey` (`optionid` ASC, `ckey` ASC); ALTER TABLE `poll_textreply` - ADD INDEX `idx_ptext_pollid_ckey` (`pollid` ASC, `ckey` ASC); + ADD INDEX `idx_ptext_pollid_ckey` (`pollid` ASC, `ckey` ASC); \ No newline at end of file diff --git a/SQL/tgstation_schema.sql b/SQL/tgstation_schema.sql index 8ec2fcfc41..2d914161d3 100644 --- a/SQL/tgstation_schema.sql +++ b/SQL/tgstation_schema.sql @@ -432,4 +432,4 @@ CREATE TABLE `schema_revision` ( /*!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 */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; \ No newline at end of file diff --git a/SQL/tgstation_schema_prefixed.sql b/SQL/tgstation_schema_prefixed.sql index 8bc768967d..2d44c8eac0 100644 --- a/SQL/tgstation_schema_prefixed.sql +++ b/SQL/tgstation_schema_prefixed.sql @@ -432,4 +432,4 @@ CREATE TABLE `SS13_schema_revision` ( /*!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 */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; \ No newline at end of file diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 50055ad67c..5a834b1f87 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -127,7 +127,7 @@ #define TOXINLOVER 24 #define DIGITIGRADE 25 //Uses weird leg sprites. Optional for Lizards, required for ashwalkers. Don't give it to other races unless you make sprites for this (see human_parts_greyscale.dmi) #define NO_UNDERWEAR 26 -#define NOLIVER 27 +#define NOLIVER 27 #define NOSTOMACH 28 #define NO_DNA_COPY 29 #define DRINKSBLOOD 30 diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index ded699c69d..65d028ea34 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -1,5 +1,79 @@ //A set of constants used to determine which type of mute an admin wishes to apply: //Please read and understand the muting/automuting stuff before changing these. MUTE_IC_AUTO etc = (MUTE_IC << 1) +//Therefore there needs to be a gap between the flags_1 for the automute flags_1 +#define MUTE_IC 1 +#define MUTE_OOC 2 +#define MUTE_PRAY 4 +#define MUTE_ADMINHELP 8 +#define MUTE_DEADCHAT 16 +#define MUTE_ALL 31 + +//Some constants for DB_Ban +#define BANTYPE_PERMA 1 +#define BANTYPE_TEMP 2 +#define BANTYPE_JOB_PERMA 3 +#define BANTYPE_JOB_TEMP 4 +#define BANTYPE_ANY_FULLBAN 5 //used to locate stuff to unban. + +#define BANTYPE_ADMIN_PERMA 7 +#define BANTYPE_ADMIN_TEMP 8 +#define BANTYPE_ANY_JOB 9 //used to remove jobbans + +//Please don't edit these values without speaking to Errorage first ~Carn +//Admin Permissions +#define R_BUILDMODE 1 +#define R_ADMIN 2 +#define R_BAN 4 +#define R_FUN 8 +#define R_SERVER 16 +#define R_DEBUG 32 +#define R_POSSESS 64 +#define R_PERMISSIONS 128 +#define R_STEALTH 256 +#define R_POLL 512 +#define R_VAREDIT 1024 +#define R_SOUNDS 2048 +#define R_SPAWN 4096 + +#if DM_VERSION > 512 +#error Remove the flag below , its been long enough +#endif +//legacy , remove post 512, it was replaced by R_POLL +#define R_REJUVINATE 2 + +#define R_MAXPERMISSION 4096 //This holds the maximum value for a permission. It is used in iteration, so keep it updated. + +#define ADMIN_QUE(user) "(?)" +#define ADMIN_FLW(user) "(FLW)" +#define ADMIN_PP(user) "(PP)" +#define ADMIN_VV(atom) "(VV)" +#define ADMIN_SM(user) "(SM)" +#define ADMIN_TP(user) "(TP)" +#define ADMIN_KICK(user) "(KICK)" +#define ADMIN_CENTCOM_REPLY(user) "(RPLY)" +#define ADMIN_SYNDICATE_REPLY(user) "(RPLY)" +#define ADMIN_SC(user) "(SC)" +#define ADMIN_SMITE(user) "(SMITE)" +#define ADMIN_LOOKUP(user) "[key_name_admin(user)][ADMIN_QUE(user)]" +#define ADMIN_LOOKUPFLW(user) "[key_name_admin(user)][ADMIN_QUE(user)] [ADMIN_FLW(user)]" +#define ADMIN_SET_SD_CODE "(SETCODE)" +#define ADMIN_FULLMONTY_NONAME(user) "[ADMIN_QUE(user)] [ADMIN_PP(user)] [ADMIN_VV(user)] [ADMIN_SM(user)] [ADMIN_FLW(user)] [ADMIN_TP(user)] [ADMIN_INDIVIDUALLOG(user)] [ADMIN_SMITE(user)]" +#define ADMIN_FULLMONTY(user) "[key_name_admin(user)] [ADMIN_FULLMONTY_NONAME(user)]" +#define ADMIN_JMP(src) "(JMP)" +#define COORD(src) "[src ? "([src.x],[src.y],[src.z])" : "nonexistent location"]" +#define ADMIN_COORDJMP(src) "[src ? "[COORD(src)] [ADMIN_JMP(src)]" : "nonexistent location"]" +#define ADMIN_INDIVIDUALLOG(user) "(LOGS)" + +#define ADMIN_PUNISHMENT_LIGHTNING "Lightning bolt" +#define ADMIN_PUNISHMENT_BRAINDAMAGE "Brain damage" +#define ADMIN_PUNISHMENT_GIB "Gib" +#define ADMIN_PUNISHMENT_BSA "Bluespace Artillery Device" + +#define AHELP_ACTIVE 1 +#define AHELP_CLOSED 2 +#define AHELP_RESOLVED 3 +//A set of constants used to determine which type of mute an admin wishes to apply: +//Please read and understand the muting/automuting stuff before changing these. MUTE_IC_AUTO etc = (MUTE_IC << 1) //Therefore there needs to be a gap between the flags for the automute flags #define MUTE_IC 1 #define MUTE_OOC 2 diff --git a/code/__DEFINES/clockcult.dm b/code/__DEFINES/clockcult.dm index 7451c42cab..d51dbfd047 100644 --- a/code/__DEFINES/clockcult.dm +++ b/code/__DEFINES/clockcult.dm @@ -6,6 +6,7 @@ #define HIEROPHANT_ANSIBLE "hierophant_ansible" //Use this for construction-related scripture! GLOBAL_VAR_INIT(clockwork_construction_value, 0) //The total value of all structures built by the clockwork cult +GLOBAL_VAR_INIT(clockwork_caches, 0) //How many clockwork caches exist in the world (not each individual) GLOBAL_VAR_INIT(clockwork_vitality, 0) //How much Vitality is stored, total GLOBAL_VAR_INIT(clockwork_power, 0) //How many watts of power are globally available to the clockwork cult diff --git a/code/__DEFINES/configuration.dm b/code/__DEFINES/configuration.dm index c4ef8e6606..3db0ca24c2 100644 --- a/code/__DEFINES/configuration.dm +++ b/code/__DEFINES/configuration.dm @@ -1,6 +1,8 @@ //config files +#define CONFIG_DEF(X) /datum/config_entry/##X { resident_file = CURRENT_RESIDENT_FILE }; /datum/config_entry/##X #define CONFIG_GET(X) global.config.Get(/datum/config_entry/##X) #define CONFIG_SET(X, Y) global.config.Set(/datum/config_entry/##X, ##Y) +#define CONFIG_TWEAK(X) /datum/config_entry/##X #define CONFIG_MAPS_FILE "maps.txt" diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm index d2de6f9100..a1842648ac 100644 --- a/code/__DEFINES/inventory.dm +++ b/code/__DEFINES/inventory.dm @@ -86,7 +86,7 @@ . = SLOT_POCKET -//Bit flags for the flags_inv variable, which determine when a piece of clothing hides another. IE a helmet hiding glasses. +//Bit flags_1 for the flags_inv variable, which determine when a piece of clothing hides another. IE a helmet hiding glasses. #define HIDEGLOVES 1 #define HIDESUITSTORAGE 2 #define HIDEJUMPSUIT 4 //these first four are only used in exterior suits @@ -134,17 +134,17 @@ #define THERMAL_PROTECTION_HAND_LEFT 0.025 #define THERMAL_PROTECTION_HAND_RIGHT 0.025 -//flags for female outfits: How much the game can safely "take off" the uniform without it looking weird +//flags_1 for female outfits: How much the game can safely "take off" the uniform without it looking weird #define NO_FEMALE_UNIFORM 0 #define FEMALE_UNIFORM_FULL 1 #define FEMALE_UNIFORM_TOP 2 -//flags for alternate styles: These are hard sprited so don't set this if you didn't put the effort in +//flags_1 for alternate styles: These are hard sprited so don't set this if you didn't put the effort in #define NORMAL_STYLE 0 #define ALT_STYLE 1 #define DIGITIGRADE_STYLE 2 -//flags for outfits that have mutantrace variants (try not to use this): Currently only needed if you're trying to add tight fitting bootyshorts +//flags_1 for outfits that have mutantrace variants (try not to use this): Currently only needed if you're trying to add tight fitting bootyshorts #define NO_MUTANTRACE_VARIATION 0 #define MUTANTRACE_VARIATION 1 @@ -152,9 +152,9 @@ #define FULL_DIGITIGRADE 1 #define SQUISHED_DIGITIGRADE 2 -//flags for covering body parts +//flags_1 for covering body parts #define GLASSESCOVERSEYES 1 -#define MASKCOVERSEYES 2 // get rid of some of the other retardation in these flags +#define MASKCOVERSEYES 2 // get rid of some of the other retardation in these flags_1 #define HEADCOVERSEYES 4 // feel free to realloc these numbers for other purposes #define MASKCOVERSMOUTH 8 // on other items, these are just for mask/head #define HEADCOVERSMOUTH 16 @@ -199,8 +199,7 @@ GLOBAL_LIST_INIT(detective_vest_allowed, typecacheof(list( /obj/item/reagent_containers/spray/pepper, /obj/item/restraints/handcuffs, /obj/item/storage/fancy/cigarettes, - /obj/item/tank/internals/emergency_oxygen, - /obj/item/tank/internals/plasmaman))) + /obj/item/tank/internals/emergency_oxygen))) GLOBAL_LIST_INIT(security_vest_allowed, typecacheof(list( /obj/item/ammo_box, @@ -213,8 +212,7 @@ GLOBAL_LIST_INIT(security_vest_allowed, typecacheof(list( /obj/item/melee/classic_baton/telescopic, /obj/item/reagent_containers/spray/pepper, /obj/item/restraints/handcuffs, - /obj/item/tank/internals/emergency_oxygen, - /obj/item/tank/internals/plasmaman))) + /obj/item/tank/internals/emergency_oxygen))) GLOBAL_LIST_INIT(security_wintercoat_allowed, typecacheof(list( /obj/item/ammo_box, @@ -229,5 +227,4 @@ GLOBAL_LIST_INIT(security_wintercoat_allowed, typecacheof(list( /obj/item/reagent_containers/spray/pepper, /obj/item/restraints/handcuffs, /obj/item/tank/internals/emergency_oxygen, - /obj/item/tank/internals/plasmaman, /obj/item/toy))) diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index d7a5356f0f..b6133df287 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -1,52 +1,52 @@ - -//Preference toggles -#define SOUND_ADMINHELP 1 -#define SOUND_MIDI 2 -#define SOUND_AMBIENCE 4 -#define SOUND_LOBBY 8 -#define MEMBER_PUBLIC 16 -#define INTENT_STYLE 32 -#define MIDROUND_ANTAG 64 -#define SOUND_INSTRUMENTS 128 -#define SOUND_SHIP_AMBIENCE 256 -#define SOUND_PRAYERS 512 -#define ANNOUNCE_LOGIN 1024 -#define SOUND_ANNOUNCEMENTS 2048 -#define DISABLE_DEATHRATTLE 4096 -#define DISABLE_ARRIVALRATTLE 8192 - -#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|MEMBER_PUBLIC|INTENT_STYLE|MIDROUND_ANTAG|SOUND_INSTRUMENTS|SOUND_SHIP_AMBIENCE|SOUND_PRAYERS|SOUND_ANNOUNCEMENTS) - -//Chat toggles -#define CHAT_OOC 1 -#define CHAT_DEAD 2 -#define CHAT_GHOSTEARS 4 -#define CHAT_GHOSTSIGHT 8 -#define CHAT_PRAYER 16 -#define CHAT_RADIO 32 -#define CHAT_PULLR 64 -#define CHAT_GHOSTWHISPER 128 -#define CHAT_GHOSTPDA 256 -#define CHAT_GHOSTRADIO 512 -#define CHAT_LOOC 1024 - -#define TOGGLES_DEFAULT_CHAT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_PULLR|CHAT_GHOSTWHISPER|CHAT_GHOSTPDA|CHAT_GHOSTRADIO|CHAT_LOOC) - -#define PARALLAX_INSANE -1 //for show offs -#define PARALLAX_HIGH 0 //default. -#define PARALLAX_MED 1 -#define PARALLAX_LOW 2 -#define PARALLAX_DISABLE 3 //this option must be the highest number - -#define PARALLAX_DELAY_DEFAULT world.tick_lag -#define PARALLAX_DELAY_MED 1 -#define PARALLAX_DELAY_LOW 2 - -#define SEC_DEPT_NONE "None" -#define SEC_DEPT_RANDOM "Random" -#define SEC_DEPT_ENGINEERING "Engineering" -#define SEC_DEPT_MEDICAL "Medical" -#define SEC_DEPT_SCIENCE "Science" + +//Preference toggles +#define SOUND_ADMINHELP 1 +#define SOUND_MIDI 2 +#define SOUND_AMBIENCE 4 +#define SOUND_LOBBY 8 +#define MEMBER_PUBLIC 16 +#define INTENT_STYLE 32 +#define MIDROUND_ANTAG 64 +#define SOUND_INSTRUMENTS 128 +#define SOUND_SHIP_AMBIENCE 256 +#define SOUND_PRAYERS 512 +#define ANNOUNCE_LOGIN 1024 +#define SOUND_ANNOUNCEMENTS 2048 +#define DISABLE_DEATHRATTLE 4096 +#define DISABLE_ARRIVALRATTLE 8192 + +#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|MEMBER_PUBLIC|INTENT_STYLE|MIDROUND_ANTAG|SOUND_INSTRUMENTS|SOUND_SHIP_AMBIENCE|SOUND_PRAYERS|SOUND_ANNOUNCEMENTS) + +//Chat toggles +#define CHAT_OOC 1 +#define CHAT_DEAD 2 +#define CHAT_GHOSTEARS 4 +#define CHAT_GHOSTSIGHT 8 +#define CHAT_PRAYER 16 +#define CHAT_RADIO 32 +#define CHAT_PULLR 64 +#define CHAT_GHOSTWHISPER 128 +#define CHAT_GHOSTPDA 256 +#define CHAT_GHOSTRADIO 512 +#define CHAT_LOOC 1024 + +#define TOGGLES_DEFAULT_CHAT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_PULLR|CHAT_GHOSTWHISPER|CHAT_GHOSTPDA|CHAT_GHOSTRADIO|CHAT_LOOC) + +#define PARALLAX_INSANE -1 //for show offs +#define PARALLAX_HIGH 0 //default. +#define PARALLAX_MED 1 +#define PARALLAX_LOW 2 +#define PARALLAX_DISABLE 3 //this option must be the highest number + +#define PARALLAX_DELAY_DEFAULT world.tick_lag +#define PARALLAX_DELAY_MED 1 +#define PARALLAX_DELAY_LOW 2 + +#define SEC_DEPT_NONE "None" +#define SEC_DEPT_RANDOM "Random" +#define SEC_DEPT_ENGINEERING "Engineering" +#define SEC_DEPT_MEDICAL "Medical" +#define SEC_DEPT_SCIENCE "Science" #define SEC_DEPT_SUPPLY "Supply" // Playtime tracking system, see jobs_exp.dm diff --git a/code/__DEFINES/radio.dm b/code/__DEFINES/radio.dm index e262aa2df7..edacfb836a 100644 --- a/code/__DEFINES/radio.dm +++ b/code/__DEFINES/radio.dm @@ -1,55 +1,5 @@ -// Radios use a large variety of predefined frequencies. +#define MIN_FREE_FREQ 1201 +#define MAX_FREE_FREQ 1599 -#define MIN_FREE_FREQ 1201 // ------------------------------------------------- -// Frequencies are always odd numbers and range from 1201 to 1599. - -#define FREQ_SYNDICATE 1213 // Nuke op comms frequency, dark brown -#define FREQ_CTF_RED 1215 // CTF red team comms frequency, red -#define FREQ_CTF_BLUE 1217 // CTF blue team comms frequency, blue -#define FREQ_CENTCOM 1337 // CentCom comms frequency, gray -#define FREQ_SUPPLY 1347 // Supply comms frequency, light brown -#define FREQ_SERVICE 1349 // Service comms frequency, green -#define FREQ_SCIENCE 1351 // Science comms frequency, plum -#define FREQ_COMMAND 1353 // Command comms frequency, gold -#define FREQ_MEDICAL 1355 // Medical comms frequency, soft blue -#define FREQ_ENGINEERING 1357 // Engineering comms frequency, orange -#define FREQ_SECURITY 1359 // Security comms frequency, red - -#define FREQ_STATUS_DISPLAYS 1435 -#define FREQ_ATMOS_ALARMS 1437 // air alarms <-> alert computers -#define FREQ_ATMOS_CONTROL 1439 // air alarms <-> vents and scrubbers - -#define MIN_FREQ 1441 // ------------------------------------------------------ -// Only the 1441 to 1489 range is freely available for general conversation. -// This represents 1/8th of the available spectrum. - -#define FREQ_ATMOS_STORAGE 1441 -#define FREQ_NAV_BEACON 1445 -#define FREQ_AI_PRIVATE 1447 // AI private comms frequency, magenta -#define FREQ_PRESSURE_PLATE 1447 -#define FREQ_AIRLOCK_CONTROL 1449 -#define FREQ_ELECTROPACK 1449 -#define FREQ_MAGNETS 1449 -#define FREQ_LOCATOR_IMPLANT 1451 -#define FREQ_SIGNALER 1457 // the default for new signalers -#define FREQ_COMMON 1459 // Common comms frequency, dark green - -#define MAX_FREQ 1489 // ------------------------------------------------------ - -#define MAX_FREE_FREQ 1599 // ------------------------------------------------- - -// Transmission types. -#define TRANSMISSION_WIRE 0 // some sort of wired connection, not used -#define TRANSMISSION_RADIO 1 // electromagnetic radiation (default) -#define TRANSMISSION_SUBSPACE 2 // subspace transmission (headsets only) - -// Filter types, used as an optimization to avoid unnecessary proc calls. -#define RADIO_TO_AIRALARM "to_airalarm" -#define RADIO_FROM_AIRALARM "from_airalarm" -#define RADIO_SIGNALER "signaler" -#define RADIO_ATMOSIA "atmosia" -#define RADIO_NAVBEACONS "navbeacons" -#define RADIO_AIRLOCK "airlock" -#define RADIO_MAGNETS "magnets" - -#define DEFAULT_SIGNALER_CODE 30 +#define MIN_FREQ 1441 +#define MAX_FREQ 1489 \ No newline at end of file diff --git a/code/__DEFINES/research.dm b/code/__DEFINES/research.dm index bb2e232886..14e6798528 100644 --- a/code/__DEFINES/research.dm +++ b/code/__DEFINES/research.dm @@ -1,8 +1,4 @@ -#define RDCONSOLE_UI_MODE_NORMAL 1 -#define RDCONSOLE_UI_MODE_EXPERT 2 -#define RDCONSOLE_UI_MODE_LIST 3 - //RDSCREEN screens #define RDSCREEN_MENU 0 #define RDSCREEN_TECHDISK 1 @@ -63,5 +59,3 @@ //#define DEPARTMENTAL_FLAG_MINING 128 #define DESIGN_ID_IGNORE "IGNORE_THIS_DESIGN" - -#define RESEARCH_MATERIAL_RECLAMATION_ID "__materials" diff --git a/code/__DEFINES/server_tools.config.dm b/code/__DEFINES/server_tools.config.dm deleted file mode 100644 index 7d3c5b8eba..0000000000 --- a/code/__DEFINES/server_tools.config.dm +++ /dev/null @@ -1,8 +0,0 @@ -#define SERVER_TOOLS_EXTERNAL_CONFIGURATION -#define SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(Name, Value) GLOBAL_VAR_INIT(##Name, ##Value); GLOBAL_PROTECT(##Name) -#define SERVER_TOOLS_READ_GLOBAL(Name) GLOB.##Name -#define SERVER_TOOLS_WRITE_GLOBAL(Name, Value) GLOB.##Name = ##Value -#define SERVER_TOOLS_WORLD_ANNOUNCE(message) to_chat(world, "[html_encode(##message)]") -#define SERVER_TOOLS_LOG(message) log_world("SERVICE: [##message]") -#define SERVER_TOOLS_NOTIFY_ADMINS(event) message_admins(##event) -#define SERVER_TOOLS_CLIENT_COUNT GLOB.clients.len diff --git a/code/__DEFINES/server_tools.dm b/code/__DEFINES/server_tools.dm index a444caf02a..9547c381c1 100644 --- a/code/__DEFINES/server_tools.dm +++ b/code/__DEFINES/server_tools.dm @@ -1,29 +1,28 @@ -// /tg/station 13 server tools API -#define SERVICE_API_VERSION_STRING "3.2.0.1" +// /tg/station 13 server tools API v3.1.0.2 //CONFIGURATION //use this define if you want to do configuration outside of this file #ifndef SERVER_TOOLS_EXTERNAL_CONFIGURATION //Comment this out once you've filled in the below -#error /tg/station server tools interface unconfigured +//#error /tg/station server tools interface unconfigured //Required interfaces (fill in with your codebase equivalent): //create a global variable named `Name` and set it to `Value` //These globals must not be modifiable from anywhere outside of the server tools -#define SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(Name, Value) +#define SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(Name, Value) GLOBAL_VAR_INIT(##Name, ##Value); GLOBAL_PROTECT(##Name) //Read the value in the global variable `Name` -#define SERVER_TOOLS_READ_GLOBAL(Name) +#define SERVER_TOOLS_READ_GLOBAL(Name) GLOB.##Name //Set the value in the global variable `Name` to `Value` -#define SERVER_TOOLS_WRITE_GLOBAL(Name, Value) +#define SERVER_TOOLS_WRITE_GLOBAL(Name, Value) GLOB.##Name = ##Value //display an announcement `message` from the server to all players -#define SERVER_TOOLS_WORLD_ANNOUNCE(message) +#define SERVER_TOOLS_WORLD_ANNOUNCE(message) to_chat(world, "[html_encode(##message)]") //Write a string `message` to a server log -#define SERVER_TOOLS_LOG(message) +#define SERVER_TOOLS_LOG(message) log_world("SERVICE: [##message]") //Notify current in-game administrators of a string `event` -#define SERVER_TOOLS_NOTIFY_ADMINS(event) +#define SERVER_TOOLS_NOTIFY_ADMINS(event) message_admins(##event) //The current amount of connected clients -#define SERVER_TOOLS_CLIENT_COUNT +#define SERVER_TOOLS_CLIENT_COUNT GLOB.clients.len #endif //Required hooks: @@ -65,15 +64,16 @@ //IMPLEMENTATION +#define SERVICE_API_VERSION_STRING "3.1.0.2" + #define REBOOT_MODE_NORMAL 0 #define REBOOT_MODE_HARD 1 #define REBOOT_MODE_SHUTDOWN 2 #define SERVICE_WORLD_PARAM "server_service" #define SERVICE_VERSION_PARAM "server_service_version" -#define SERVICE_INSTANCE_PARAM "server_instance" #define SERVICE_PR_TEST_JSON "prtestjob.json" -#define SERVICE_INTERFACE_DLL "TGDreamDaemonBridge.dll" +#define SERVICE_INTERFACE_DLL "TGServiceInterface.dll" #define SERVICE_INTERFACE_FUNCTION "DDEntryPoint" #define SERVICE_CMD_HARD_REBOOT "hard_reboot" @@ -98,12 +98,11 @@ #define SERVICE_REQUEST_WORLD_REBOOT "worldreboot" #define SERVICE_REQUEST_API_VERSION "api_ver" -#define SERVICE_RETURN_SUCCESS "SUCCESS" - /* The MIT License -Copyright (c) 2017 Jordan Brown +Copyright (c) 2011 Dominic Tarr + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to diff --git a/code/__DEFINES/shuttles.dm b/code/__DEFINES/shuttles.dm index ac081c1ca9..b961c9bd44 100644 --- a/code/__DEFINES/shuttles.dm +++ b/code/__DEFINES/shuttles.dm @@ -61,6 +61,7 @@ #define DOCKING_NULL_DESTINATION 8 #define DOCKING_NULL_SOURCE 16 + //Docking turf movements #define MOVE_TURF 1 #define MOVE_AREA 2 diff --git a/code/__DEFINES/sight.dm b/code/__DEFINES/sight.dm index d756cbaf1b..218afcafb7 100644 --- a/code/__DEFINES/sight.dm +++ b/code/__DEFINES/sight.dm @@ -25,6 +25,6 @@ //for clothing visor toggles, these determine which vars to toggle #define VISOR_FLASHPROTECT 1 #define VISOR_TINT 2 -#define VISOR_VISIONFLAGS 4 //all following flags only matter for glasses +#define VISOR_VISIONFLAGS 4 //all following flags_1 only matter for glasses #define VISOR_DARKNESSVIEW 8 #define VISOR_INVISVIEW 16 diff --git a/code/__DEFINES/stat.dm b/code/__DEFINES/stat.dm index d2993f2f13..331bc6765f 100644 --- a/code/__DEFINES/stat.dm +++ b/code/__DEFINES/stat.dm @@ -18,8 +18,8 @@ #define HUSK 64 #define NOCLONE 128 #define CLUMSY 256 -#define DUMB 512 -#define MONKEYLIKE 1024 //sets IsAdvancedToolUser to FALSE +#define DUMB 512 +#define MONKEYLIKE 1024 //sets IsAdvancedToolUser to FALSE // bitflags for machine stat variable #define BROKEN 1 diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 3a5b0cac59..5a0dded276 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -102,4 +102,4 @@ A.overlays.Cut();\ }\ A.flags_1 &= ~OVERLAY_QUEUED_1;\ - } \ No newline at end of file + } diff --git a/code/__DEFINES/time.dm b/code/__DEFINES/time.dm index 8bc4d039f6..987d52e0cd 100644 --- a/code/__DEFINES/time.dm +++ b/code/__DEFINES/time.dm @@ -22,6 +22,6 @@ When using time2text(), please use "DDD" to find the weekday. Refrain from using #define TICKS *world.tick_lag -#define DS2TICKS(DS) ((DS)/world.tick_lag) +#define DS2TICKS(DS) (DS/world.tick_lag) -#define TICKS2DS(T) ((T) TICKS) \ No newline at end of file +#define TICKS2DS(T) (T TICKS) \ No newline at end of file diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm index a9f5766eb6..3831349536 100644 --- a/code/__HELPERS/cmp.dm +++ b/code/__HELPERS/cmp.dm @@ -30,7 +30,7 @@ GLOBAL_VAR_INIT(cmp_field, "name") return sorttext(a.ckey, b.ckey) /proc/cmp_subsystem_init(datum/controller/subsystem/a, datum/controller/subsystem/b) - return initial(b.init_order) - initial(a.init_order) //uses initial() so it can be used on types + return b.init_order - a.init_order /proc/cmp_subsystem_display(datum/controller/subsystem/a, datum/controller/subsystem/b) return sorttext(b.name, a.name) @@ -72,3 +72,4 @@ GLOBAL_VAR_INIT(cmp_field, "name") /proc/cmp_profile_count_dsc(list/A, list/B) return B[PROFILE_ITEM_COUNT] - A[PROFILE_ITEM_COUNT] + diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 56a5e9b8b7..d3b62b67af 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -473,7 +473,7 @@ Proc for attack log creation, because really why not if(extra_args) new_args += extra_args - for(var/j in 1 to amount) + for(var/j in 1 to amount) var/atom/X = new spawn_type(arglist(new_args)) X.admin_spawned = admin_spawn diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm index e019af213f..bfcfd23f50 100644 --- a/code/__HELPERS/names.dm +++ b/code/__HELPERS/names.dm @@ -121,6 +121,10 @@ GLOBAL_VAR(command_name) return new_station_name /proc/syndicate_name() + var/static/syndicate_name + if (syndicate_name) + return syndicate_name + var/name = "" // Prefix @@ -143,6 +147,7 @@ GLOBAL_VAR(command_name) name += pick("-", "*", "") name += pick("Tech", "Sun", "Co", "Tek", "X", "Inc", "Gen", "Star", "Dyne", "Code", "Hive") + syndicate_name = name return name diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm deleted file mode 100644 index c8710d6570..0000000000 --- a/code/__HELPERS/roundend.dm +++ /dev/null @@ -1,432 +0,0 @@ -/datum/controller/subsystem/ticker/proc/gather_roundend_feedback() - var/clients = GLOB.player_list.len - var/surviving_humans = 0 - var/surviving_total = 0 - var/ghosts = 0 - var/escaped_humans = 0 - var/escaped_total = 0 - - for(var/mob/M in GLOB.player_list) - if(ishuman(M)) - if(!M.stat) - surviving_humans++ - if(M.z == ZLEVEL_CENTCOM) - escaped_humans++ - if(!M.stat) - surviving_total++ - if(M.z == ZLEVEL_CENTCOM) - escaped_total++ - - if(isobserver(M)) - ghosts++ - - if(clients) - SSblackbox.record_feedback("nested tally", "round_end_stats", clients, list("clients")) - if(ghosts) - SSblackbox.record_feedback("nested tally", "round_end_stats", ghosts, list("ghosts")) - if(surviving_humans) - SSblackbox.record_feedback("nested tally", "round_end_stats", surviving_humans, list("survivors", "human")) - if(surviving_total) - SSblackbox.record_feedback("nested tally", "round_end_stats", surviving_total, list("survivors", "total")) - if(escaped_humans) - SSblackbox.record_feedback("nested tally", "round_end_stats", escaped_humans, list("escapees", "human")) - if(escaped_total) - SSblackbox.record_feedback("nested tally", "round_end_stats", escaped_total, list("escapees", "total")) - - gather_antag_success_rate() - -/datum/controller/subsystem/ticker/proc/gather_antag_success_rate() - var/team_gid = 1 - var/list/team_ids = list() - - for(var/datum/antagonist/A in GLOB.antagonists) - var/list/antag_info = list() - antag_info["key"] = A.owner.key - antag_info["name"] = A.owner.name - antag_info["antagonist_type"] = A.type - antag_info["antagonist_name"] = A.name //For auto and custom roles - antag_info["objectives"] = list() - antag_info["team"] = list() - var/datum/objective_team/T = A.get_team() - if(T) - antag_info["team"]["type"] = T.type - antag_info["team"]["name"] = T.name - if(!team_ids[T]) - team_ids[T] = team_gid++ - antag_info["team"]["id"] = team_ids[T] - - if(!A.owner) - continue - if(A.objectives.len) - for(var/datum/objective/O in A.objectives) - var/result = O.check_completion() ? "SUCCESS" : "FAIL" - antag_info["objectives"] += list(list("objective_type"=O.type,"text"=O.explanation_text,"result"=result)) - SSblackbox.record_feedback("associative", "antagonists", 1, antag_info) - -/datum/controller/subsystem/ticker/proc/gather_newscaster() - var/json_file = file("[GLOB.log_directory]/newscaster.json") - var/list/file_data = list() - var/pos = 1 - for(var/datum/newscaster/feed_channel/channel in GLOB.news_network.network_channels) - if(!GLOB.news_network.network_channels.len) - break - file_data["[pos]"] = list("channel name" = "[channel.channel_name]", "author" = "[channel.author]", "censored" = channel.censored ? 1 : 0, "author censored" = channel.authorCensor ? 1 : 0, "messages" = list()) - if(!channel.messages.len) - continue - for(var/datum/newscaster/feed_message/message in channel.messages) - file_data["[pos]"]["messages"] |= list("author" = "[message.author]", "time stamp" = "[message.time_stamp]", "censored" = message.bodyCensor ? 1 : 0, "author censored" = message.authorCensor ? 1 : 0, "photo file" = "[message.photo_file]", "photo caption" = "[message.caption]", "body" = "[message.body]", "comments" = list()) - if(!message.comments.len) - continue - for(var/datum/newscaster/feed_comment/comment in message.comments) - file_data["[pos]"]["messages"]["comments"] = list("author" = "[comment.author]", "time stamp" = "[comment.time_stamp]", "body" = "[comment.body]") - pos++ - if(GLOB.news_network.wanted_issue.active) - file_data["wanted"] = list("author" = "[GLOB.news_network.wanted_issue.scannedUser]", "criminal" = "[GLOB.news_network.wanted_issue.criminal]", "description" = "[GLOB.news_network.wanted_issue.body]", "photo file" = "[GLOB.news_network.wanted_issue.photo_file]") - WRITE_FILE(json_file, json_encode(file_data)) - -/datum/controller/subsystem/ticker/proc/declare_completion() - set waitfor = FALSE - - to_chat(world, "


The round has ended.") - if(LAZYLEN(GLOB.round_end_notifiees)) - send2irc("Notice", "[GLOB.round_end_notifiees.Join(", ")] the round has ended.") - - for(var/client/C in GLOB.clients) - if(!C.credits) - C.RollCredits() - C.playtitlemusic(40) - - display_report() - - gather_roundend_feedback() - - CHECK_TICK - - //Set news report and mode result - mode.set_round_result() - - send2irc("Server", "Round just ended.") - - if(length(CONFIG_GET(keyed_string_list/cross_server))) - send_news_report() - - CHECK_TICK - - //These need update to actually reflect the real antagonists - //Print a list of antagonists to the server log - var/list/total_antagonists = list() - //Look into all mobs in world, dead or alive - for(var/datum/mind/Mind in minds) - var/temprole = Mind.special_role - if(temprole) //if they are an antagonist of some sort. - if(temprole in total_antagonists) //If the role exists already, add the name to it - total_antagonists[temprole] += ", [Mind.name]([Mind.key])" - else - total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob - total_antagonists[temprole] += ": [Mind.name]([Mind.key])" - - CHECK_TICK - - //Now print them all into the log! - log_game("Antagonists at round end were...") - for(var/i in total_antagonists) - log_game("[i]s[total_antagonists[i]].") - - CHECK_TICK - - //Collects persistence features - if(mode.allow_persistence_save) - SSpersistence.CollectData() - - //stop collecting feedback during grifftime - SSblackbox.Seal() - - sleep(50) - ready_for_reboot = TRUE - standard_reboot() - -/datum/controller/subsystem/ticker/proc/standard_reboot() - if(ready_for_reboot) - if(mode.station_was_nuked) - Reboot("Station destroyed by Nuclear Device.", "nuke") - else - Reboot("Round ended.", "proper completion") - else - CRASH("Attempted standard reboot without ticker roundend completion") - -//Common part of the report -/datum/controller/subsystem/ticker/proc/build_roundend_report() - var/list/parts = list() - - //Gamemode specific things. Should be empty most of the time. - parts += mode.special_report() - - CHECK_TICK - - //AI laws - parts += law_report() - - CHECK_TICK - - //Antagonists - parts += antag_report() - - CHECK_TICK - //Medals - parts += medal_report() - //Station Goals - parts += goal_report() - - listclearnulls(parts) - - return parts.Join() - - -/datum/controller/subsystem/ticker/proc/survivor_report() - var/list/parts = list() - var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED - var/num_survivors = 0 - var/num_escapees = 0 - var/num_shuttle_escapees = 0 - - //Player status report - for(var/i in GLOB.mob_list) - var/mob/Player = i - if(Player.mind && !isnewplayer(Player)) - if(Player.stat != DEAD && !isbrain(Player)) - num_survivors++ - if(station_evacuated) //If the shuttle has already left the station - var/list/area/shuttle_areas - if(SSshuttle && SSshuttle.emergency) - shuttle_areas = SSshuttle.emergency.shuttle_areas - if(Player.onCentCom() || Player.onSyndieBase()) - num_escapees++ - if(shuttle_areas[get_area(Player)]) - num_shuttle_escapees++ - - //Round statistics report - var/datum/station_state/end_state = new /datum/station_state() - end_state.count() - var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100) - - parts += "[GLOB.TAB]Shift Duration: [DisplayTimeText(world.time - SSticker.round_start_time)]" - parts += "[GLOB.TAB]Station Integrity: [mode.station_was_nuked ? "Destroyed" : "[station_integrity]%"]" - var/total_players = GLOB.joined_player_list.len - if(total_players) - parts+= "[GLOB.TAB]Total Population: [total_players]" - if(station_evacuated) - parts += "
[GLOB.TAB]Evacuation Rate: [num_escapees] ([PERCENT(num_escapees/total_players)]%)" - parts += "[GLOB.TAB](on emergency shuttle): [num_shuttle_escapees] ([PERCENT(num_shuttle_escapees/total_players)]%)" - parts += "[GLOB.TAB]Survival Rate: [num_survivors] ([PERCENT(num_survivors/total_players)]%)" - return parts.Join("
") - -/datum/controller/subsystem/ticker/proc/show_roundend_report(client/C,common_report) - var/list/report_parts = list() - - report_parts += personal_report(C) - report_parts += common_report - - var/datum/browser/roundend_report = new(C, "roundend") - roundend_report.width = 800 - roundend_report.height = 600 - roundend_report.set_content(report_parts.Join()) - roundend_report.stylesheets = list() - roundend_report.add_stylesheet("roundend",'html/browser/roundend.css') - - roundend_report.open(0) - -/datum/controller/subsystem/ticker/proc/personal_report(client/C) - var/list/parts = list() - var/mob/M = C.mob - if(M.mind && !isnewplayer(M)) - if(M.stat != DEAD && !isbrain(M)) - if(EMERGENCY_ESCAPED_OR_ENDGAMED) - if(!M.onCentCom() || !M.onSyndieBase()) - parts += "
" - parts += "You managed to survive, but were marooned on [station_name()]..." - else - parts += "
" - parts += "You managed to survive the events on [station_name()] as [M.real_name]." - else - parts += "
" - parts += "You managed to survive the events on [station_name()] as [M.real_name]." - - else - parts += "
" - parts += "You did not survive the events on [station_name()]..." - else - parts += "
" - parts += "
" - if(GLOB.survivor_report) - parts += GLOB.survivor_report - else - parts += survivor_report() - - parts += "
" - - return parts.Join() - -/datum/controller/subsystem/ticker/proc/display_report() - GLOB.common_report = build_roundend_report() - for(var/client/C in GLOB.clients) - show_roundend_report(C,GLOB.common_report) - give_show_report_button(C) - CHECK_TICK - -/datum/controller/subsystem/ticker/proc/law_report() - var/list/parts = list() - //Silicon laws report - for (var/i in GLOB.ai_list) - var/mob/living/silicon/ai/aiPlayer = i - if(aiPlayer.mind) - parts += "[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws [aiPlayer.stat != DEAD ? "at the end of the round" : "when it was deactivated"] were:" - parts += aiPlayer.laws.get_law_list(include_zeroth=TRUE) - - parts += "Total law changes: [aiPlayer.law_change_counter]" - - if (aiPlayer.connected_robots.len) - var/robolist = "[aiPlayer.real_name]'s minions were: " - for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots) - if(robo.mind) - robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.mind.key]), ":" (Played by: [robo.mind.key]), "]" - parts += "[robolist]" - - for (var/mob/living/silicon/robot/robo in GLOB.silicon_mobs) - if (!robo.connected_ai && robo.mind) - if (robo.stat != DEAD) - parts += "[robo.name] (Played by: [robo.mind.key]) survived as an AI-less borg! Its laws were:" - else - parts += "[robo.name] (Played by: [robo.mind.key]) was unable to survive the rigors of being a cyborg without an AI. Its laws were:" - - if(robo) //How the hell do we lose robo between here and the world messages directly above this? - parts += robo.laws.get_law_list(include_zeroth=TRUE) - if(parts.len) - return "
[parts.Join("
")]
" - else - return "" - -/datum/controller/subsystem/ticker/proc/goal_report() - var/list/parts = list() - if(mode.station_goals.len) - for(var/V in mode.station_goals) - var/datum/station_goal/G = V - parts += G.get_result() - return "
    [parts.Join()]
" - -/datum/controller/subsystem/ticker/proc/medal_report() - if(GLOB.commendations.len) - var/list/parts = list() - parts += "Medal Commendations:" - for (var/com in GLOB.commendations) - parts += com - return "
[parts.Join("
")]
" - return "" - -/datum/controller/subsystem/ticker/proc/antag_report() - var/list/result = list() - var/list/all_teams = list() - var/list/all_antagonists = list() - - for(var/datum/antagonist/A in GLOB.antagonists) - all_teams |= A.get_team() - all_antagonists += A - - for(var/datum/objective_team/T in all_teams) - result += T.roundend_report() - for(var/datum/antagonist/X in all_antagonists) - if(X.get_team() == T) - all_antagonists -= X - result += " "//newline between teams - - var/currrent_category - var/datum/antagonist/previous_category - - sortTim(all_antagonists, /proc/cmp_antag_category) - - for(var/datum/antagonist/A in all_antagonists) - if(!A.show_in_roundend) - continue - if(A.roundend_category != currrent_category) - if(previous_category) - result += previous_category.roundend_report_footer() - result += "
" - result += "
" - result += A.roundend_report_header() - currrent_category = A.roundend_category - previous_category = A - result += A.roundend_report() - result += "

" - - if(all_antagonists.len) - var/datum/antagonist/last = all_antagonists[all_antagonists.len] - result += last.roundend_report_footer() - result += "
" - - return result.Join() - -/proc/cmp_antag_category(datum/antagonist/A,datum/antagonist/B) - return sorttext(B.roundend_category,A.roundend_category) - - -/datum/controller/subsystem/ticker/proc/give_show_report_button(client/C) - var/datum/action/report/R = new - C.player_details.player_actions += R - R.Grant(C.mob) - to_chat(C,"Show roundend report again") - -/datum/action/report - name = "Show roundend report" - button_icon_state = "vote" - -/datum/action/report/Trigger() - if(owner && GLOB.common_report && SSticker.current_state == GAME_STATE_FINISHED) - SSticker.show_roundend_report(owner.client,GLOB.common_report) - -/datum/action/report/IsAvailable() - return 1 - -/datum/action/report/Topic(href,href_list) - if(usr != owner) - return - if(href_list["report"]) - Trigger() - return - - -/proc/printplayer(datum/mind/ply, fleecheck) - var/text = "[ply.key] was [ply.name] the [ply.assigned_role] and" - if(ply.current) - if(ply.current.stat == DEAD) - text += " died" - else - text += " survived" - if(fleecheck) - var/turf/T = get_turf(ply.current) - if(!T || !(T.z in GLOB.station_z_levels)) - text += " while fleeing the station" - if(ply.current.real_name != ply.name) - text += " as [ply.current.real_name]" - else - text += " had their body destroyed" - return text - -/proc/printplayerlist(list/players,fleecheck) - var/list/parts = list() - - parts += "
    " - for(var/datum/mind/M in players) - parts += "
  • [printplayer(M,fleecheck)]
  • " - parts += "
" - return parts.Join() - - -/proc/printobjectives(datum/mind/ply) - var/list/objective_parts = list() - var/count = 1 - for(var/datum/objective/objective in ply.objectives) - if(objective.check_completion()) - objective_parts += "Objective #[count]: [objective.explanation_text] Success!" - else - objective_parts += "Objective #[count]: [objective.explanation_text] Fail." - count++ - return objective_parts.Join("
") diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 2eeee95d09..bae773b27e 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -139,6 +139,7 @@ return NORTH //returns the north-zero clockwise angle in degrees, given a direction + /proc/dir2angle(D) switch(D) if(NORTH) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index da7d2134a1..9ec23fa966 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -199,8 +199,6 @@ Turf and target are separate in case you want to teleport some distance from a t newname = C.prefs.custom_names[role] else switch(role) - if("human") - newname = random_unique_name(gender) if("clown") newname = pick(GLOB.clown_names) if("mime") @@ -526,7 +524,7 @@ Turf and target are separate in case you want to teleport some distance from a t processing_list.Cut(1, 2) //Byond does not allow things to be in multiple contents, or double parent-child hierarchies, so only += is needed //This is also why we don't need to check against assembled as we go along - processing_list += A.contents + processing_list += A.contents assembled += A return assembled @@ -1494,7 +1492,6 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) var/time_low = num2hex(world.time, 3) var/time_clock = num2hex(TICK_DELTA_TO_MS(world.tick_usage), 3) - return "{[time_high]-[time_mid]-[GUID_VERSION][time_low]-[GUID_VARIANT][time_clock]-[node_id]}" // \ref behaviour got changed in 512 so this is necesary to replicate old behaviour. diff --git a/code/_globalvars/game_modes.dm b/code/_globalvars/game_modes.dm index 3822f7077d..9c3af923f1 100644 --- a/code/_globalvars/game_modes.dm +++ b/code/_globalvars/game_modes.dm @@ -1,12 +1,18 @@ GLOBAL_VAR_INIT(master_mode, "traitor") //"extended" GLOBAL_VAR_INIT(secret_force_mode, "secret") // if this is anything but "secret", the secret rotation will forceably choose this mode -GLOBAL_VAR(common_report) //Contains commmon part of roundend report -GLOBAL_VAR(survivor_report) //Contains shared surivor report for roundend report (part of personal report) - GLOBAL_VAR_INIT(wavesecret, 0) // meteor mode, delays wave progression, terrible name GLOBAL_DATUM(start_state, /datum/station_state) // Used in round-end report - -//TODO clear this one up too -GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult) \ No newline at end of file +// Cult, needs to be global so admin cultists are functional +GLOBAL_VAR_INIT(blood_target, null) // Cult Master's target or Construct's Master +GLOBAL_DATUM(blood_target_image, /image) +GLOBAL_VAR_INIT(blood_target_reset_timer, null) +GLOBAL_DATUM(sac_mind, /datum/mind) +GLOBAL_VAR_INIT(sac_image, null) +GLOBAL_VAR_INIT(cult_vote_called, FALSE) +GLOBAL_VAR_INIT(cult_mastered, FALSE) +GLOBAL_VAR_INIT(reckoning_complete, FALSE) +GLOBAL_VAR_INIT(sac_complete, FALSE) +GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult) +GLOBAL_LIST_EMPTY(summon_spots) \ No newline at end of file diff --git a/code/_globalvars/misc.dm b/code/_globalvars/misc.dm index 8b8b817586..bb86b4cbb0 100644 --- a/code/_globalvars/misc.dm +++ b/code/_globalvars/misc.dm @@ -16,5 +16,3 @@ GLOBAL_VAR_INIT(CHARGELEVEL, 0.001) // Cap for how fast cells charge, as a perce GLOBAL_LIST_EMPTY(powernets) GLOBAL_VAR_INIT(bsa_unlock, FALSE) //BSA unlocked by head ID swipes - -GLOBAL_LIST_EMPTY(player_details) // ckey -> /datum/player_details \ No newline at end of file diff --git a/code/_js/byjax.dm b/code/_js/byjax.dm index 9d96bbc412..5557440d32 100644 --- a/code/_js/byjax.dm +++ b/code/_js/byjax.dm @@ -45,4 +45,3 @@ Be sure to include required js functions in your page, or it'll raise an excepti receiver << output(argums,"[control_id]:replaceContent") return - diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 6d941589d3..dc06d17819 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -104,7 +104,7 @@ #define ui_health "EAST-1:28,CENTER-1:15" #define ui_internal "EAST-1:28,CENTER:17" -//borgs +//borgs #define ui_borg_health "EAST-1:28,CENTER-1:15" //borgs have the health display where humans have the pressure damage indicator. //aliens diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 2ad2eb76f5..0006d72d3b 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -302,41 +302,32 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." /obj/screen/alert/bloodsense/process() var/atom/blood_target - - var/datum/antagonist/cult/antag = mob_viewer.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - if(!antag) - return - var/datum/objective/sacrifice/sac_objective = locate() in antag.cult_team.objectives - - if(antag.cult_team.blood_target) - if(!get_turf(antag.cult_team.blood_target)) - antag.cult_team.blood_target = null + if(GLOB.blood_target) + if(!get_turf(GLOB.blood_target)) + GLOB.blood_target = null else - blood_target = antag.cult_team.blood_target + blood_target = GLOB.blood_target if(Cviewer && Cviewer.seeking && Cviewer.master) blood_target = Cviewer.master desc = "Your blood sense is leading you to [Cviewer.master]" if(!blood_target) - if(sac_objective && !sac_objective.check_completion()) + if(!GLOB.sac_complete) if(icon_state == "runed_sense0") return animate(src, transform = null, time = 1, loop = 0) angle = 0 cut_overlays() icon_state = "runed_sense0" - desc = "Nar-Sie demands that [sac_objective.target] be sacrificed before the summoning ritual can begin." - add_overlay(sac_objective.sac_image) + desc = "Nar-Sie demands that [GLOB.sac_mind] be sacrificed before the summoning ritual can begin." + add_overlay(GLOB.sac_image) else - var/datum/objective/eldergod/summon_objective = locate() in antag.cult_team.objectives - if(!summon_objective) - return if(icon_state == "runed_sense1") return animate(src, transform = null, time = 1, loop = 0) angle = 0 cut_overlays() icon_state = "runed_sense1" - desc = "The sacrifice is complete, summon Nar-Sie! The summoning can only take place in [english_list(summon_objective.summon_spots)]!" + desc = "The sacrifice is complete, summon Nar-Sie! The summoning can only take place in [english_list(GLOB.summon_spots)]!" add_overlay(narnar) return var/turf/P = get_turf(blood_target) @@ -397,13 +388,11 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." desc = "CHETR
NYY
HAGEHUGF-NAQ-UBABE
RATVAR.
" else var/servants = 0 - var/list/textlist = list() + var/list/textlist for(var/mob/living/L in GLOB.alive_mob_list) if(is_servant_of_ratvar(L)) servants++ - var/datum/antagonist/clockcult/C = mob_viewer.mind.has_antag_datum(/datum/antagonist/clockcult,TRUE) - if(C && C.clock_team) - textlist += "[C.clock_team.eminence ? "There is an Eminence." : "There is no Eminence! Get one ASAP!"]
" + textlist = list("[SSticker.mode.eminence ? "There is an Eminence." : "There is no Eminence! Get one ASAP!"]
") textlist += "There are currently [servants] servant[servants > 1 ? "s" : ""] of Ratvar.
" for(var/i in SSticker.scripture_states) if(i != SCRIPTURE_DRIVER) //ignore the always-unlocked stuff diff --git a/code/_onclick/hud/credits.dm b/code/_onclick/hud/credits.dm deleted file mode 100644 index dfdbf390c1..0000000000 --- a/code/_onclick/hud/credits.dm +++ /dev/null @@ -1,69 +0,0 @@ -#define CREDIT_ROLL_SPEED 125 -#define CREDIT_SPAWN_SPEED 10 -#define CREDIT_ANIMATE_HEIGHT (14 * world.icon_size) -#define CREDIT_EASE_DURATION 22 -#define CREDITS_PATH "[GLOB.config_dir]contributors.dmi" - -/client/proc/RollCredits() - set waitfor = FALSE - if(!fexists(CREDITS_PATH)) - return - var/icon/credits_icon = new(CREDITS_PATH) - LAZYINITLIST(credits) - var/list/_credits = credits - verbs += /client/proc/ClearCredits - var/static/list/credit_order_for_this_round - if(isnull(credit_order_for_this_round)) - credit_order_for_this_round = list("Thanks for playing!") + (shuffle(icon_states(credits_icon)) - "Thanks for playing!") - for(var/I in credit_order_for_this_round) - if(!credits) - return - _credits += new /obj/screen/credit(null, I, src, credits_icon) - sleep(CREDIT_SPAWN_SPEED) - sleep(CREDIT_ROLL_SPEED - CREDIT_SPAWN_SPEED) - verbs -= /client/proc/ClearCredits - qdel(credits_icon) - -/client/proc/ClearCredits() - set name = "Hide Credits" - set category = "OOC" - verbs -= /client/proc/ClearCredits - QDEL_LIST(credits) - credits = null - -/obj/screen/credit - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - alpha = 0 - screen_loc = "12,1" - layer = SPLASHSCREEN_LAYER - var/client/parent - var/matrix/target - -/obj/screen/credit/Initialize(mapload, credited, client/P, icon/I) - . = ..() - icon = I - parent = P - icon_state = credited - maptext = credited - maptext_x = world.icon_size + 8 - maptext_y = (world.icon_size / 2) - 4 - maptext_width = world.icon_size * 3 - var/matrix/M = matrix(transform) - M.Translate(0, CREDIT_ANIMATE_HEIGHT) - animate(src, transform = M, time = CREDIT_ROLL_SPEED) - target = M - animate(src, alpha = 255, time = CREDIT_EASE_DURATION, flags = ANIMATION_PARALLEL) - addtimer(CALLBACK(src, .proc/FadeOut), CREDIT_ROLL_SPEED - CREDIT_EASE_DURATION) - QDEL_IN(src, CREDIT_ROLL_SPEED) - P.screen += src - -/obj/screen/credit/Destroy() - var/client/P = parent - P.screen -= src - icon = null - LAZYREMOVE(P.credits, src) - parent = null - return ..() - -/obj/screen/credit/proc/FadeOut() - animate(src, alpha = 0, transform = target, time = CREDIT_EASE_DURATION) diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index 65c4bd23c2..2047225589 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -1,4 +1,3 @@ - /mob var/list/screens = list() @@ -175,3 +174,4 @@ layer = LIGHTING_LAYER blend_mode = BLEND_ADD show_when_dead = TRUE + diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm index 87354d6f0b..903f3c0790 100644 --- a/code/_onclick/telekinesis.dm +++ b/code/_onclick/telekinesis.dm @@ -78,7 +78,7 @@ var/mob/living/carbon/tk_user = null /obj/item/tk_grab/Initialize() - . = ..() + ..() START_PROCESSING(SSfastprocess, src) /obj/item/tk_grab/Destroy() diff --git a/code/controllers/configuration/config_entry.dm b/code/controllers/configuration/config_entry.dm index 28643bea20..92dcb9baf0 100644 --- a/code/controllers/configuration/config_entry.dm +++ b/code/controllers/configuration/config_entry.dm @@ -9,7 +9,7 @@ var/value var/default //read-only, just set value directly - var/resident_file //the file which this was loaded from, if any + var/resident_file //the file which this belongs to, must be set var/modified = FALSE //set to TRUE if the default has been overridden by a config entry var/protection = NONE @@ -18,6 +18,8 @@ var/dupes_allowed = FALSE /datum/config_entry/New() + if(!resident_file) + CRASH("Config entry [type] has no resident_file set") if(type == abstract_type) CRASH("Abstract config entry [type] instatiated!") name = lowertext(type2top(type)) @@ -53,9 +55,8 @@ . = !(IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "ValidateAndSet" && GLOB.LastAdminCalledTargetRef == "[REF(src)]") if(!.) log_admin_private("Config set of [type] to [str_val] attempted by [key_name(usr)]") - + /datum/config_entry/proc/ValidateAndSet(str_val) - VASProcCallGuard(str_val) CRASH("Invalid config entry type!") /datum/config_entry/proc/ValidateKeyedList(str_val, list_mode, splitter) @@ -79,12 +80,12 @@ if(LIST_MODE_TEXT) temp = key_value continue_check = temp - if(continue_check && ValidateListEntry(key_name, temp)) + if(continue_check && ValidateKeyName(key_name)) value[key_name] = temp return TRUE return FALSE -/datum/config_entry/proc/ValidateListEntry(key_name, key_value) +/datum/config_entry/proc/ValidateKeyName(key_name) return TRUE /datum/config_entry/string @@ -96,8 +97,6 @@ return var_name != "auto_trim" && ..() /datum/config_entry/string/ValidateAndSet(str_val) - if(!VASProcCallGuard(str_val)) - return FALSE value = auto_trim ? trim(str_val) : str_val return TRUE @@ -109,8 +108,6 @@ var/min_val = -INFINITY /datum/config_entry/number/ValidateAndSet(str_val) - if(!VASProcCallGuard(str_val)) - return FALSE var/temp = text2num(trim(str_val)) if(!isnull(temp)) value = Clamp(integer ? round(temp) : temp, min_val, max_val) @@ -128,8 +125,6 @@ abstract_type = /datum/config_entry/flag /datum/config_entry/flag/ValidateAndSet(str_val) - if(!VASProcCallGuard(str_val)) - return FALSE value = text2num(trim(str_val)) != 0 return TRUE @@ -138,8 +133,6 @@ value = list() /datum/config_entry/number_list/ValidateAndSet(str_val) - if(!VASProcCallGuard(str_val)) - return FALSE str_val = trim(str_val) var/list/new_list = list() var/list/values = splittext(str_val," ") @@ -159,8 +152,6 @@ dupes_allowed = TRUE /datum/config_entry/keyed_flag_list/ValidateAndSet(str_val) - if(!VASProcCallGuard(str_val)) - return FALSE return ValidateKeyedList(str_val, LIST_MODE_FLAG, " ") /datum/config_entry/keyed_number_list @@ -173,8 +164,6 @@ return var_name != "splitter" && ..() /datum/config_entry/keyed_number_list/ValidateAndSet(str_val) - if(!VASProcCallGuard(str_val)) - return FALSE return ValidateKeyedList(str_val, LIST_MODE_NUM, splitter) /datum/config_entry/keyed_string_list @@ -187,8 +176,6 @@ return var_name != "splitter" && ..() /datum/config_entry/keyed_string_list/ValidateAndSet(str_val) - if(!VASProcCallGuard(str_val)) - return FALSE return ValidateKeyedList(str_val, LIST_MODE_TEXT, splitter) #undef LIST_MODE_NUM diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index f411bd65d3..e9c0aa71b8 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -20,13 +20,10 @@ GLOBAL_PROTECT(config_dir) /datum/controller/configuration/New() config = src - InitEntries() + var/list/config_files = InitEntries() LoadModes() - if(!LoadEntries("config.txt")) - log_config("No $include directives found in config.txt! Loading legacy game_options/dbconfig/comms files...") - LoadEntries("game_options.txt") - LoadEntries("dbconfig.txt") - LoadEntries("comms.txt") + for(var/I in config_files) + LoadEntries(I) loadmaplist(CONFIG_MAPS_FILE) /datum/controller/configuration/Destroy() @@ -45,6 +42,8 @@ GLOBAL_PROTECT(config_dir) var/list/_entries_by_type = list() entries_by_type = _entries_by_type + . = list() + for(var/I in typesof(/datum/config_entry)) //typesof is faster in this case var/datum/config_entry/E = I if(initial(E.abstract_type) == I) @@ -58,30 +57,24 @@ GLOBAL_PROTECT(config_dir) continue _entries[esname] = E _entries_by_type[I] = E + .[E.resident_file] = TRUE /datum/controller/configuration/proc/RemoveEntry(datum/config_entry/CE) entries -= CE.name entries_by_type -= CE.type -/datum/controller/configuration/proc/LoadEntries(filename, list/stack = list()) - var/filename_to_test = world.system_type == MS_WINDOWS ? lowertext(filename) : filename - if(filename_to_test in stack) - log_config("Warning: Config recursion detected ([english_list(stack)]), breaking!") - return - stack = stack + filename_to_test - +/datum/controller/configuration/proc/LoadEntries(filename) log_config("Loading config file [filename]...") var/list/lines = world.file2list("[GLOB.config_dir][filename]") var/list/_entries = entries for(var/L in lines) if(!L) continue - - var/firstchar = copytext(L, 1, 2) - if(firstchar == "#") + + if(copytext(L, 1, 2) == "#") continue - var/lockthis = firstchar == "@" + var/lockthis = copytext(L, 1, 2) == "@" if(lockthis) L = copytext(L, 2) @@ -98,17 +91,14 @@ GLOBAL_PROTECT(config_dir) if(!entry) continue - if(entry == "$include") - if(!value) - log_config("Warning: Invalid $include directive: [value]") - else - LoadEntries(value, stack) - continue - var/datum/config_entry/E = _entries[entry] if(!E) log_config("Unknown setting in configuration: '[entry]'") continue + + if(filename != E.resident_file) + log_config("Found [entry] in [filename] when it should have been in [E.resident_file]! Ignoring.") + continue if(lockthis) E.protection |= CONFIG_ENTRY_LOCKED @@ -117,14 +107,10 @@ GLOBAL_PROTECT(config_dir) if(!validated) log_config("Failed to validate setting \"[value]\" for [entry]") else if(E.modified && !E.dupes_allowed) - log_config("Duplicate setting for [entry] ([value], [E.resident_file]) detected! Using latest.") - - E.resident_file = filename + log_config("Duplicate setting for [entry] ([value]) detected! Using latest.") if(validated) E.modified = TRUE - - . = TRUE /datum/controller/configuration/can_vv_get(var_name) return (var_name != "entries_by_type" || !hiding_entries_by_type) && ..() diff --git a/code/controllers/configuration/entries/comms.dm b/code/controllers/configuration/entries/comms.dm index e720ed93fd..bf099f6cb6 100644 --- a/code/controllers/configuration/entries/comms.dm +++ b/code/controllers/configuration/entries/comms.dm @@ -1,28 +1,22 @@ -/datum/config_entry/string/comms_key +#define CURRENT_RESIDENT_FILE "comms.txt" + +CONFIG_DEF(string/comms_key) protection = CONFIG_ENTRY_HIDDEN /datum/config_entry/string/comms_key/ValidateAndSet(str_val) - return str_val != "default_pwd" && length(str_val) > 6 && ..() + return str_val != "default_pwd" && length(str_val) > 6 && ..() -/datum/config_entry/keyed_string_list/cross_server +CONFIG_DEF(string/cross_server_address) protection = CONFIG_ENTRY_LOCKED -/datum/config_entry/keyed_string_list/cross_server/ValidateAndSet(str_val) - . = ..() - if(.) - var/list/newv = list() - for(var/I in value) - newv[replacetext(I, "+", " ")] = value[I] - value = newv +/datum/config_entry/string/cross_server_address/ValidateAndSet(str_val) + return str_val != "byond:\\address:port" && ..() -/datum/config_entry/keyed_string_list/cross_server/ValidateListEntry(key_name, key_value) - return key_value != "byond:\\address:port" && ..() - -/datum/config_entry/string/cross_comms_name +CONFIG_DEF(string/cross_comms_name) GLOBAL_VAR_INIT(medals_enabled, TRUE) //will be auto set to false if the game fails contacting the medal hub to prevent unneeded calls. -/datum/config_entry/string/medal_hub_address +CONFIG_DEF(string/medal_hub_address) -/datum/config_entry/string/medal_hub_password +CONFIG_DEF(string/medal_hub_password) protection = CONFIG_ENTRY_HIDDEN \ No newline at end of file diff --git a/code/controllers/configuration/entries/dbconfig.dm b/code/controllers/configuration/entries/dbconfig.dm index 1ac4d85419..c46880686a 100644 --- a/code/controllers/configuration/entries/dbconfig.dm +++ b/code/controllers/configuration/entries/dbconfig.dm @@ -1,26 +1,28 @@ -/datum/config_entry/flag/sql_enabled // for sql switching +#define CURRENT_RESIDENT_FILE "dbconfig.txt" + +CONFIG_DEF(flag/sql_enabled) // for sql switching protection = CONFIG_ENTRY_LOCKED -/datum/config_entry/string/address +CONFIG_DEF(string/address) value = "localhost" protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN -/datum/config_entry/number/port +CONFIG_DEF(number/port) value = 3306 min_val = 0 max_val = 65535 protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN -/datum/config_entry/string/feedback_database +CONFIG_DEF(string/feedback_database) value = "test" protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN -/datum/config_entry/string/feedback_login +CONFIG_DEF(string/feedback_login) value = "root" protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN -/datum/config_entry/string/feedback_password +CONFIG_DEF(string/feedback_password) protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN -/datum/config_entry/string/feedback_tableprefix +CONFIG_DEF(string/feedback_tableprefix) protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 0f7e65ec13..b04d7845f5 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -1,253 +1,253 @@ -/datum/config_entry/number_list/repeated_mode_adjust +#define CURRENT_RESIDENT_FILE "game_options.txt" -/datum/config_entry/keyed_number_list/probability +CONFIG_DEF(number_list/repeated_mode_adjust) -/datum/config_entry/keyed_number_list/probability/ValidateListEntry(key_name) +CONFIG_DEF(keyed_number_list/probability) + +/datum/config_entry/keyed_number_list/probability/ValidateKeyName(key_name) return key_name in config.modes -/datum/config_entry/keyed_number_list/max_pop +CONFIG_DEF(keyed_number_list/max_pop) -/datum/config_entry/keyed_number_list/max_pop/ValidateListEntry(key_name) +/datum/config_entry/keyed_number_list/max_pop/ValidateKeyName(key_name) return key_name in config.modes -/datum/config_entry/keyed_number_list/min_pop +CONFIG_DEF(keyed_number_list/min_pop) -/datum/config_entry/keyed_number_list/min_pop/ValidateListEntry(key_name, key_value) +/datum/config_entry/keyed_number_list/min_pop/ValidateKeyName(key_name) return key_name in config.modes -/datum/config_entry/keyed_flag_list/continuous // which roundtypes continue if all antagonists die +CONFIG_DEF(keyed_flag_list/continuous) // which roundtypes continue if all antagonists die -/datum/config_entry/keyed_flag_list/continuous/ValidateListEntry(key_name, key_value) +/datum/config_entry/keyed_flag_list/continuous/ValidateKeyName(key_name) return key_name in config.modes -/datum/config_entry/keyed_flag_list/midround_antag // which roundtypes use the midround antagonist system +CONFIG_DEF(keyed_flag_list/midround_antag) // which roundtypes use the midround antagonist system -/datum/config_entry/keyed_flag_list/midround_antag/ValidateListEntry(key_name, key_value) +/datum/config_entry/keyed_flag_list/midround_antag/ValidateKeyName(key_name) return key_name in config.modes -/datum/config_entry/keyed_string_list/policy +CONFIG_DEF(keyed_string_list/policy) -/datum/config_entry/number/damage_multiplier +CONFIG_DEF(number/damage_multiplier) value = 1 integer = FALSE -/datum/config_entry/number/minimal_access_threshold //If the number of players is larger than this threshold, minimal access will be turned on. +CONFIG_DEF(number/minimal_access_threshold) //If the number of players is larger than this threshold, minimal access will be turned on. min_val = 0 -/datum/config_entry/flag/jobs_have_minimal_access //determines whether jobs use minimal access or expanded access. +CONFIG_DEF(flag/jobs_have_minimal_access) //determines whether jobs use minimal access or expanded access. -/datum/config_entry/flag/assistants_have_maint_access +CONFIG_DEF(flag/assistants_have_maint_access) -/datum/config_entry/flag/security_has_maint_access +CONFIG_DEF(flag/security_has_maint_access) -/datum/config_entry/flag/everyone_has_maint_access +CONFIG_DEF(flag/everyone_has_maint_access) -/datum/config_entry/flag/sec_start_brig //makes sec start in brig instead of dept sec posts +CONFIG_DEF(flag/sec_start_brig) //makes sec start in brig instead of dept sec posts -/datum/config_entry/flag/force_random_names +CONFIG_DEF(flag/force_random_names) -/datum/config_entry/flag/humans_need_surnames +CONFIG_DEF(flag/humans_need_surnames) -/datum/config_entry/flag/allow_ai // allow ai job +CONFIG_DEF(flag/allow_ai) // allow ai job -/datum/config_entry/flag/disable_secborg // disallow secborg module to be chosen. +CONFIG_DEF(flag/disable_secborg) // disallow secborg module to be chosen. -/datum/config_entry/flag/disable_peaceborg +CONFIG_DEF(flag/disable_peaceborg) -/datum/config_entry/number/traitor_scaling_coeff //how much does the amount of players get divided by to determine traitors +CONFIG_DEF(number/traitor_scaling_coeff) //how much does the amount of players get divided by to determine traitors value = 6 min_val = 1 -/datum/config_entry/number/brother_scaling_coeff //how many players per brother team +CONFIG_DEF(number/brother_scaling_coeff) //how many players per brother team value = 25 min_val = 1 -/datum/config_entry/number/changeling_scaling_coeff //how much does the amount of players get divided by to determine changelings +CONFIG_DEF(number/changeling_scaling_coeff) //how much does the amount of players get divided by to determine changelings value = 6 min_val = 1 -/datum/config_entry/number/security_scaling_coeff //how much does the amount of players get divided by to determine open security officer positions +CONFIG_DEF(number/security_scaling_coeff) //how much does the amount of players get divided by to determine open security officer positions value = 8 min_val = 1 -/datum/config_entry/number/abductor_scaling_coeff //how many players per abductor team +CONFIG_DEF(number/abductor_scaling_coeff) //how many players per abductor team value = 15 min_val = 1 -/datum/config_entry/number/traitor_objectives_amount +CONFIG_DEF(number/traitor_objectives_amount) value = 2 min_val = 0 -/datum/config_entry/number/brother_objectives_amount +CONFIG_DEF(number/brother_objectives_amount) value = 2 min_val = 0 -/datum/config_entry/flag/reactionary_explosions //If we use reactionary explosions, explosions that react to walls and doors +CONFIG_DEF(flag/reactionary_explosions) //If we use reactionary explosions, explosions that react to walls and doors -/datum/config_entry/flag/protect_roles_from_antagonist //If security and such can be traitor/cult/other +CONFIG_DEF(flag/protect_roles_from_antagonist) //If security and such can be traitor/cult/other -/datum/config_entry/flag/protect_assistant_from_antagonist //If assistants can be traitor/cult/other +CONFIG_DEF(flag/protect_assistant_from_antagonist) //If assistants can be traitor/cult/other -/datum/config_entry/flag/enforce_human_authority //If non-human species are barred from joining as a head of staff +CONFIG_DEF(flag/enforce_human_authority) //If non-human species are barred from joining as a head of staff -/datum/config_entry/flag/allow_latejoin_antagonists // If late-joining players can be traitor/changeling +CONFIG_DEF(flag/allow_latejoin_antagonists) // If late-joining players can be traitor/changeling -/datum/config_entry/number/midround_antag_time_check // How late (in minutes you want the midround antag system to stay on, setting this to 0 will disable the system) +CONFIG_DEF(number/midround_antag_time_check) // How late (in minutes) you want the midround antag system to stay on, setting this to 0 will disable the system value = 60 min_val = 0 -/datum/config_entry/number/midround_antag_life_check // A ratio of how many people need to be alive in order for the round not to immediately end in midround antagonist +CONFIG_DEF(number/midround_antag_life_check) // A ratio of how many people need to be alive in order for the round not to immediately end in midround antagonist value = 0.7 integer = FALSE min_val = 0 max_val = 1 -/datum/config_entry/number/shuttle_refuel_delay +CONFIG_DEF(number/shuttle_refuel_delay) value = 12000 min_val = 0 -/datum/config_entry/flag/show_game_type_odds //if set this allows players to see the odds of each roundtype on the get revision screen +CONFIG_DEF(flag/show_game_type_odds) //if set this allows players to see the odds of each roundtype on the get revision screen -/datum/config_entry/keyed_flag_list/roundstart_races //races you can play as from the get go. +CONFIG_DEF(keyed_flag_list/roundstart_races) //races you can play as from the get go. -/datum/config_entry/flag/join_with_mutant_humans //players can pick mutant bodyparts for humans before joining the game +CONFIG_DEF(flag/join_with_mutant_humans) //players can pick mutant bodyparts for humans before joining the game -/datum/config_entry/flag/no_summon_guns //No +CONFIG_DEF(flag/no_summon_guns) //No -/datum/config_entry/flag/no_summon_magic //Fun +CONFIG_DEF(flag/no_summon_magic) //Fun -/datum/config_entry/flag/no_summon_events //Allowed +CONFIG_DEF(flag/no_summon_events) //Allowed -/datum/config_entry/flag/no_intercept_report //Whether or not to send a communications intercept report roundstart. This may be overriden by gamemodes. +CONFIG_DEF(flag/no_intercept_report) //Whether or not to send a communications intercept report roundstart. This may be overriden by gamemodes. -/datum/config_entry/number/arrivals_shuttle_dock_window //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station +CONFIG_DEF(number/arrivals_shuttle_dock_window) //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station value = 55 min_val = 30 -/datum/config_entry/flag/arrivals_shuttle_require_undocked //Require the arrivals shuttle to be undocked before latejoiners can join +CONFIG_DEF(flag/arrivals_shuttle_require_undocked) //Require the arrivals shuttle to be undocked before latejoiners can join -/datum/config_entry/flag/arrivals_shuttle_require_safe_latejoin //Require the arrivals shuttle to be operational in order for latejoiners to join +CONFIG_DEF(flag/arrivals_shuttle_require_safe_latejoin) //Require the arrivals shuttle to be operational in order for latejoiners to join -/datum/config_entry/string/alert_green +CONFIG_DEF(string/alert_green) value = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced." -/datum/config_entry/string/alert_blue_upto +CONFIG_DEF(string/alert_blue_upto) value = "The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible, random searches are permitted." -/datum/config_entry/string/alert_blue_downto +CONFIG_DEF(string/alert_blue_downto) value = "The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed." -/datum/config_entry/string/alert_red_upto +CONFIG_DEF(string/alert_red_upto) value = "There is an immediate serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised." -/datum/config_entry/string/alert_red_downto +CONFIG_DEF(string/alert_red_downto) value = "The station's destruction has been averted. There is still however an immediate serious threat to the station. Security may have weapons unholstered at all times, random searches are allowed and advised." -/datum/config_entry/string/alert_delta +CONFIG_DEF(string/alert_delta) value = "Destruction of the station is imminent. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill." -/datum/config_entry/flag/revival_pod_plants +CONFIG_DEF(flag/revival_pod_plants) -/datum/config_entry/flag/revival_cloning +CONFIG_DEF(flag/revival_cloning) -/datum/config_entry/number/revival_brain_life +CONFIG_DEF(number/revival_brain_life) value = -1 min_val = -1 -/datum/config_entry/flag/rename_cyborg +CONFIG_DEF(flag/rename_cyborg) -/datum/config_entry/flag/ooc_during_round +CONFIG_DEF(flag/ooc_during_round) -/datum/config_entry/flag/emojis +CONFIG_DEF(flag/emojis) -/datum/config_entry/number/run_delay //Used for modifying movement speed for mobs. +CONFIG_DEF(number/run_delay) //Used for modifying movement speed for mobs. var/static/value_cache = 0 -/datum/config_entry/number/run_delay/ValidateAndSet() +CONFIG_TWEAK(number/run_delay/ValidateAndSet()) . = ..() if(.) value_cache = value -/datum/config_entry/number/walk_delay +CONFIG_DEF(number/walk_delay) var/static/value_cache = 0 -/datum/config_entry/number/walk_delay/ValidateAndSet() +CONFIG_TWEAK(number/walk_delay/ValidateAndSet()) . = ..() if(.) value_cache = value -/datum/config_entry/number/human_delay //Mob specific modifiers. NOTE: These will affect different mob types in different ways -/datum/config_entry/number/robot_delay -/datum/config_entry/number/monkey_delay -/datum/config_entry/number/alien_delay -/datum/config_entry/number/slime_delay -/datum/config_entry/number/animal_delay +CONFIG_DEF(number/human_delay) //Mob specific modifiers. NOTE: These will affect different mob types in different ways +CONFIG_DEF(number/robot_delay) +CONFIG_DEF(number/monkey_delay) +CONFIG_DEF(number/alien_delay) +CONFIG_DEF(number/slime_delay) +CONFIG_DEF(number/animal_delay) -/datum/config_entry/number/gateway_delay //How long the gateway takes before it activates. Default is half an hour. +CONFIG_DEF(number/gateway_delay) //How long the gateway takes before it activates. Default is half an hour. value = 18000 min_val = 0 -/datum/config_entry/flag/ghost_interaction +CONFIG_DEF(flag/ghost_interaction) -/datum/config_entry/flag/silent_ai -/datum/config_entry/flag/silent_borg +CONFIG_DEF(flag/silent_ai) +CONFIG_DEF(flag/silent_borg) -/datum/config_entry/flag/sandbox_autoclose // close the sandbox panel after spawning an item, potentially reducing griff +CONFIG_DEF(flag/sandbox_autoclose) // close the sandbox panel after spawning an item, potentially reducing griff -/datum/config_entry/number/default_laws //Controls what laws the AI spawns with. +CONFIG_DEF(number/default_laws) //Controls what laws the AI spawns with. value = 0 min_val = 0 max_val = 3 -/datum/config_entry/number/silicon_max_law_amount +CONFIG_DEF(number/silicon_max_law_amount) value = 12 min_val = 0 -/datum/config_entry/keyed_flag_list/random_laws +CONFIG_DEF(keyed_flag_list/random_laws) -/datum/config_entry/keyed_number_list/law_weight +CONFIG_DEF(keyed_number_list/law_weight) splitter = "," -/datum/config_entry/number/assistant_cap +CONFIG_DEF(number/assistant_cap) value = -1 min_val = -1 -/datum/config_entry/flag/starlight -/datum/config_entry/flag/grey_assistants +CONFIG_DEF(flag/starlight) +CONFIG_DEF(flag/grey_assistants) -/datum/config_entry/number/lavaland_budget +CONFIG_DEF(number/lavaland_budget) value = 60 min_val = 0 -/datum/config_entry/number/space_budget +CONFIG_DEF(number/space_budget) value = 16 min_val = 0 -/datum/config_entry/flag/allow_random_events // Enables random events mid-round when set +CONFIG_DEF(flag/allow_random_events) // Enables random events mid-round when set -/datum/config_entry/number/events_min_time_mul // Multipliers for random events minimal starting time and minimal players amounts +CONFIG_DEF(number/events_min_time_mul) // Multipliers for random events minimal starting time and minimal players amounts value = 1 min_val = 0 integer = FALSE -/datum/config_entry/number/events_min_players_mul +CONFIG_DEF(number/events_min_players_mul) value = 1 min_val = 0 integer = FALSE -/datum/config_entry/number/mice_roundstart +CONFIG_DEF(number/mice_roundstart) value = 10 min_val = 0 -/datum/config_entry/number/bombcap +CONFIG_DEF(number/bombcap) value = 14 min_val = 4 -/datum/config_entry/flag/allow_crew_objectives - -/datum/config_entry/flag/allow_miscreants - -/datum/config_entry/flag/allow_extended_miscreants +CONFIG_DEF(flag/allow_crew_objectives) +CONFIG_DEF(flag/allow_miscreants) +CONFIG_DEF(flag/allow_extended_miscreants) /datum/config_entry/number/bombcap/ValidateAndSet(str_val) . = ..() @@ -258,9 +258,9 @@ GLOB.MAX_EX_FLASH_RANGE = value GLOB.MAX_EX_FLAME_RANGE = value -/datum/config_entry/number/emergency_shuttle_autocall_threshold +CONFIG_DEF(number/emergency_shuttle_autocall_threshold) min_val = 0 max_val = 1 integer = FALSE -/datum/config_entry/flag/ic_printing +CONFIG_DEF(flag/ic_printing) diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm deleted file mode 100644 index e6b3695033..0000000000 --- a/code/controllers/configuration/entries/general.dm +++ /dev/null @@ -1,388 +0,0 @@ -/datum/config_entry/flag/autoadmin // if autoadmin is enabled - protection = CONFIG_ENTRY_LOCKED - -/datum/config_entry/string/autoadmin_rank // the rank for autoadmins - value = "Game Master" - protection = CONFIG_ENTRY_LOCKED - -/datum/config_entry/string/servername // server name (the name of the game window) - -/datum/config_entry/string/serversqlname // short form server name used for the DB - -/datum/config_entry/string/stationname // station name (the name of the station in-game) - -/datum/config_entry/number/lobby_countdown // In between round countdown. - value = 120 - min_val = 0 - -/datum/config_entry/number/round_end_countdown // Post round murder death kill countdown - value = 25 - min_val = 0 - -/datum/config_entry/flag/hub // if the game appears on the hub or not - -/datum/config_entry/flag/log_ooc // log OOC channel - -/datum/config_entry/flag/log_access // log login/logout - -/datum/config_entry/flag/log_say // log client say - -/datum/config_entry/flag/log_admin // log admin actions - protection = CONFIG_ENTRY_LOCKED - -/datum/config_entry/flag/log_prayer // log prayers - -/datum/config_entry/flag/log_law // log lawchanges - -/datum/config_entry/flag/log_game // log game events - -/datum/config_entry/flag/log_vote // log voting - -/datum/config_entry/flag/log_whisper // log client whisper - -/datum/config_entry/flag/log_attack // log attack messages - -/datum/config_entry/flag/log_emote // log emotes - -/datum/config_entry/flag/log_adminchat // log admin chat messages - protection = CONFIG_ENTRY_LOCKED - -/datum/config_entry/flag/log_pda // log pda messages - -/datum/config_entry/flag/log_twitter // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases. - -/datum/config_entry/flag/log_world_topic // log all world.Topic() calls - -/datum/config_entry/flag/log_manifest // log crew manifest to seperate file - -/datum/config_entry/flag/allow_admin_ooccolor // Allows admins with relevant permissions to have their own ooc colour - -/datum/config_entry/flag/allow_vote_restart // allow votes to restart - -/datum/config_entry/flag/allow_vote_mode // allow votes to change mode - -/datum/config_entry/number/vote_delay // minimum time between voting sessions (deciseconds, 10 minute default) - value = 6000 - min_val = 0 - -/datum/config_entry/number/vote_period // length of voting period (deciseconds, default 1 minute) - value = 600 - min_val = 0 - -/datum/config_entry/flag/default_no_vote // vote does not default to nochange/norestart - -/datum/config_entry/flag/no_dead_vote // dead people can't vote - -/datum/config_entry/flag/allow_metadata // Metadata is supported. - -/datum/config_entry/flag/popup_admin_pm // adminPMs to non-admins show in a pop-up 'reply' window when set - -/datum/config_entry/number/fps - value = 20 - min_val = 1 - max_val = 100 //byond will start crapping out at 50, so this is just ridic - var/sync_validate = FALSE - -/datum/config_entry/number/fps/ValidateAndSet(str_val) - . = ..() - if(.) - sync_validate = TRUE - var/datum/config_entry/number/ticklag/TL = config.entries_by_type[/datum/config_entry/number/ticklag] - if(!TL.sync_validate) - TL.ValidateAndSet(10 / value) - sync_validate = FALSE - -/datum/config_entry/number/ticklag - integer = FALSE - var/sync_validate = FALSE - -/datum/config_entry/number/ticklag/New() //ticklag weirdly just mirrors fps - var/datum/config_entry/CE = /datum/config_entry/number/fps - value = 10 / initial(CE.value) - ..() - -/datum/config_entry/number/ticklag/ValidateAndSet(str_val) - . = text2num(str_val) > 0 && ..() - if(.) - sync_validate = TRUE - var/datum/config_entry/number/fps/FPS = config.entries_by_type[/datum/config_entry/number/fps] - if(!FPS.sync_validate) - FPS.ValidateAndSet(10 / value) - sync_validate = FALSE - -/datum/config_entry/flag/allow_holidays - -/datum/config_entry/number/tick_limit_mc_init //SSinitialization throttling - value = TICK_LIMIT_MC_INIT_DEFAULT - min_val = 0 //oranges warned us - integer = FALSE - -/datum/config_entry/flag/admin_legacy_system //Defines whether the server uses the legacy admin system with admins.txt or the SQL system - protection = CONFIG_ENTRY_LOCKED - -/datum/config_entry/string/hostedby - -/datum/config_entry/flag/norespawn - -/datum/config_entry/flag/guest_jobban - -/datum/config_entry/flag/usewhitelist - -/datum/config_entry/flag/ban_legacy_system //Defines whether the server uses the legacy banning system with the files in /data or the SQL system. - protection = CONFIG_ENTRY_LOCKED - -/datum/config_entry/flag/use_age_restriction_for_jobs //Do jobs use account age restrictions? --requires database - -/datum/config_entry/flag/use_account_age_for_jobs //Uses the time they made the account for the job restriction stuff. New player joining alerts should be unaffected. - -/datum/config_entry/flag/use_exp_tracking - -/datum/config_entry/flag/use_exp_restrictions_heads - -/datum/config_entry/number/use_exp_restrictions_heads_hours - value = 0 - min_val = 0 - -/datum/config_entry/flag/use_exp_restrictions_heads_department - -/datum/config_entry/flag/use_exp_restrictions_other - -/datum/config_entry/flag/use_exp_restrictions_admin_bypass - -/datum/config_entry/string/server - -/datum/config_entry/string/banappeals - -/datum/config_entry/string/wikiurl - value = "http://www.tgstation13.org/wiki" - -/datum/config_entry/string/forumurl - value = "http://tgstation13.org/phpBB/index.php" - -/datum/config_entry/string/rulesurl - value = "http://www.tgstation13.org/wiki/Rules" - -/datum/config_entry/string/githuburl - value = "https://www.github.com/tgstation/-tg-station" - -/datum/config_entry/number/githubrepoid - value = null - min_val = 0 - -/datum/config_entry/flag/guest_ban - -/datum/config_entry/number/id_console_jobslot_delay - value = 30 - min_val = 0 - -/datum/config_entry/number/inactivity_period //time in ds until a player is considered inactive - value = 3000 - min_val = 0 - -/datum/config_entry/number/inactivity_period/ValidateAndSet(str_val) - . = ..() - if(.) - value *= 10 //documented as seconds in config.txt - -/datum/config_entry/number/afk_period //time in ds until a player is considered inactive - value = 3000 - min_val = 0 - -/datum/config_entry/number/afk_period/ValidateAndSet(str_val) - . = ..() - if(.) - value *= 10 //documented as seconds in config.txt - -/datum/config_entry/flag/kick_inactive //force disconnect for inactive players - -/datum/config_entry/flag/load_jobs_from_txt - -/datum/config_entry/flag/forbid_singulo_possession - -/datum/config_entry/flag/automute_on //enables automuting/spam prevention - -/datum/config_entry/string/panic_server_name - -/datum/config_entry/string/panic_server_name/ValidateAndSet(str_val) - return str_val != "\[Put the name here\]" && ..() - -/datum/config_entry/string/panic_server_address //Reconnect a player this linked server if this server isn't accepting new players - -/datum/config_entry/string/panic_server_address/ValidateAndSet(str_val) - return str_val != "byond://address:port" && ..() - -/datum/config_entry/string/invoke_youtubedl - protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN - -/datum/config_entry/flag/show_irc_name - -/datum/config_entry/flag/see_own_notes //Can players see their own admin notes - -/datum/config_entry/number/note_fresh_days - value = null - min_val = 0 - integer = FALSE - -/datum/config_entry/number/note_stale_days - value = null - min_val = 0 - integer = FALSE - -/datum/config_entry/flag/maprotation - -/datum/config_entry/number/maprotatechancedelta - value = 0.75 - min_val = 0 - max_val = 1 - integer = FALSE - -/datum/config_entry/number/soft_popcap - value = null - min_val = 0 - -/datum/config_entry/number/hard_popcap - value = null - min_val = 0 - -/datum/config_entry/number/extreme_popcap - value = null - min_val = 0 - -/datum/config_entry/string/soft_popcap_message - value = "Be warned that the server is currently serving a high number of users, consider using alternative game servers." - -/datum/config_entry/string/hard_popcap_message - value = "The server is currently serving a high number of users, You cannot currently join. You may wait for the number of living crew to decline, observe, or find alternative servers." - -/datum/config_entry/string/extreme_popcap_message - value = "The server is currently serving a high number of users, find alternative servers." - -/datum/config_entry/flag/panic_bunker // prevents people the server hasn't seen before from connecting - -/datum/config_entry/number/notify_new_player_age // how long do we notify admins of a new player - min_val = -1 - -/datum/config_entry/number/notify_new_player_account_age // how long do we notify admins of a new byond account - min_val = 0 - -/datum/config_entry/flag/irc_first_connection_alert // do we notify the irc channel when somebody is connecting for the first time? - -/datum/config_entry/flag/check_randomizer - -/datum/config_entry/string/ipintel_email - -/datum/config_entry/string/ipintel_email/ValidateAndSet(str_val) - return str_val != "ch@nge.me" && ..() - -/datum/config_entry/number/ipintel_rating_bad - value = 1 - integer = FALSE - min_val = 0 - max_val = 1 - -/datum/config_entry/number/ipintel_save_good - value = 12 - min_val = 0 - -/datum/config_entry/number/ipintel_save_bad - value = 1 - min_val = 0 - -/datum/config_entry/string/ipintel_domain - value = "check.getipintel.net" - -/datum/config_entry/flag/aggressive_changelog - -/datum/config_entry/flag/autoconvert_notes //if all connecting player's notes should attempt to be converted to the database - protection = CONFIG_ENTRY_LOCKED - -/datum/config_entry/flag/allow_webclient - -/datum/config_entry/flag/webclient_only_byond_members - -/datum/config_entry/flag/announce_admin_logout - -/datum/config_entry/flag/announce_admin_login - -/datum/config_entry/flag/allow_map_voting - -/datum/config_entry/flag/generate_minimaps - -/datum/config_entry/number/client_warn_version - value = null - min_val = 500 - max_val = DM_VERSION - 1 - -/datum/config_entry/string/client_warn_message - value = "Your version of byond may have issues or be blocked from accessing this server in the future." - -/datum/config_entry/flag/client_warn_popup - -/datum/config_entry/number/client_error_version - value = null - min_val = 500 - max_val = DM_VERSION - 1 - -/datum/config_entry/string/client_error_message - value = "Your version of byond is too old, may have issues, and is blocked from accessing this server." - -/datum/config_entry/number/minute_topic_limit - value = null - min_val = 0 - -/datum/config_entry/number/second_topic_limit - value = null - min_val = 0 - -/datum/config_entry/number/error_cooldown // The "cooldown" time for each occurrence of a unique error - value = 600 - min_val = 0 - -/datum/config_entry/number/error_limit // How many occurrences before the next will silence them - value = 50 - -/datum/config_entry/number/error_silence_time // How long a unique error will be silenced for - value = 6000 - -/datum/config_entry/number/error_msg_delay // How long to wait between messaging admins about occurrences of a unique error - value = 50 - -/datum/config_entry/flag/irc_announce_new_game - -/datum/config_entry/flag/debug_admin_hrefs - -/datum/config_entry/number/mc_tick_rate/base_mc_tick_rate - integer = FALSE - value = 1 - -/datum/config_entry/number/mc_tick_rate/high_pop_mc_tick_rate - integer = FALSE - value = 1.1 - -/datum/config_entry/number/mc_tick_rate/high_pop_mc_mode_amount - value = 65 - -/datum/config_entry/number/mc_tick_rate/disable_high_pop_mc_mode_amount - value = 60 - -/datum/config_entry/number/mc_tick_rate - abstract_type = /datum/config_entry/number/mc_tick_rate - -/datum/config_entry/number/mc_tick_rate/ValidateAndSet(str_val) - . = ..() - if (.) - Master.UpdateTickRate() - -/datum/config_entry/flag/resume_after_initializations - -/datum/config_entry/flag/resume_after_initializations/ValidateAndSet(str_val) - . = ..() - if(. && Master.current_runlevel) - world.sleep_offline = !value - -/datum/config_entry/number/rounds_until_hard_restart - value = -1 - min_val = 0 - -/datum/config_entry/string/default_view - value = "15x15" diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index 93230b3e37..59b6fc34ef 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -394,4 +394,4 @@ SUBSYSTEM_DEF(air) #undef SSAIR_EXCITEDGROUPS #undef SSAIR_HIGHPRESSURE #undef SSAIR_HOTSPOT -#undef SSAIR_SUPERCONDUCTIVITY +#undef SSAIR_SUPERCONDUCTIVITY \ No newline at end of file diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index 485e4e7fd3..941fcbbcd6 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -8,11 +8,11 @@ SUBSYSTEM_DEF(blackbox) var/list/feedback = list() //list of datum/feedback_variable var/triggertime = 0 var/sealed = FALSE //time to stop tracking stats? - var/list/versions = list("antagonists" = 3, - "admin_secrets_fun_used" = 2, - "time_dilation_current" = 3, + var/list/research_levels = list() //list of highest tech levels attained that isn't lost lost by destruction of RD computers + var/list/versions = list("time_dilation_current" = 2, "science_techweb_unlock" = 2) //associative list of any feedback variables that have had their format changed since creation and their current version, remember to update this + /datum/controller/subsystem/blackbox/Initialize() triggertime = world.time . = ..() @@ -62,6 +62,8 @@ SUBSYSTEM_DEF(blackbox) record_feedback("tally", "radio_usage", MS.pda_msgs.len, "PDA") if (MS.rc_msgs.len) record_feedback("tally", "radio_usage", MS.rc_msgs.len, "request console") + if(research_levels.len) + SSblackbox.record_feedback("associative", "high_research_level", 1, research_levels) if (!SSdbcore.Connect()) return @@ -88,35 +90,39 @@ SUBSYSTEM_DEF(blackbox) sealed = TRUE return TRUE +/datum/controller/subsystem/blackbox/proc/log_research(tech, level) + if(!(tech in research_levels) || research_levels[tech] < level) + research_levels[tech] = level + /datum/controller/subsystem/blackbox/proc/LogBroadcast(freq) if(sealed) return switch(freq) - if(FREQ_COMMON) + if(1459) record_feedback("tally", "radio_usage", 1, "common") - if(FREQ_SCIENCE) + if(GLOB.SCI_FREQ) record_feedback("tally", "radio_usage", 1, "science") - if(FREQ_COMMAND) + if(GLOB.COMM_FREQ) record_feedback("tally", "radio_usage", 1, "command") - if(FREQ_MEDICAL) + if(GLOB.MED_FREQ) record_feedback("tally", "radio_usage", 1, "medical") - if(FREQ_ENGINEERING) + if(GLOB.ENG_FREQ) record_feedback("tally", "radio_usage", 1, "engineering") - if(FREQ_SECURITY) + if(GLOB.SEC_FREQ) record_feedback("tally", "radio_usage", 1, "security") - if(FREQ_SYNDICATE) + if(GLOB.SYND_FREQ) record_feedback("tally", "radio_usage", 1, "syndicate") - if(FREQ_SERVICE) + if(GLOB.SERV_FREQ) record_feedback("tally", "radio_usage", 1, "service") - if(FREQ_SUPPLY) + if(GLOB.SUPP_FREQ) record_feedback("tally", "radio_usage", 1, "supply") - if(FREQ_CENTCOM) + if(GLOB.CENTCOM_FREQ) record_feedback("tally", "radio_usage", 1, "centcom") - if(FREQ_AI_PRIVATE) + if(GLOB.AIPRIV_FREQ) record_feedback("tally", "radio_usage", 1, "ai private") - if(FREQ_CTF_RED) + if(GLOB.REDTEAM_FREQ) record_feedback("tally", "radio_usage", 1, "CTF red team") - if(FREQ_CTF_BLUE) + if(GLOB.BLUETEAM_FREQ) record_feedback("tally", "radio_usage", 1, "CTF blue team") else record_feedback("tally", "radio_usage", 1, "other") @@ -186,7 +192,7 @@ Versioning "gun_fired" = 2) */ /datum/controller/subsystem/blackbox/proc/record_feedback(key_type, key, increment, data, overwrite) - if(sealed || !key_type || !istext(key) || !isnum(increment) || !data) + if(sealed || !key_type || !istext(key) || !isnum(increment || !data)) return var/datum/feedback_variable/FV = find_feedback_datum(key, key_type) switch(key_type) @@ -219,10 +225,7 @@ Versioning var/pos = length(FV.json["data"]) + 1 FV.json["data"]["[pos]"] = list() //in 512 "pos" can be replaced with "[FV.json["data"].len+1]" for(var/i in data) - if(islist(data[i])) - FV.json["data"]["[pos]"]["[i]"] = data[i] //and here with "[FV.json["data"].len]" - else - FV.json["data"]["[pos]"]["[i]"] = "[data[i]]" + FV.json["data"]["[pos]"]["[i]"] = "[data[i]]" //and here with "[FV.json["data"].len]" else CRASH("Invalid feedback key_type: [key_type]") diff --git a/code/controllers/subsystem/input.dm b/code/controllers/subsystem/input.dm deleted file mode 100644 index f4763a74ed..0000000000 --- a/code/controllers/subsystem/input.dm +++ /dev/null @@ -1,12 +0,0 @@ -SUBSYSTEM_DEF(input) - name = "Input" - wait = 1 //SS_TICKER means this runs every tick - flags = SS_TICKER | SS_NO_INIT | SS_KEEP_TIMING - priority = 151 - runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY - -/datum/controller/subsystem/input/fire() - 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] - C.keyLoop() \ No newline at end of file diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 756a22174a..5cfbeb9414 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -107,6 +107,9 @@ SUBSYSTEM_DEF(job) if(player.mind && job.title in player.mind.restricted_roles) Debug("FOC incompatible with antagonist role, Player: [player]") continue + if(CONFIG_GET(flag/enforce_human_authority) && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features)) + Debug("FOC non-human failed, Player: [player]") + continue if(player.client.prefs.GetJobDepartment(job, level) & job.flag) Debug("FOC pass, Player: [player], Level:[level]") candidates += player @@ -141,6 +144,11 @@ SUBSYSTEM_DEF(job) Debug("GRJ incompatible with antagonist role, Player: [player], Job: [job.title]") continue + if(CONFIG_GET(flag/enforce_human_authority) && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features)) + Debug("GRJ non-human failed, Player: [player]") + continue + + if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1) Debug("GRJ Random job given, Player: [player], Job: [job]") if(AssignRole(player, job.title)) @@ -311,6 +319,10 @@ SUBSYSTEM_DEF(job) Debug("DO incompatible with antagonist role, Player: [player], Job:[job.title]") continue + if(CONFIG_GET(flag/enforce_human_authority) && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features)) + Debug("DO non-human failed, Player: [player], Job:[job.title]") + continue + // If the player wants that job on this level, then try give it to him. if(player.client.prefs.GetJobDepartment(job, level) & job.flag) diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm index 1ad3a8ab15..43565846fb 100644 --- a/code/controllers/subsystem/lighting.dm +++ b/code/controllers/subsystem/lighting.dm @@ -22,7 +22,7 @@ SUBSYSTEM_DEF(lighting) create_all_lighting_objects() initialized = TRUE - + fire(FALSE, TRUE) ..() diff --git a/code/controllers/subsystem/machines.dm b/code/controllers/subsystem/machines.dm index e235afaaa4..db6af6d686 100644 --- a/code/controllers/subsystem/machines.dm +++ b/code/controllers/subsystem/machines.dm @@ -62,4 +62,4 @@ SUBSYSTEM_DEF(machines) if (istype(SSmachines.processing)) processing = SSmachines.processing if (istype(SSmachines.powernets)) - powernets = SSmachines.powernets + powernets = SSmachines.powernets \ No newline at end of file diff --git a/code/controllers/subsystem/npcpool.dm b/code/controllers/subsystem/npcpool.dm index 63ceb15ab8..6ee4626f25 100644 --- a/code/controllers/subsystem/npcpool.dm +++ b/code/controllers/subsystem/npcpool.dm @@ -135,12 +135,12 @@ SUBSYSTEM_DEF(npcpool) if(facCount == 1 && helpProb) helpProb = 100 - + if(prob(helpProb) && candidate.takeDelegate(check,FALSE)) --canBeUsed.len candidate.eye_color = "yellow" candidate.update_icons() - + if(!currentrun.len || MC_TICK_CHECK) //don't change SS state if it isn't necessary return diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm index b98be937fc..d310f46d2a 100644 --- a/code/controllers/subsystem/persistence.dm +++ b/code/controllers/subsystem/persistence.dm @@ -250,4 +250,4 @@ SUBSYSTEM_DEF(persistence) var/list/file_data = list() file_data["data"] = saved_modes fdel(json_file) - WRITE_FILE(json_file, json_encode(file_data)) + WRITE_FILE(json_file, json_encode(file_data)) \ No newline at end of file diff --git a/code/controllers/subsystem/radio.dm b/code/controllers/subsystem/radio.dm index 8299709392..43803aa647 100644 --- a/code/controllers/subsystem/radio.dm +++ b/code/controllers/subsystem/radio.dm @@ -14,22 +14,35 @@ SUBSYSTEM_DEF(radio) /datum/controller/subsystem/radio/proc/add_object(obj/device, new_frequency as num, filter = null as text|null) var/f_text = num2text(new_frequency) var/datum/radio_frequency/frequency = frequencies[f_text] + if(!frequency) - frequencies[f_text] = frequency = new(new_frequency) + frequency = new + frequency.frequency = new_frequency + frequencies[f_text] = frequency + frequency.add_listener(device, filter) return frequency /datum/controller/subsystem/radio/proc/remove_object(obj/device, old_frequency) var/f_text = num2text(old_frequency) var/datum/radio_frequency/frequency = frequencies[f_text] + if(frequency) frequency.remove_listener(device) - // let's don't delete frequencies in case a non-listener keeps a reference + + if(frequency.devices.len == 0) + qdel(frequency) + frequencies -= f_text + return 1 /datum/controller/subsystem/radio/proc/return_frequency(new_frequency as num) var/f_text = num2text(new_frequency) var/datum/radio_frequency/frequency = frequencies[f_text] + if(!frequency) - frequencies[f_text] = frequency = new(new_frequency) + frequency = new + frequency.frequency = new_frequency + frequencies[f_text] = frequency + return frequency diff --git a/code/controllers/subsystem/research.dm b/code/controllers/subsystem/research.dm index a2dc4b9c74..d1bcf31885 100644 --- a/code/controllers/subsystem/research.dm +++ b/code/controllers/subsystem/research.dm @@ -54,7 +54,6 @@ SUBSYSTEM_DEF(research) bitcoins = single_server_income break //Just need one to work. var/income_time_difference = world.time - last_income - science_tech.last_bitcoins = bitcoins // Doesn't take tick drift into account bitcoins *= income_time_difference / 10 science_tech.research_points += bitcoins last_income = world.time diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index 24e31e3c7c..c80bc17047 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -158,7 +158,7 @@ SUBSYSTEM_DEF(shuttle) break /datum/controller/subsystem/shuttle/proc/CheckAutoEvac() - if(emergencyNoEscape || emergencyNoRecall || !emergency || !SSticker.HasRoundStarted()) + if(emergencyNoEscape || emergencyNoRecall || !emergency) return var/threshold = CONFIG_GET(number/emergency_shuttle_autocall_threshold) @@ -261,7 +261,7 @@ SUBSYSTEM_DEF(shuttle) if(!admiral_message) admiral_message = pick(GLOB.admiral_messages) - var/intercepttext = "Nanotrasen Update: Request For Shuttle.
\ + var/intercepttext = "NanoTrasen Update: Request For Shuttle.
\ To whom it may concern:

\ We have taken note of the situation upon [station_name()] and have come to the \ conclusion that it does not warrant the abandonment of the station.
\ @@ -382,7 +382,7 @@ SUBSYSTEM_DEF(shuttle) emergency.setTimer(emergencyDockTime) priority_announce("Hostile environment resolved. \ You have 3 minutes to board the Emergency Shuttle.", - null, 'sound/ai/shuttledock.ogg', "Priority") + null, 'sound/AI/shuttledock.ogg', "Priority") //try to move/request to dockHome if possible, otherwise dockAway. Mainly used for admin buttons /datum/controller/subsystem/shuttle/proc/toggleShuttle(shuttleId, dockHome, dockAway, timed) diff --git a/code/controllers/subsystem/squeak.dm b/code/controllers/subsystem/squeak.dm index 022b659d8a..0148011e8b 100644 --- a/code/controllers/subsystem/squeak.dm +++ b/code/controllers/subsystem/squeak.dm @@ -1,6 +1,6 @@ // The Squeak // because this is about placement of mice mobs, and nothing to do with -// mice - the computer peripheral +// mice - the computer peripheral SUBSYSTEM_DEF(squeak) name = "Squeak" diff --git a/code/controllers/subsystem/stickyban.dm b/code/controllers/subsystem/stickyban.dm index 371cf22b3b..8251df0039 100644 --- a/code/controllers/subsystem/stickyban.dm +++ b/code/controllers/subsystem/stickyban.dm @@ -27,6 +27,6 @@ SUBSYSTEM_DEF(stickyban) ban["existing_user_matches_this_round"] = list() ban["admin_matches_this_round"] = list() cache[ckey] = ban - + for (var/bannedckey in cache) world.SetConfig("ban", bannedckey, list2stickyban(cache[bannedckey])) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 54b693d543..881bb7fcb7 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -398,6 +398,204 @@ SUBSYSTEM_DEF(ticker) var/mob/living/L = I L.notransform = FALSE +/datum/controller/subsystem/ticker/proc/declare_completion() + set waitfor = FALSE + var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED + var/num_survivors = 0 + var/num_escapees = 0 + var/num_shuttle_escapees = 0 + var/list/successfulCrew = list() + var/list/miscreants = list() + + to_chat(world, "


The round has ended.") + if(LAZYLEN(GLOB.round_end_notifiees)) + send2irc("Notice", "[GLOB.round_end_notifiees.Join(", ")] the round has ended.") + +/* var/nocredits = config.no_credits_round_end + for(var/client/C in GLOB.clients) + if(!C.credits && !nocredits) + C.RollCredits() + C.playtitlemusic(40)*/ + + //Player status report + for(var/i in GLOB.mob_list) + var/mob/Player = i + if(Player.mind && !isnewplayer(Player)) + if(Player.stat != DEAD && !isbrain(Player)) + num_survivors++ + if(station_evacuated) //If the shuttle has already left the station + var/list/area/shuttle_areas + if(SSshuttle && SSshuttle.emergency) + shuttle_areas = SSshuttle.emergency.shuttle_areas + if(!Player.onCentCom() && !Player.onSyndieBase()) + to_chat(Player, "You managed to survive, but were marooned on [station_name()]...") + else + num_escapees++ + to_chat(Player, "You managed to survive the events on [station_name()] as [Player.real_name].") + if(shuttle_areas[get_area(Player)]) + num_shuttle_escapees++ + else + to_chat(Player, "You managed to survive the events on [station_name()] as [Player.real_name].") + else + to_chat(Player, "You did not survive the events on [station_name()]...") + + CHECK_TICK + + //Round statistics report + var/datum/station_state/end_state = new /datum/station_state() + end_state.count() + var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100) + + to_chat(world, "
[GLOB.TAB]Shift Duration: [DisplayTimeText(world.time - SSticker.round_start_time)]") + to_chat(world, "
[GLOB.TAB]Station Integrity: [mode.station_was_nuked ? "Destroyed" : "[station_integrity]%"]") + if(mode.station_was_nuked) + SSticker.news_report = STATION_DESTROYED_NUKE + var/total_players = GLOB.joined_player_list.len + if(total_players) + to_chat(world, "
[GLOB.TAB]Total Population: [total_players]") + if(station_evacuated) + to_chat(world, "
[GLOB.TAB]Evacuation Rate: [num_escapees] ([PERCENT(num_escapees/total_players)]%)") + to_chat(world, "
[GLOB.TAB](on emergency shuttle): [num_shuttle_escapees] ([PERCENT(num_shuttle_escapees/total_players)]%)") + news_report = STATION_EVACUATED + if(SSshuttle.emergency.is_hijacked()) + news_report = SHUTTLE_HIJACK + to_chat(world, "
[GLOB.TAB]Survival Rate: [num_survivors] ([PERCENT(num_survivors/total_players)]%)") + to_chat(world, "
") + + CHECK_TICK + + //Silicon laws report + for (var/i in GLOB.ai_list) + var/mob/living/silicon/ai/aiPlayer = i + if (aiPlayer.stat != DEAD && aiPlayer.mind) + to_chat(world, "[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws at the end of the round were:") + aiPlayer.show_laws(1) + else if (aiPlayer.mind) //if the dead ai has a mind, use its key instead + to_chat(world, "[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws when it was deactivated were:") + aiPlayer.show_laws(1) + + to_chat(world, "Total law changes: [aiPlayer.law_change_counter]") + + if (aiPlayer.connected_robots.len) + var/robolist = "[aiPlayer.real_name]'s minions were: " + for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots) + if(robo.mind) + robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.mind.key]), ":" (Played by: [robo.mind.key]), "]" + to_chat(world, "[robolist]") + + CHECK_TICK + + for (var/mob/living/silicon/robot/robo in GLOB.silicon_mobs) + if (!robo.connected_ai && robo.mind) + if (robo.stat != DEAD) + to_chat(world, "[robo.name] (Played by: [robo.mind.key]) survived as an AI-less borg! Its laws were:") + else + to_chat(world, "[robo.name] (Played by: [robo.mind.key]) was unable to survive the rigors of being a cyborg without an AI. Its laws were:") + + if(robo) //How the hell do we lose robo between here and the world messages directly above this? + robo.laws.show_laws(world) + + CHECK_TICK + + mode.declare_completion()//To declare normal completion. + + CHECK_TICK + + //calls auto_declare_completion_* for all modes + for(var/handler in typesof(/datum/game_mode/proc)) + if (findtext("[handler]","auto_declare_completion_")) + call(mode, handler)(force_ending) + + CHECK_TICK + + if(CONFIG_GET(string/cross_server_address)) + send_news_report() + + CHECK_TICK + + //Print a list of antagonists to the server log + var/list/total_antagonists = list() + //Look into all mobs in world, dead or alive + for(var/datum/mind/Mind in minds) + var/temprole = Mind.special_role + if(temprole) //if they are an antagonist of some sort. + if(temprole in total_antagonists) //If the role exists already, add the name to it + total_antagonists[temprole] += ", [Mind.name]([Mind.key])" + else + total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob + total_antagonists[temprole] += ": [Mind.name]([Mind.key])" + + CHECK_TICK + + //Now print them all into the log! + log_game("Antagonists at round end were...") + for(var/i in total_antagonists) + log_game("[i]s[total_antagonists[i]].") + + CHECK_TICK + + for(var/datum/mind/crewMind in minds) + if(!crewMind.current || !crewMind.objectives.len) + continue + for(var/datum/objective/miscreant/MO in crewMind.objectives) + miscreants += "[crewMind.current.real_name] (Played by: [crewMind.key])
Objective: [MO.explanation_text] (Optional)" + for(var/datum/objective/crew/CO in crewMind.objectives) + if(CO.check_completion()) + to_chat(crewMind.current, "
Your optional objective: [CO.explanation_text] Success!") + successfulCrew += "[crewMind.current.real_name] (Played by: [crewMind.key])
Objective: [CO.explanation_text] Success! (Optional)" + else + to_chat(crewMind.current, "
Your optional objective: [CO.explanation_text] Failed.") + + if (successfulCrew.len) + var/completedObjectives = "The following crew members completed their Crew Objectives:
" + for(var/i in successfulCrew) + completedObjectives += "[i]
" + to_chat(world, "[completedObjectives]
") + else + if(CONFIG_GET(flag/allow_crew_objectives)) + to_chat(world, "Nobody completed their Crew Objectives!
") + + CHECK_TICK + + if (miscreants.len) + var/miscreantObjectives = "The following crew members were miscreants:
" + for(var/i in miscreants) + miscreantObjectives += "[i]
" + to_chat(world, "[miscreantObjectives]
") + + CHECK_TICK + + mode.declare_station_goal_completion() + + CHECK_TICK + //medals, placed far down so that people can actually see the commendations. + if(GLOB.commendations.len) + to_chat(world, "Medal Commendations:") + for (var/com in GLOB.commendations) + to_chat(world, com) + + CHECK_TICK + + //Collects persistence features + if(mode.allow_persistence_save) + SSpersistence.CollectData() + + //stop collecting feedback during grifftime + SSblackbox.Seal() + + sleep(50) + ready_for_reboot = TRUE + standard_reboot() + +/datum/controller/subsystem/ticker/proc/standard_reboot() + if(ready_for_reboot) + if(mode.station_was_nuked) + Reboot("Station destroyed by Nuclear Device.", "nuke") + else + Reboot("Round ended.", "proper completion") + else + CRASH("Attempted standard reboot without ticker roundend completion") + /datum/controller/subsystem/ticker/proc/send_tip_of_the_round() var/m if(selected_tip) @@ -631,7 +829,6 @@ SUBSYSTEM_DEF(ticker) world.Reboot() /datum/controller/subsystem/ticker/Shutdown() - gather_newscaster() //called here so we ensure the log is created even upon admin reboot if(!round_end_sound) round_end_sound = pick(\ 'sound/roundend/newroundsexy.ogg', diff --git a/code/controllers/subsystem/time_track.dm b/code/controllers/subsystem/time_track.dm index 3b19ae31cd..17cfa6fc06 100644 --- a/code/controllers/subsystem/time_track.dm +++ b/code/controllers/subsystem/time_track.dm @@ -35,4 +35,4 @@ SUBSYSTEM_DEF(time_track) last_tick_realtime = current_realtime last_tick_byond_time = current_byondtime last_tick_tickcount = current_tickcount - SSblackbox.record_feedback("associative", "time_dilation_current", 1, list("[SQLtime()]" = list("current" = "[time_dilation_current]", "avg_fast" = "[time_dilation_avg_fast]", "avg" = "[time_dilation_avg]", "avg_slow" = "[time_dilation_avg_slow]"))) + SSblackbox.record_feedback("associative", "time_dilation_current", 1, list("[time_dilation_current]" = "[SQLtime()]")) diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm index 938cd86396..3a2ca82bcd 100644 --- a/code/controllers/subsystem/timer.dm +++ b/code/controllers/subsystem/timer.dm @@ -1,6 +1,5 @@ #define BUCKET_LEN (world.fps*1*60) //how many ticks should we keep in the bucket. (1 minutes worth) -#define BUCKET_POS(timer) ((round((timer.timeToRun - SStimer.head_offset) / world.tick_lag) % BUCKET_LEN) + 1) -#define TIMER_MAX (world.time + TICKS2DS(min(BUCKET_LEN-(SStimer.practical_offset-DS2TICKS(world.time - SStimer.head_offset))-1, BUCKET_LEN-1))) +#define BUCKET_POS(timer) (round((timer.timeToRun - SStimer.head_offset) / world.tick_lag) + 1) #define TIMER_ID_MAX (2**24) //max float with integer precision SUBSYSTEM_DEF(timer) @@ -10,11 +9,11 @@ SUBSYSTEM_DEF(timer) flags = SS_TICKER|SS_NO_INIT - var/list/datum/timedevent/second_queue = list() //awe, yes, you've had first queue, but what about second queue? + var/list/datum/timedevent/processing = list() var/list/hashes = list() var/head_offset = 0 //world.time of the first entry in the the bucket. - var/practical_offset = 1 //index of the first non-empty item in the bucket. + var/practical_offset = 0 //index of the first non-empty item in the bucket. var/bucket_resolution = 0 //world.tick_lag the bucket was designed for var/bucket_count = 0 //how many timers are in the buckets @@ -28,19 +27,13 @@ SUBSYSTEM_DEF(timer) var/static/last_invoke_warning = 0 var/static/bucket_auto_reset = TRUE -/datum/controller/subsystem/timer/PreInit() - bucket_list.len = BUCKET_LEN - head_offset = world.time - bucket_resolution = world.tick_lag - /datum/controller/subsystem/timer/stat_entry(msg) - ..("B:[bucket_count] P:[length(second_queue)] H:[length(hashes)] C:[length(clienttime_timers)] S:[length(timer_id_dict)]") + ..("B:[bucket_count] P:[length(processing)] H:[length(hashes)] C:[length(clienttime_timers)]") /datum/controller/subsystem/timer/fire(resumed = FALSE) var/lit = last_invoke_tick var/last_check = world.time - TIMER_NO_INVOKE_WARNING var/list/bucket_list = src.bucket_list - if(!bucket_count) last_invoke_tick = world.time @@ -57,9 +50,9 @@ SUBSYSTEM_DEF(timer) var/datum/timedevent/bucket_head = bucket_list[i] if (!bucket_head) continue - + log_world("Active timers at index [i]:") - + var/datum/timedevent/bucket_node = bucket_head var/anti_loop_check = 1000 do @@ -67,62 +60,50 @@ SUBSYSTEM_DEF(timer) bucket_node = bucket_node.next anti_loop_check-- while(bucket_node && bucket_node != bucket_head && anti_loop_check) - log_world("Active timers in the second_queue queue:") - for(var/I in second_queue) + log_world("Active timers in the processing queue:") + for(var/I in processing) log_world(get_timer_debug_string(I)) - var/next_clienttime_timer_index = 0 - var/len = length(clienttime_timers) - - for (next_clienttime_timer_index in 1 to len) + while(length(clienttime_timers)) + var/datum/timedevent/ctime_timer = clienttime_timers[clienttime_timers.len] + if (ctime_timer.timeToRun <= REALTIMEOFDAY) + --clienttime_timers.len + var/datum/callback/callBack = ctime_timer.callBack + ctime_timer.spent = REALTIMEOFDAY + callBack.InvokeAsync() + qdel(ctime_timer) + else + break //None of the rest are ready to run if (MC_TICK_CHECK) - next_clienttime_timer_index-- - break - var/datum/timedevent/ctime_timer = clienttime_timers[next_clienttime_timer_index] - if (ctime_timer.timeToRun > REALTIMEOFDAY) - next_clienttime_timer_index-- - break - - var/datum/callback/callBack = ctime_timer.callBack - if (!callBack) - clienttime_timers.Cut(next_clienttime_timer_index,next_clienttime_timer_index+1) - CRASH("Invalid timer: [get_timer_debug_string(ctime_timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset], REALTIMEOFDAY: [REALTIMEOFDAY]") - - ctime_timer.spent = REALTIMEOFDAY - callBack.InvokeAsync() - qdel(ctime_timer) - - - if (next_clienttime_timer_index) - clienttime_timers.Cut(1,next_clienttime_timer_index+1) - - if (MC_TICK_CHECK) - return + return var/static/list/spent = list() var/static/datum/timedevent/timer - if (practical_offset > BUCKET_LEN) - head_offset += TICKS2DS(BUCKET_LEN) - practical_offset = 1 - resumed = FALSE + var/static/datum/timedevent/head - if ((length(bucket_list) != BUCKET_LEN) || (world.tick_lag != bucket_resolution)) - reset_buckets() + if (practical_offset > BUCKET_LEN || (!resumed && length(bucket_list) != BUCKET_LEN || world.tick_lag != bucket_resolution)) + shift_buckets() bucket_list = src.bucket_list resumed = FALSE if (!resumed) timer = null + head = null - while (practical_offset <= BUCKET_LEN && head_offset + (practical_offset*world.tick_lag) <= world.time) - var/datum/timedevent/head = bucket_list[practical_offset] + while (practical_offset <= BUCKET_LEN && head_offset + (practical_offset*world.tick_lag) <= world.time && !MC_TICK_CHECK) if (!timer || !head || timer == head) head = bucket_list[practical_offset] + if (!head) + practical_offset++ + if (MC_TICK_CHECK) + break + continue timer = head - while (timer) + do var/datum/callback/callBack = timer.callBack if (!callBack) + qdel(timer) bucket_resolution = null //force bucket recreation CRASH("Invalid timer: [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]") @@ -132,68 +113,15 @@ SUBSYSTEM_DEF(timer) callBack.InvokeAsync() last_invoke_tick = world.time + timer = timer.next + if (MC_TICK_CHECK) return - - timer = timer.next - if (timer == head) - break - - - bucket_list[practical_offset++] = null - - //we freed up a bucket, lets see if anything in second_queue needs to be shifted to that bucket. - var/i = 0 - var/L = length(second_queue) - for (i in 1 to L) - timer = second_queue[i] - if (timer.timeToRun >= TIMER_MAX) - i-- - break - - if (timer.timeToRun < head_offset) - bucket_resolution = null //force bucket recreation - CRASH("[i] Invalid timer state: Timer in long run queue with a time to run less then head_offset. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]") - - if (timer.callBack && !timer.spent) - timer.callBack.InvokeAsync() - spent += timer - bucket_count++ - else if(!QDELETED(timer)) - qdel(timer) - continue - - if (timer.timeToRun < head_offset + TICKS2DS(practical_offset)) - bucket_resolution = null //force bucket recreation - CRASH("[i] Invalid timer state: Timer in long run queue that would require a backtrack to transfer to short run queue. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]") - if (timer.callBack && !timer.spent) - timer.callBack.InvokeAsync() - spent += timer - bucket_count++ - else if(!QDELETED(timer)) - qdel(timer) - continue - - bucket_count++ - var/bucket_pos = max(1, BUCKET_POS(timer)) - - var/datum/timedevent/bucket_head = bucket_list[bucket_pos] - if (!bucket_head) - bucket_list[bucket_pos] = timer - timer.next = null - timer.prev = null - continue - - if (!bucket_head.prev) - bucket_head.prev = bucket_head - timer.next = bucket_head - timer.prev = bucket_head.prev - timer.next.prev = timer - timer.prev.next = timer - if (i) - second_queue.Cut(1, i+1) - + while (timer && timer != head) timer = null + bucket_list[practical_offset++] = null + if (MC_TICK_CHECK) + return bucket_count -= length(spent) @@ -213,7 +141,7 @@ SUBSYSTEM_DEF(timer) if(!TE.callBack) . += ", NO CALLBACK" -/datum/controller/subsystem/timer/proc/reset_buckets() +/datum/controller/subsystem/timer/proc/shift_buckets() var/list/bucket_list = src.bucket_list var/list/alltimers = list() //collect the timers currently in the bucket @@ -234,7 +162,7 @@ SUBSYSTEM_DEF(timer) head_offset = world.time bucket_resolution = world.tick_lag - alltimers += second_queue + alltimers += processing if (!length(alltimers)) return @@ -245,26 +173,22 @@ SUBSYSTEM_DEF(timer) if (head.timeToRun < head_offset) head_offset = head.timeToRun - var/new_bucket_count - var/i = 1 - for (i in 1 to length(alltimers)) - var/datum/timedevent/timer = alltimers[1] + var/list/timers_to_remove = list() + + for (var/thing in alltimers) + var/datum/timedevent/timer = thing if (!timer) + timers_to_remove += timer continue var/bucket_pos = BUCKET_POS(timer) - if (timer.timeToRun >= TIMER_MAX) - i-- + if (bucket_pos > BUCKET_LEN) break - + timers_to_remove += timer //remove it from the big list once we are done if (!timer.callBack || timer.spent) - WARNING("Invalid timer: [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]") - if (timer.callBack) - qdel(timer) continue - - new_bucket_count++ + bucket_count++ var/datum/timedevent/bucket_head = bucket_list[bucket_pos] if (!bucket_head) bucket_list[bucket_pos] = timer @@ -278,14 +202,12 @@ SUBSYSTEM_DEF(timer) timer.prev = bucket_head.prev timer.next.prev = timer timer.prev.next = timer - if (i) - alltimers.Cut(1, i+1) - second_queue = alltimers - bucket_count = new_bucket_count + + processing = (alltimers - timers_to_remove) /datum/controller/subsystem/timer/Recover() - second_queue |= SStimer.second_queue + processing |= SStimer.processing hashes |= SStimer.hashes timer_id_dict |= SStimer.timer_id_dict bucket_list |= SStimer.bucket_list @@ -302,6 +224,8 @@ SUBSYSTEM_DEF(timer) var/datum/timedevent/next var/datum/timedevent/prev + var/static/nextid = 1 + /datum/timedevent/New(datum/callback/callBack, timeToRun, flags, hash) id = TIMER_ID_NULL src.callBack = callBack @@ -311,65 +235,56 @@ SUBSYSTEM_DEF(timer) if (flags & TIMER_UNIQUE) SStimer.hashes[hash] = src - if (flags & TIMER_STOPPABLE) - id = GUID() - SStimer.timer_id_dict[id] = src + do + if (nextid >= TIMER_ID_MAX) + nextid = 1 + id = nextid++ + while(SStimer.timer_id_dict["timerid" + num2text(id, 8)]) + SStimer.timer_id_dict["timerid" + num2text(id, 8)] = src - name = "Timer: [id] (\ref[src]), TTR: [timeToRun], Flags: [jointext(bitfield2list(flags, list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT")), ", ")], callBack: \ref[callBack], callBack.object: [callBack.object]\ref[callBack.object]([getcallingtype()]), callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""])" + name = "Timer: " + num2text(id, 8) + ", TTR: [timeToRun], Flags: [jointext(bitfield2list(flags, list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT")), ", ")], callBack: [REF(callBack)], callBack.object: [callBack.object][REF(callBack.object)]([getcallingtype()]), callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""])" - if ((timeToRun < world.time || timeToRun < SStimer.head_offset) && !(flags & TIMER_CLIENT_TIME)) - CRASH("Invalid timer state: Timer created that would require a backtrack to run (addtimer would never let this happen): [SStimer.get_timer_debug_string(src)]") + if (spent) + CRASH("HOLY JESUS. WHAT IS THAT? WHAT THE FUCK IS THAT?") if (callBack.object != GLOBAL_PROC) LAZYADD(callBack.object.active_timers, src) - - var/list/L - if (flags & TIMER_CLIENT_TIME) - L = SStimer.clienttime_timers - else if (timeToRun >= TIMER_MAX) - L = SStimer.second_queue - - - if (L) - //binary search sorted insert - var/cttl = length(L) + //sorted insert + var/list/ctts = SStimer.clienttime_timers + var/cttl = length(ctts) if(cttl) - var/left = 1 - var/right = cttl - var/mid = (left+right) >> 1 //rounded divide by two for hedgehogs - - var/datum/timedevent/item - while (left < right) - item = L[mid] - if (item.timeToRun <= timeToRun) - left = mid+1 - else - right = mid - mid = (left+right) >> 1 - - item = L[mid] - mid = item.timeToRun > timeToRun ? mid : mid+1 - L.Insert(mid, src) - + var/datum/timedevent/Last = ctts[cttl] + if(Last.timeToRun >= timeToRun) + ctts += src + else + for(var/i in cttl to 1 step -1) + var/datum/timedevent/E = ctts[i] + if(E.timeToRun <= timeToRun) + ctts.Insert(i, src) + break else - L += src + ctts += src return //get the list of buckets var/list/bucket_list = SStimer.bucket_list - //calculate our place in the bucket list var/bucket_pos = BUCKET_POS(src) - + //we are too far aways from needing to run to be in the bucket list, shift_buckets() will handle us. + if (bucket_pos > length(bucket_list)) + SStimer.processing += src + return //get the bucket for our tick var/datum/timedevent/bucket_head = bucket_list[bucket_pos] SStimer.bucket_count++ //empty bucket, we will just add ourselves if (!bucket_head) bucket_list[bucket_pos] = src + if (bucket_pos < SStimer.practical_offset) + SStimer.practical_offset = bucket_pos return //other wise, lets do a simplified linked list add. if (!bucket_head.prev) @@ -381,9 +296,10 @@ SUBSYSTEM_DEF(timer) /datum/timedevent/Destroy() ..() - if (flags & TIMER_UNIQUE && hash) + if (flags & TIMER_UNIQUE) SStimer.hashes -= hash + if (callBack && callBack.object && callBack.object != GLOBAL_PROC && callBack.object.active_timers) callBack.object.active_timers -= src UNSETEMPTY(callBack.object.active_timers) @@ -391,33 +307,13 @@ SUBSYSTEM_DEF(timer) callBack = null if (flags & TIMER_STOPPABLE) - SStimer.timer_id_dict -= id + SStimer.timer_id_dict -= "timerid" + num2text(id, 8) if (flags & TIMER_CLIENT_TIME) - if (!spent) - spent = world.time - SStimer.clienttime_timers -= src + SStimer.clienttime_timers -= src return QDEL_HINT_IWILLGC if (!spent) - spent = world.time - var/bucketpos = BUCKET_POS(src) - var/datum/timedevent/buckethead - var/list/bucket_list = SStimer.bucket_list - if (bucketpos > 0) - buckethead = bucket_list[bucketpos] - - if (buckethead == src) - bucket_list[bucketpos] = next - SStimer.bucket_count-- - else if (timeToRun < TIMER_MAX || next || prev) - SStimer.bucket_count-- - else - var/l = length(SStimer.second_queue) - SStimer.second_queue -= src - if (l == length(SStimer.second_queue)) - SStimer.bucket_count-- - if (prev == next && next) next.prev = null prev.next = null @@ -426,6 +322,19 @@ SUBSYSTEM_DEF(timer) prev.next = next if (next) next.prev = prev + + var/bucketpos = BUCKET_POS(src) + var/datum/timedevent/buckethead + var/list/bucket_list = SStimer.bucket_list + + if (bucketpos > 0 && bucketpos <= length(bucket_list)) + buckethead = bucket_list[bucketpos] + SStimer.bucket_count-- + else + SStimer.processing -= src + + if (buckethead == src) + bucket_list[bucketpos] = next else if (prev && prev.next == src) prev.next = next @@ -442,16 +351,9 @@ SUBSYSTEM_DEF(timer) else . = "[callBack.object.type]" -/proc/addtimer(datum/callback/callback, wait = 0, flags = 0) +/proc/addtimer(datum/callback/callback, wait, flags) if (!callback) - CRASH("addtimer called without a callback") - - if (wait < 0) - stack_trace("Addtimer called with a negitive wait. Converting to 0") - - //alot of things add short timers on themselves in their destroy, we ignore those cases - if (wait >= 1 && callback && callback.object && callback.object != GLOBAL_PROC && QDELETED(callback.object)) - stack_trace("Add timer called with a callback assigned to a qdeleted object") + return wait = max(wait, 0) @@ -472,10 +374,11 @@ SUBSYSTEM_DEF(timer) var/datum/timedevent/hash_timer = SStimer.hashes[hash] if(hash_timer) if (hash_timer.spent) //it's pending deletion, pretend it doesn't exist. - hash_timer.hash = null //but keep it from accidentally deleting us + hash_timer.hash = null + SStimer.hashes -= hash else + if (flags & TIMER_OVERRIDE) - hash_timer.hash = null //no need having it delete it's hash if we are going to replace it qdel(hash_timer) else if (hash_timer.flags & TIMER_STOPPABLE) @@ -500,7 +403,7 @@ SUBSYSTEM_DEF(timer) qdel(id) return TRUE //id is string - var/datum/timedevent/timer = SStimer.timer_id_dict[id] + var/datum/timedevent/timer = SStimer.timer_id_dict["timerid[id]"] if (timer && !timer.spent) qdel(timer) return TRUE @@ -509,5 +412,3 @@ SUBSYSTEM_DEF(timer) #undef BUCKET_LEN #undef BUCKET_POS -#undef TIMER_MAX -#undef TIMER_ID_MAX \ No newline at end of file diff --git a/code/controllers/subsystem/title.dm b/code/controllers/subsystem/title.dm index a0bcb5feec..4f1dbc37c7 100644 --- a/code/controllers/subsystem/title.dm +++ b/code/controllers/subsystem/title.dm @@ -36,7 +36,7 @@ SUBSYSTEM_DEF(title) break file_path = "config/title_screens/images/[pick(title_screens)]" - + icon = new(fcopy_rsc(file_path)) if(splash_turf) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index acb873dd5b..37811c183f 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -206,7 +206,6 @@ SUBSYSTEM_DEF(vote) var/datum/action/vote/V = new if(question) V.name = "Vote: [question]" - C.player_details.player_actions += V V.Grant(C.mob) generated_actions += V return 1 @@ -300,7 +299,6 @@ SUBSYSTEM_DEF(vote) for(var/v in generated_actions) var/datum/action/vote/V = v if(!QDELETED(V)) - V.remove_from_client() V.Remove(V.owner) generated_actions = list() @@ -320,16 +318,7 @@ SUBSYSTEM_DEF(vote) /datum/action/vote/Trigger() if(owner) owner.vote() - remove_from_client() Remove(owner) /datum/action/vote/IsAvailable() return 1 - -/datum/action/vote/proc/remove_from_client() - if(owner.client) - owner.client.player_details.player_actions -= src - else if(owner.ckey) - var/datum/player_details/P = GLOB.player_details[owner.ckey] - if(P) - P.player_actions -= src \ No newline at end of file diff --git a/code/datums/action.dm b/code/datums/action.dm index f14945fa24..f941a00a54 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -170,15 +170,14 @@ ..(current_button) else if(target && current_button.appearance_cache != target.appearance) //replace with /ref comparison if this is not valid. var/obj/item/I = target + current_button.appearance_cache = I.appearance var/old_layer = I.layer var/old_plane = I.plane I.layer = FLOAT_LAYER //AAAH I.plane = FLOAT_PLANE //^ what that guy said - current_button.cut_overlays() - current_button.add_overlay(I) + current_button.overlays = list(I) I.layer = old_layer I.plane = old_plane - current_button.appearance_cache = I.appearance /datum/action/item_action/toggle_light name = "Toggle Light" diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index c12a08a792..8d86507271 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -373,9 +373,32 @@ ion = list() /datum/ai_laws/proc/show_laws(who) - var/list/printable_laws = get_law_list(include_zeroth = TRUE) - for(var/law in printable_laws) - to_chat(who,law) + + if (devillaws && devillaws.len) //Yes, devil laws go in FRONT of zeroth laws, as the devil must still obey it's ban/obligation. + for(var/i in devillaws) + to_chat(who, "666. [i]") + + if (zeroth) + to_chat(who, "0. [zeroth]") + + for (var/index = 1, index <= ion.len, index++) + var/law = ion[index] + var/num = ionnum() + to_chat(who, "[num]. [law]") + + var/number = 1 + for (var/index = 1, index <= inherent.len, index++) + var/law = inherent[index] + + if (length(law) > 0) + to_chat(who, "[number]. [law]") + number++ + + for (var/index = 1, index <= supplied.len, index++) + var/law = supplied[index] + if (length(law) > 0) + to_chat(who, "[number]. [law]") + number++ /datum/ai_laws/proc/clear_zeroth_law(force) //only removes zeroth from antag ai if force is 1 if(force) diff --git a/code/datums/antagonists/abductor.dm b/code/datums/antagonists/abductor.dm index 3b8935d9fa..8d13c48e7c 100644 --- a/code/datums/antagonists/abductor.dm +++ b/code/datums/antagonists/abductor.dm @@ -1,6 +1,5 @@ /datum/antagonist/abductor name = "Abductor" - roundend_category = "abductors" job_rank = ROLE_ABDUCTOR var/datum/objective_team/abductor_team/team var/sub_role @@ -71,65 +70,3 @@ var/mob/living/carbon/human/H = owner.current var/datum/species/abductor/A = H.dna.species A.scientist = TRUE - - -/datum/objective_team/abductor_team - member_name = "abductor" - var/team_number - var/list/datum/mind/abductees = list() - -/datum/objective_team/abductor_team/is_solo() - return FALSE - -/datum/objective_team/abductor_team/proc/add_objective(datum/objective/O) - O.team = src - O.update_explanation_text() - objectives += O - -/datum/objective_team/abductor_team/roundend_report() - var/list/result = list() - - var/won = TRUE - for(var/datum/objective/O in objectives) - if(!O.check_completion()) - won = FALSE - if(won) - result += "[name] team fulfilled its mission!" - else - result += "[name] team failed its mission." - - result += "The abductors of [name] were:" - for(var/datum/mind/abductor_mind in members) - result += printplayer(abductor_mind) - result += printobjectives(abductor_mind) - - return result.Join("
") - - -/datum/antagonist/abductee - name = "Abductee" - roundend_category = "abductees" - -/datum/antagonist/abductee/on_gain() - give_objective() - . = ..() - -/datum/antagonist/abductee/greet() - to_chat(owner, "Your mind snaps!") - to_chat(owner, "You can't remember how you got here...") - owner.announce_objectives() - -/datum/antagonist/abductee/proc/give_objective() - var/mob/living/carbon/human/H = owner.current - if(istype(H)) - H.gain_trauma_type(BRAIN_TRAUMA_MILD) - var/objtype = (prob(75) ? /datum/objective/abductee/random : pick(subtypesof(/datum/objective/abductee/) - /datum/objective/abductee/random)) - var/datum/objective/abductee/O = new objtype() - objectives += O - owner.objectives += objectives - -/datum/antagonist/abductee/apply_innate_effects(mob/living/mob_override) - SSticker.mode.update_abductor_icons_added(mob_override ? mob_override.mind : owner) - -/datum/antagonist/abductee/remove_innate_effects(mob/living/mob_override) - SSticker.mode.update_abductor_icons_removed(mob_override ? mob_override.mind : owner) \ No newline at end of file diff --git a/code/datums/antagonists/antag_datum.dm b/code/datums/antagonists/antag_datum.dm index 6b5a573eff..0a7b2aa22f 100644 --- a/code/datums/antagonists/antag_datum.dm +++ b/code/datums/antagonists/antag_datum.dm @@ -2,8 +2,6 @@ GLOBAL_LIST_EMPTY(antagonists) /datum/antagonist var/name = "Antagonist" - var/roundend_category = "other antagonists" //Section of roundend report, datums with same category will be displayed together, also default header for the section - var/show_in_roundend = TRUE //Set to false to hide the antagonists from roundend report var/datum/mind/owner //Mind that owns this datum var/silent = FALSE //Silent will prevent the gain/lose texts to show var/can_coexist_with_others = TRUE //Whether or not the person will be able to have more than one datum @@ -11,7 +9,6 @@ GLOBAL_LIST_EMPTY(antagonists) var/delete_on_mind_deletion = TRUE var/job_rank var/replace_banned = TRUE //Should replace jobbaned player with ghosts if granted. - var/list/objectives = list() /datum/antagonist/New(datum/mind/new_owner) GLOB.antagonists += src @@ -99,62 +96,9 @@ GLOBAL_LIST_EMPTY(antagonists) /datum/antagonist/proc/get_team() return -//Individual roundend report -/datum/antagonist/proc/roundend_report() - var/list/report = list() - - if(!owner) - CRASH("antagonist datum without owner") - - report += printplayer(owner) - - var/objectives_complete = TRUE - if(owner.objectives.len) - report += printobjectives(owner) - for(var/datum/objective/objective in owner.objectives) - if(!objective.check_completion()) - objectives_complete = FALSE - break - - if(owner.objectives.len == 0 || objectives_complete) - report += "The [name] was successful!" - else - report += "The [name] has failed!" - - return report.Join("
") - -//Displayed at the start of roundend_category section, default to roundend_category header -/datum/antagonist/proc/roundend_report_header() - return "The [roundend_category] were:
" - -//Displayed at the end of roundend_category section -/datum/antagonist/proc/roundend_report_footer() - return - //Should probably be on ticker or job ss ? /proc/get_antagonists(antag_type,specific = FALSE) . = list() for(var/datum/antagonist/A in GLOB.antagonists) if(!specific && istype(A,antag_type) || specific && A.type == antag_type) - . += A.owner - - - -//This datum will autofill the name with special_role -//Used as placeholder for minor antagonists, please create proper datums for these -/datum/antagonist/auto_custom - -/datum/antagonist/auto_custom/on_gain() - ..() - name = owner.special_role - //Add all objectives not already owned by other datums to this one. - var/list/already_registered_objectives = list() - for(var/datum/antagonist/A in owner.antag_datums) - if(A == src) - continue - else - already_registered_objectives |= A.objectives - objectives = owner.objectives - already_registered_objectives - -//This one is created by admin tools for custom objectives -/datum/antagonist/custom \ No newline at end of file + . += A.owner \ No newline at end of file diff --git a/code/datums/antagonists/blob.dm b/code/datums/antagonists/blob.dm deleted file mode 100644 index 5689e6a567..0000000000 --- a/code/datums/antagonists/blob.dm +++ /dev/null @@ -1,59 +0,0 @@ -/datum/antagonist/blob - name = "Blob" - roundend_category = "blobs" - job_rank = ROLE_BLOB - - var/datum/action/innate/blobpop/pop_action - var/starting_points_human_blob = 60 - var/point_rate_human_blob = 2 - -/datum/antagonist/blob/roundend_report() - var/basic_report = ..() - //Display max blobpoints for blebs that lost - if(isovermind(owner.current)) //embarrasing if not - var/mob/camera/blob/overmind = owner.current - if(!overmind.victory_in_progress) //if it won this doesn't really matter - var/point_report = "
[owner.name] took over [overmind.max_count] tiles at the height of its growth." - return basic_report+point_report - return basic_report - -/datum/antagonist/blob/greet() - if(!isovermind(owner.current)) - to_chat(owner,"You feel bloated.") - -/datum/antagonist/blob/on_gain() - create_objectives() - . = ..() - -/datum/antagonist/blob/proc/create_objectives() - var/datum/objective/blob_takeover/main = new - main.owner = owner - objectives += main - owner.objectives |= objectives - -/datum/antagonist/blob/apply_innate_effects(mob/living/mob_override) - if(!isovermind(owner.current)) - if(!pop_action) - pop_action = new - pop_action.Grant(owner.current) - -/datum/objective/blob_takeover - explanation_text = "Reach critical mass!" - -//Non-overminds get this on blob antag assignment -/datum/action/innate/blobpop - name = "Pop" - desc = "Unleash the blob" - icon_icon = 'icons/mob/blob.dmi' - button_icon_state = "blob" - -/datum/action/innate/blobpop/Activate() - var/mob/old_body = owner - var/datum/antagonist/blob/blobtag = owner.mind.has_antag_datum(/datum/antagonist/blob) - if(!blobtag) - Remove() - return - var/mob/camera/blob/B = new /mob/camera/blob(get_turf(old_body), blobtag.starting_points_human_blob) - owner.mind.transfer_to(B) - old_body.gib() - B.place_blob_core(blobtag.point_rate_human_blob, pop_override = TRUE) \ No newline at end of file diff --git a/code/datums/antagonists/brother.dm b/code/datums/antagonists/brother.dm index dd3bdef9d2..6458e6da09 100644 --- a/code/datums/antagonists/brother.dm +++ b/code/datums/antagonists/brother.dm @@ -55,71 +55,3 @@ /datum/antagonist/brother/proc/finalize_brother() SSticker.mode.update_brother_icons_added(owner) - - -/datum/objective_team/brother_team - name = "brotherhood" - member_name = "blood brother" - var/meeting_area - -/datum/objective_team/brother_team/is_solo() - return FALSE - -/datum/objective_team/brother_team/proc/update_name() - var/list/last_names = list() - for(var/datum/mind/M in members) - var/list/split_name = splittext(M.name," ") - last_names += split_name[split_name.len] - - name = last_names.Join(" & ") - -/datum/objective_team/brother_team/roundend_report() - var/list/parts = list() - - parts += "The blood brothers of [name] were:" - for(var/datum/mind/M in members) - parts += printplayer(M) - var/win = TRUE - var/objective_count = 1 - for(var/datum/objective/objective in objectives) - if(objective.check_completion()) - parts += "Objective #[objective_count]: [objective.explanation_text] Success!" - else - parts += "Objective #[objective_count]: [objective.explanation_text] Fail." - win = FALSE - objective_count++ - if(win) - parts += "The blood brothers were successful!" - else - parts += "The blood brothers have failed!" - - return "
[parts.Join("
")]
" - -/datum/objective_team/brother_team/proc/add_objective(datum/objective/O, needs_target = FALSE) - O.team = src - if(needs_target) - O.find_target() - O.update_explanation_text() - objectives += O - -/datum/objective_team/brother_team/proc/forge_brother_objectives() - objectives = list() - var/is_hijacker = prob(10) - for(var/i = 1 to max(1, CONFIG_GET(number/brother_objectives_amount) + (members.len > 2) - is_hijacker)) - forge_single_objective() - if(is_hijacker) - if(!locate(/datum/objective/hijack) in objectives) - add_objective(new/datum/objective/hijack) - else if(!locate(/datum/objective/escape) in objectives) - add_objective(new/datum/objective/escape) - -/datum/objective_team/brother_team/proc/forge_single_objective() - if(prob(50)) - if(LAZYLEN(active_ais()) && prob(100/GLOB.joined_player_list.len)) - add_objective(new/datum/objective/destroy, TRUE) - else if(prob(30)) - add_objective(new/datum/objective/maroon, TRUE) - else - add_objective(new/datum/objective/assassinate, TRUE) - else - add_objective(new/datum/objective/steal, TRUE) \ No newline at end of file diff --git a/code/datums/antagonists/changeling.dm b/code/datums/antagonists/changeling.dm index 83886a98ad..e98bfed782 100644 --- a/code/datums/antagonists/changeling.dm +++ b/code/datums/antagonists/changeling.dm @@ -4,11 +4,11 @@ /datum/antagonist/changeling name = "Changeling" - roundend_category = "changelings" job_rank = ROLE_CHANGELING var/you_are_greet = TRUE var/give_objectives = TRUE + var/list/objectives = list() var/team_mode = FALSE //Should assign team objectives ? //Changeling Stuff @@ -78,7 +78,7 @@ . = ..() /datum/antagonist/changeling/on_removal() - remove_changeling_powers() + remove_changeling_powers(FALSE) owner.objectives -= objectives . = ..() @@ -100,11 +100,11 @@ chem_recharge_slowdown = initial(chem_recharge_slowdown) mimicing = "" -/datum/antagonist/changeling/proc/remove_changeling_powers() +/datum/antagonist/changeling/proc/remove_changeling_powers(keep_free_powers=0) if(ishuman(owner.current) || ismonkey(owner.current)) reset_properties() for(var/obj/effect/proc_holder/changeling/p in purchasedpowers) - if(p.always_keep) + if((p.dna_cost == 0 && keep_free_powers) || p.always_keep) continue purchasedpowers -= p p.on_refund(owner.current) @@ -116,13 +116,13 @@ /datum/antagonist/changeling/proc/reset_powers() if(purchasedpowers) - remove_changeling_powers() - //Repurchase free powers. + remove_changeling_powers(TRUE) + //Purchase free powers. for(var/path in all_powers) var/obj/effect/proc_holder/changeling/S = new path() if(!S.dna_cost) if(!has_sting(S)) - purchasedpowers += S + purchasedpowers+=S S.on_purchase(owner.current,TRUE) /datum/antagonist/changeling/proc/has_sting(obj/effect/proc_holder/changeling/power) @@ -478,35 +478,4 @@ /datum/antagonist/changeling/xenobio name = "Xenobio Changeling" give_objectives = FALSE - show_in_roundend = FALSE //These are here for admin tracking purposes only you_are_greet = FALSE - -/datum/antagonist/changeling/roundend_report() - var/list/parts = list() - - var/changelingwin = 1 - if(!owner.current) - changelingwin = 0 - - parts += printplayer(owner) - - //Removed sanity if(changeling) because we -want- a runtime to inform us that the changelings list is incorrect and needs to be fixed. - parts += "Changeling ID: [changelingID]." - parts += "Genomes Extracted: [absorbedcount]" - parts += " " - if(objectives.len) - var/count = 1 - for(var/datum/objective/objective in objectives) - if(objective.check_completion()) - parts += "Objective #[count]: [objective.explanation_text] Success!
" - else - parts += "Objective #[count]: [objective.explanation_text] Fail." - changelingwin = 0 - count++ - - if(changelingwin) - parts += "The changeling was successful!" - else - parts += "The changeling has failed." - - return parts.Join("
") \ No newline at end of file diff --git a/code/datums/antagonists/clockcult.dm b/code/datums/antagonists/clockcult.dm index 5f99ccc5dd..8cc1c9e9a7 100644 --- a/code/datums/antagonists/clockcult.dm +++ b/code/datums/antagonists/clockcult.dm @@ -1,11 +1,8 @@ //CLOCKCULT PROOF OF CONCEPT /datum/antagonist/clockcult name = "Clock Cultist" - roundend_category = "clock cultists" - job_rank = ROLE_SERVANT_OF_RATVAR var/datum/action/innate/hierophant/hierophant_network = new() - var/datum/objective_team/clockcult/clock_team - var/make_team = TRUE //This should be only false for tutorial scarabs + job_rank = ROLE_SERVANT_OF_RATVAR /datum/antagonist/clockcult/silent silent = TRUE @@ -14,22 +11,6 @@ qdel(hierophant_network) return ..() -/datum/antagonist/clockcult/get_team() - return clock_team - -/datum/antagonist/clockcult/create_team(datum/objective_team/clockcult/new_team) - if(!new_team && make_team) - //TODO blah blah same as the others, allow multiple - for(var/datum/antagonist/clockcult/H in GLOB.antagonists) - if(H.clock_team) - clock_team = H.clock_team - return - clock_team = new /datum/objective_team/clockcult - return - if(make_team && !istype(new_team)) - stack_trace("Wrong team type passed to [type] initialization.") - clock_team = new_team - /datum/antagonist/clockcult/can_be_owned(datum/mind/new_owner) . = ..() if(.) @@ -183,35 +164,3 @@ if(iscyborg(owner.current)) to_chat(owner.current, "Despite your freedom from Ratvar's influence, you are still irreparably damaged and no longer possess certain functions such as AI linking.") . = ..() - - -/datum/objective_team/clockcult - name = "Clockcult" - var/list/objective - var/datum/mind/eminence - -/datum/objective_team/clockcult/proc/check_clockwork_victory() - if(GLOB.clockwork_gateway_activated) - return TRUE - return FALSE - -/datum/objective_team/clockcult/roundend_report() - var/list/parts = list() - - if(check_clockwork_victory()) - parts += "Ratvar's servants defended the Ark until its activation!" - else - parts += "The Ark was destroyed! Ratvar will rust away for all eternity!" - parts += " " - parts += "The servants' objective was: [CLOCKCULT_OBJECTIVE]." - parts += "Construction Value(CV) was: [GLOB.clockwork_construction_value]" - for(var/i in SSticker.scripture_states) - if(i != SCRIPTURE_DRIVER) - parts += "[i] scripture was: [SSticker.scripture_states[i] ? "UN":""]LOCKED" - if(eminence) - parts += "The Eminence was: [printplayer(eminence)]" - if(members.len) - parts += "Ratvar's servants were:" - parts += printplayerlist(members - eminence) - - return "
[parts.Join("
")]
" \ No newline at end of file diff --git a/code/datums/antagonists/cult.dm b/code/datums/antagonists/cult.dm index bce9123fb3..c26b0f8108 100644 --- a/code/datums/antagonists/cult.dm +++ b/code/datums/antagonists/cult.dm @@ -2,103 +2,84 @@ /datum/antagonist/cult name = "Cultist" - roundend_category = "cultists" var/datum/action/innate/cult/comm/communion = new var/datum/action/innate/cult/mastervote/vote = new job_rank = ROLE_CULTIST var/ignore_implant = FALSE - var/give_equipment = FALSE - - var/datum/objective_team/cult/cult_team - -/datum/antagonist/cult/get_team() - return cult_team - -/datum/antagonist/cult/create_team(datum/objective_team/cult/new_team) - if(!new_team) - //todo remove this and allow admin buttons to create more than one cult - for(var/datum/antagonist/cult/H in GLOB.antagonists) - if(H.cult_team) - cult_team = H.cult_team - return - cult_team = new /datum/objective_team/cult - cult_team.setup_objectives() - return - if(!istype(new_team)) - stack_trace("Wrong team type passed to [type] initialization.") - cult_team = new_team - -/datum/antagonist/cult/proc/add_objectives() - objectives |= cult_team.objectives - owner.objectives |= objectives - -/datum/antagonist/cult/proc/remove_objectives() - owner.objectives -= objectives /datum/antagonist/cult/Destroy() QDEL_NULL(communion) QDEL_NULL(vote) return ..() +/datum/antagonist/cult/proc/add_objectives() + var/list/target_candidates = list() + for(var/mob/living/carbon/human/player in GLOB.player_list) + if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && !is_convertable_to_cult(player) && (player != owner) && player.stat != DEAD) + target_candidates += player.mind + if(target_candidates.len == 0) + message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.") + for(var/mob/living/carbon/human/player in GLOB.player_list) + if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && (player != owner) && player.stat != DEAD) + target_candidates += player.mind + listclearnulls(target_candidates) + if(LAZYLEN(target_candidates)) + GLOB.sac_mind = pick(target_candidates) + if(!GLOB.sac_mind) + message_admins("Cult Sacrifice: ERROR - Null target chosen!") + else + var/datum/job/sacjob = SSjob.GetJob(GLOB.sac_mind.assigned_role) + var/datum/preferences/sacface = GLOB.sac_mind.current.client.prefs + var/icon/reshape = get_flat_human_icon(null, sacjob, sacface) + reshape.Shift(SOUTH, 4) + reshape.Shift(EAST, 1) + reshape.Crop(7,4,26,31) + reshape.Crop(-5,-3,26,30) + GLOB.sac_image = reshape + else + message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!") + GLOB.sac_complete = TRUE + SSticker.mode.cult_objectives += "sacrifice" + if(!GLOB.summon_spots.len) + while(GLOB.summon_spots.len < SUMMON_POSSIBILITIES) + var/area/summon = pick(GLOB.sortedAreas - GLOB.summon_spots) + if(summon && (summon.z in GLOB.station_z_levels) && summon.valid_territory) + GLOB.summon_spots += summon + SSticker.mode.cult_objectives += "eldergod" + +/datum/antagonist/cult/proc/cult_memorization(datum/mind/cult_mind) + var/mob/living/current = cult_mind.current + for(var/obj_count = 1,obj_count <= SSticker.mode.cult_objectives.len,obj_count++) + var/explanation + switch(SSticker.mode.cult_objectives[obj_count]) + if("sacrifice") + if(GLOB.sac_mind) + explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role] via invoking a Sacrifice rune with them on it and three acolytes around it." + else + explanation = "The veil has already been weakened here, proceed to the final objective." + GLOB.sac_complete = TRUE + if("eldergod") + explanation = "Summon Nar-Sie by invoking the rune 'Summon Nar-Sie'. The summoning can only be accomplished in [english_list(GLOB.summon_spots)] - where the veil is weak enough for the ritual to begin." + if(!silent) + to_chat(current, "Objective #[obj_count]: [explanation]") + cult_mind.memory += "Objective #[obj_count]: [explanation]
" + /datum/antagonist/cult/can_be_owned(datum/mind/new_owner) . = ..() if(. && !ignore_implant) - . = is_convertable_to_cult(new_owner.current,cult_team) - -/datum/antagonist/cult/greet() - to_chat(owner, "You are a member of the cult!") - owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/bloodcult.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change - owner.announce_objectives() + . = is_convertable_to_cult(new_owner.current) /datum/antagonist/cult/on_gain() . = ..() var/mob/living/current = owner.current - add_objectives() - if(give_equipment) - equip_cultist() + if(!LAZYLEN(SSticker.mode.cult_objectives)) + add_objectives() SSticker.mode.cult += owner // Only add after they've been given objectives + cult_memorization(owner) SSticker.mode.update_cult_icons_added(owner) current.log_message("Has been converted to the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG) - - if(cult_team.blood_target && cult_team.blood_target_image && current.client) - current.client.images += cult_team.blood_target_image - - -/datum/antagonist/cult/proc/equip_cultist(tome=FALSE) - var/mob/living/carbon/H = owner.current - if(!istype(H)) - return - if (owner.assigned_role == "Clown") - to_chat(owner, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") - H.dna.remove_mutation(CLOWNMUT) - - if(tome) - . += cult_give_item(/obj/item/tome, H) - else - . += cult_give_item(/obj/item/paper/talisman/supply, H) - to_chat(owner, "These will help you start the cult on this station. Use them well, and remember - you are not the only one.") - - -/datum/antagonist/cult/proc/cult_give_item(obj/item/item_path, mob/living/carbon/human/mob) - var/list/slots = list( - "backpack" = slot_in_backpack, - "left pocket" = slot_l_store, - "right pocket" = slot_r_store - ) - - var/T = new item_path(mob) - var/item_name = initial(item_path.name) - var/where = mob.equip_in_one_of_slots(T, slots) - if(!where) - to_chat(mob, "Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1).") - return 0 - else - to_chat(mob, "You have a [item_name] in your [where].") - if(where == "backpack") - var/obj/item/storage/B = mob.back - B.orient2hud(mob) - B.show_to(mob) - return 1 + if(GLOB.blood_target && GLOB.blood_target_image && current.client) + current.client.images += GLOB.blood_target_image /datum/antagonist/cult/apply_innate_effects(mob/living/mob_override) . = ..() @@ -108,7 +89,7 @@ current.faction |= "cult" current.grant_language(/datum/language/narsie) current.verbs += /mob/living/proc/cult_help - if(!cult_team.cult_mastered) + if(!GLOB.cult_mastered) vote.Grant(current) communion.Grant(current) current.throw_alert("bloodsense", /obj/screen/alert/bloodsense) @@ -126,7 +107,6 @@ current.clear_alert("bloodsense") /datum/antagonist/cult/on_removal() - remove_objectives() owner.wipe_memory() SSticker.mode.cult -= owner SSticker.mode.update_cult_icons_removed(owner) @@ -134,8 +114,8 @@ owner.current.visible_message("[owner.current] looks like [owner.current.p_they()] just reverted to their old faith!", ignored_mob = owner.current) to_chat(owner.current, "An unfamiliar white light flashes through your mind, cleansing the taint of the Geometer and all your memories as her servant.") owner.current.log_message("Has renounced the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG) - if(cult_team.blood_target && cult_team.blood_target_image && owner.current.client) - owner.current.client.images -= cult_team.blood_target_image + if(GLOB.blood_target && GLOB.blood_target_image && owner.current.client) + owner.current.client.images -= GLOB.blood_target_image . = ..() /datum/antagonist/cult/master @@ -165,7 +145,7 @@ var/mob/living/current = owner.current if(mob_override) current = mob_override - if(!cult_team.reckoning_complete) + if(!GLOB.reckoning_complete) reckoning.Grant(current) bloodmark.Grant(current) throwing.Grant(current) @@ -182,118 +162,3 @@ throwing.Remove(current) current.update_action_buttons_icon() current.remove_status_effect(/datum/status_effect/cult_master) - -/datum/objective_team/cult - name = "Cult" - - var/blood_target - var/image/blood_target_image - var/blood_target_reset_timer - - var/cult_vote_called = FALSE - var/cult_mastered = FALSE - var/reckoning_complete = FALSE - - -/datum/objective_team/cult/proc/setup_objectives() - //SAC OBJECTIVE , todo: move this to objective internals - var/list/target_candidates = list() - var/datum/objective/sacrifice/sac_objective = new - sac_objective.team = src - - for(var/mob/living/carbon/human/player in GLOB.player_list) - if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && !is_convertable_to_cult(player) && player.stat != DEAD) - target_candidates += player.mind - - if(target_candidates.len == 0) - message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.") - for(var/mob/living/carbon/human/player in GLOB.player_list) - if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && player.stat != DEAD) - target_candidates += player.mind - listclearnulls(target_candidates) - if(LAZYLEN(target_candidates)) - sac_objective.target = pick(target_candidates) - sac_objective.update_explanation_text() - - var/datum/job/sacjob = SSjob.GetJob(sac_objective.target.assigned_role) - var/datum/preferences/sacface = sac_objective.target.current.client.prefs - var/icon/reshape = get_flat_human_icon(null, sacjob, sacface) - reshape.Shift(SOUTH, 4) - reshape.Shift(EAST, 1) - reshape.Crop(7,4,26,31) - reshape.Crop(-5,-3,26,30) - sac_objective.sac_image = reshape - - objectives += sac_objective - else - message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!") - - - //SUMMON OBJECTIVE - - var/datum/objective/eldergod/summon_objective = new() - summon_objective.team = src - objectives += summon_objective - -/datum/objective/sacrifice - var/sacced = FALSE - var/sac_image - -/datum/objective/sacrifice/check_completion() - return sacced || completed - -/datum/objective/sacrifice/update_explanation_text() - if(target && !sacced) - explanation_text = "Sacrifice [target], the [target.assigned_role] via invoking a Sacrifice rune with them on it and three acolytes around it." - else - explanation_text = "The veil has already been weakened here, proceed to the final objective." - -/datum/objective/eldergod - var/summoned = FALSE - var/list/summon_spots = list() - -/datum/objective/eldergod/New() - ..() - var/sanity = 0 - while(summon_spots.len < SUMMON_POSSIBILITIES && sanity < 100) - var/area/summon = pick(GLOB.sortedAreas - summon_spots) - if(summon && (summon.z in GLOB.station_z_levels) && summon.valid_territory) - summon_spots += summon - sanity++ - update_explanation_text() - -/datum/objective/eldergod/update_explanation_text() - explanation_text = "Summon Nar-Sie by invoking the rune 'Summon Nar-Sie'. The summoning can only be accomplished in [english_list(summon_spots)] - where the veil is weak enough for the ritual to begin." - -/datum/objective/eldergod/check_completion() - return summoned || completed - -/datum/objective_team/cult/proc/check_cult_victory() - for(var/datum/objective/O in objectives) - if(!O.check_completion()) - return FALSE - return TRUE - -/datum/objective_team/cult/roundend_report() - var/list/parts = list() - - if(check_cult_victory()) - parts += "The cult has succeeded! Nar-sie has snuffed out another torch in the void!" - else - parts += "The staff managed to stop the cult! Dark words and heresy are no match for Nanotrasen's finest!" - - if(objectives.len) - parts += "The cultists' objectives were:" - var/count = 1 - for(var/datum/objective/objective in objectives) - if(objective.check_completion()) - parts += "Objective #[count]: [objective.explanation_text] Success!" - else - parts += "Objective #[count]: [objective.explanation_text] Fail." - count++ - - if(members.len) - parts += "The cultists were:" - parts += printplayerlist(members) - - return "
[parts.Join("
")]
" \ No newline at end of file diff --git a/code/datums/antagonists/datum_traitor.dm b/code/datums/antagonists/datum_traitor.dm index 80487f69e8..d386c79c25 100644 --- a/code/datums/antagonists/datum_traitor.dm +++ b/code/datums/antagonists/datum_traitor.dm @@ -1,6 +1,5 @@ /datum/antagonist/traitor name = "Traitor" - roundend_category = "traitors" job_rank = ROLE_TRAITOR var/should_specialise = FALSE //do we split into AI and human, set to true on inital assignment only var/ai_datum = ANTAG_DATUM_TRAITOR_AI @@ -9,6 +8,7 @@ var/employer = "The Syndicate" var/give_objectives = TRUE var/should_give_codewords = TRUE + var/list/objectives_given = list() /datum/antagonist/traitor/human var/should_equip = TRUE @@ -52,9 +52,9 @@ if(should_specialise) return ..()//we never did any of this anyway SSticker.mode.traitors -= owner - for(var/O in objectives) + for(var/O in objectives_given) owner.objectives -= O - objectives = list() + objectives_given = list() if(!silent && owner.current) to_chat(owner.current," You are no longer the [special_role]! ") owner.special_role = null @@ -71,11 +71,11 @@ /datum/antagonist/traitor/proc/add_objective(var/datum/objective/O) owner.objectives += O - objectives += O + objectives_given += O /datum/antagonist/traitor/proc/remove_objective(var/datum/objective/O) owner.objectives -= O - objectives -= O + objectives_given -= O /datum/antagonist/traitor/proc/forge_traitor_objectives() return @@ -127,7 +127,6 @@ if(prob(30)) objective_count += forge_single_objective() - for(var/i = objective_count, i < CONFIG_GET(number/traitor_objectives_amount), i++) var/datum/objective/assassinate/kill_objective = new kill_objective.owner = owner @@ -153,6 +152,11 @@ maroon_objective.owner = owner maroon_objective.find_target() add_objective(maroon_objective) + else if(prob(50)) + var/datum/objective/assassinate/late/late_objective = new + late_objective.owner = owner + late_objective.find_target() + add_objective(late_objective) else var/datum/objective/assassinate/kill_objective = new kill_objective.owner = owner @@ -290,53 +294,3 @@ where = "In your [equipped_slot]" to_chat(mob, "

[where] is a folder containing secret documents that another Syndicate group wants. We have set up a meeting with one of their agents on station to make an exchange. Exercise extreme caution as they cannot be trusted and may be hostile.
") -//TODO Collate -/datum/antagonist/traitor/roundend_report() - var/list/result = list() - - var/traitorwin = TRUE - - result += printplayer(owner) - - var/TC_uses = 0 - var/uplink_true = FALSE - var/purchases = "" - for(var/datum/component/uplink/H in GLOB.uplinks) - if(H.owner && H.owner == owner.key) - TC_uses += H.purchase_log.total_spent - uplink_true = TRUE - purchases += H.purchase_log.generate_render(FALSE) - - var/objectives_text = "" - if(objectives.len)//If the traitor had no objectives, don't need to process this. - var/count = 1 - for(var/datum/objective/objective in objectives) - if(objective.check_completion()) - objectives_text += "
Objective #[count]: [objective.explanation_text] Success!" - else - objectives_text += "
Objective #[count]: [objective.explanation_text] Fail." - traitorwin = FALSE - count++ - - if(uplink_true) - var/uplink_text = "(used [TC_uses] TC) [purchases]" - if(TC_uses==0 && traitorwin) - var/static/icon/badass = icon('icons/badass.dmi', "badass") - uplink_text += "[icon2html(badass, world)]" - result += uplink_text - - result += objectives_text - - var/special_role_text = lowertext(name) - - if(traitorwin) - result += "The [special_role_text] was successful!" - else - result += "The [special_role_text] has failed!" - SEND_SOUND(owner.current, 'sound/ambience/ambifailure.ogg') - - return result.Join("
") - -/datum/antagonist/traitor/roundend_report_footer() - return "
The code phrases were: [GLOB.syndicate_code_phrase]
\ - The code responses were: [GLOB.syndicate_code_response]
" \ No newline at end of file diff --git a/code/datums/antagonists/devil.dm b/code/datums/antagonists/devil.dm index 97e0d8c18a..416a8f3752 100644 --- a/code/datums/antagonists/devil.dm +++ b/code/datums/antagonists/devil.dm @@ -86,7 +86,6 @@ GLOBAL_LIST_INIT(devil_syllable, list("hal", "ve", "odr", "neit", "ci", "quon", GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", ", the Lord of all things", ", Jr.")) /datum/antagonist/devil name = "Devil" - roundend_category = "devils" job_rank = ROLE_DEVIL //Don't delete upon mind destruction, otherwise soul re-selling will break. delete_on_mind_deletion = FALSE @@ -509,35 +508,6 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", owner.RemoveSpell(S) .=..() -/datum/antagonist/devil/proc/printdevilinfo() - var/list/parts = list() - parts += "The devil's true name is: [truename]" - parts += "The devil's bans were:" - parts += "[GLOB.TAB][GLOB.lawlorify[LORE][ban]]" - parts += "[GLOB.TAB][GLOB.lawlorify[LORE][bane]]" - parts += "[GLOB.TAB][GLOB.lawlorify[LORE][obligation]]" - parts += "[GLOB.TAB][GLOB.lawlorify[LORE][banish]]" - return parts.Join("
") - -/datum/antagonist/devil/roundend_report() - var/list/parts = list() - parts += printplayer(owner) - parts += printdevilinfo() - parts += printobjectives(owner) - return parts.Join("
") - -/datum/antagonist/devil/roundend_report_footer() - //sintouched go here for now as a hack , TODO proper antag datum for these - var/list/parts = list() - if(SSticker.mode.sintouched.len) - parts += "The sintouched were:" - var/list/sintouchedUnique = uniqueList(SSticker.mode.sintouched) - for(var/S in sintouchedUnique) - var/datum/mind/sintouched_mind = S - parts += printplayer(sintouched_mind) - parts += printobjectives(sintouched_mind) - return parts.Join("
") - //A simple super light weight datum for the codex gigas. /datum/fakeDevil var/truename diff --git a/code/datums/antagonists/ninja.dm b/code/datums/antagonists/ninja.dm index 8201cd879d..ab4822dd79 100644 --- a/code/datums/antagonists/ninja.dm +++ b/code/datums/antagonists/ninja.dm @@ -37,20 +37,19 @@ else if(M.assigned_role in GLOB.command_positions) possible_targets[M] = 1 //good-guy - var/list/possible_objectives = list(1,2,3,4) - - while(objectives.len < quantity) - switch(pick_n_take(possible_objectives)) + var/list/objectives = list(1,2,3,4) + while(owner.objectives.len < quantity) + switch(pick_n_take(objectives)) if(1) //research var/datum/objective/download/O = new /datum/objective/download() O.owner = owner O.gen_amount_goal() - objectives += O + owner.objectives += O if(2) //steal var/datum/objective/steal/special/O = new /datum/objective/steal/special() O.owner = owner - objectives += O + owner.objectives += O if(3) //protect/kill if(!possible_targets.len) continue @@ -64,13 +63,13 @@ O.owner = owner O.target = M O.explanation_text = "Slay \the [M.current.real_name], the [M.assigned_role]." - objectives += O + owner.objectives += O else //protect var/datum/objective/protect/O = new /datum/objective/protect() O.owner = owner O.target = M O.explanation_text = "Protect \the [M.current.real_name], the [M.assigned_role], from harm." - objectives += O + owner.objectives += O if(4) //debrain/capture if(!possible_targets.len) continue var/selected = rand(1,possible_targets.len) @@ -83,17 +82,17 @@ O.owner = owner O.target = M O.explanation_text = "Steal the brain of [M.current.real_name]." - objectives += O + owner.objectives += O else //capture var/datum/objective/capture/O = new /datum/objective/capture() O.owner = owner O.gen_amount_goal() - objectives += O + owner.objectives += O else break var/datum/objective/O = new /datum/objective/survive() O.owner = owner - owner.objectives |= objectives + owner.objectives += O /proc/remove_ninja(mob/living/L) diff --git a/code/datums/antagonists/nukeop.dm b/code/datums/antagonists/nukeop.dm deleted file mode 100644 index 30d00ac3dd..0000000000 --- a/code/datums/antagonists/nukeop.dm +++ /dev/null @@ -1,322 +0,0 @@ -#define NUKE_RESULT_FLUKE 0 -#define NUKE_RESULT_NUKE_WIN 1 -#define NUKE_RESULT_CREW_WIN 2 -#define NUKE_RESULT_CREW_WIN_SYNDIES_DEAD 3 -#define NUKE_RESULT_DISK_LOST 4 -#define NUKE_RESULT_DISK_STOLEN 5 -#define NUKE_RESULT_NOSURVIVORS 6 -#define NUKE_RESULT_WRONG_STATION 7 -#define NUKE_RESULT_WRONG_STATION_DEAD 8 - -/datum/antagonist/nukeop - name = "Nuclear Operative" - roundend_category = "syndicate operatives" //just in case - job_rank = ROLE_OPERATIVE - var/datum/objective_team/nuclear/nuke_team - var/always_new_team = FALSE //If not assigned a team by default ops will try to join existing ones, set this to TRUE to always create new team. - var/send_to_spawnpoint = TRUE //Should the user be moved to default spawnpoint. - var/nukeop_outfit = /datum/outfit/syndicate - -/datum/antagonist/nukeop/proc/update_synd_icons_added(mob/living/M) - var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS] - opshud.join_hud(M) - set_antag_hud(M, "synd") - -/datum/antagonist/nukeop/proc/update_synd_icons_removed(mob/living/M) - var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS] - opshud.leave_hud(M) - set_antag_hud(M, null) - -/datum/antagonist/nukeop/apply_innate_effects(mob/living/mob_override) - var/mob/living/M = mob_override || owner.current - update_synd_icons_added(M) - -/datum/antagonist/nukeop/remove_innate_effects(mob/living/mob_override) - var/mob/living/M = mob_override || owner.current - update_synd_icons_removed(M) - -/datum/antagonist/nukeop/proc/equip_op() - if(!ishuman(owner.current)) - return - var/mob/living/carbon/human/H = owner.current - - H.set_species(/datum/species/human) //Plasamen burn up otherwise, and lizards are vulnerable to asimov AIs - - H.equipOutfit(nukeop_outfit) - return TRUE - -/datum/antagonist/nukeop/greet() - owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ops.ogg',100,0) - to_chat(owner, "You are a [nuke_team ? nuke_team.syndicate_name : "syndicate"] agent!") - owner.announce_objectives() - return - -/datum/antagonist/nukeop/on_gain() - give_alias() - forge_objectives() - . = ..() - equip_op() - memorize_code() - if(send_to_spawnpoint) - move_to_spawnpoint() - -/datum/antagonist/nukeop/get_team() - return nuke_team - -/datum/antagonist/nukeop/proc/assign_nuke() - if(nuke_team && !nuke_team.tracked_nuke) - nuke_team.memorized_code = random_nukecode() - var/obj/machinery/nuclearbomb/nuke = locate("syndienuke") in GLOB.nuke_list - if(nuke) - nuke_team.tracked_nuke = nuke - if(nuke.r_code == "ADMIN") - nuke.r_code = nuke_team.memorized_code - else //Already set by admins/something else? - nuke_team.memorized_code = nuke.r_code - else - stack_trace("Syndicate nuke not found during nuke team creation.") - nuke_team.memorized_code = null - -/datum/antagonist/nukeop/proc/give_alias() - if(nuke_team && nuke_team.syndicate_name) - var/number = 1 - number = nuke_team.members.Find(owner) - owner.current.real_name = "[nuke_team.syndicate_name] Operative #[number]" - -/datum/antagonist/nukeop/proc/memorize_code() - if(nuke_team && nuke_team.tracked_nuke && nuke_team.memorized_code) - owner.store_memory("[nuke_team.tracked_nuke] Code: [nuke_team.memorized_code]", 0, 0) - to_chat(owner, "The nuclear authorization code is: [nuke_team.memorized_code]") - else - to_chat(owner, "Unfortunately the syndicate was unable to provide you with nuclear authorization code.") - -/datum/antagonist/nukeop/proc/forge_objectives() - if(nuke_team) - owner.objectives |= nuke_team.objectives - -/datum/antagonist/nukeop/proc/move_to_spawnpoint() - var/team_number = 1 - if(nuke_team) - team_number = nuke_team.members.Find(owner) - owner.current.forceMove(GLOB.nukeop_start[((team_number - 1) % GLOB.nukeop_start.len) + 1]) - -/datum/antagonist/nukeop/leader/move_to_spawnpoint() - owner.current.forceMove(pick(GLOB.nukeop_leader_start)) - -/datum/antagonist/nukeop/create_team(datum/objective_team/nuclear/new_team) - if(!new_team) - if(!always_new_team) - for(var/datum/antagonist/nukeop/N in GLOB.antagonists) - if(N.nuke_team) - nuke_team = N.nuke_team - return - nuke_team = new /datum/objective_team/nuclear - nuke_team.update_objectives() - assign_nuke() //This is bit ugly - return - if(!istype(new_team)) - stack_trace("Wrong team type passed to [type] initialization.") - nuke_team = new_team - -/datum/antagonist/nukeop/leader - name = "Nuclear Operative Leader" - nukeop_outfit = /datum/outfit/syndicate/leader - always_new_team = TRUE - var/title - -/datum/antagonist/nukeop/leader/memorize_code() - ..() - if(nuke_team && nuke_team.memorized_code) - var/obj/item/paper/P = new - P.info = "The nuclear authorization code is: [nuke_team.memorized_code]" - P.name = "nuclear bomb code" - var/mob/living/carbon/human/H = owner.current - if(!istype(H)) - P.forceMove(get_turf(H)) - else - H.put_in_hands(P, TRUE) - H.update_icons() - -/datum/antagonist/nukeop/leader/give_alias() - title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord") - if(nuke_team && nuke_team.syndicate_name) - owner.current.real_name = "[nuke_team.syndicate_name] [title]" - else - owner.current.real_name = "Syndicate [title]" - -/datum/antagonist/nukeop/leader/greet() - owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ops.ogg',100,0) - to_chat(owner, "You are the Syndicate [title] for this mission. You are responsible for the distribution of telecrystals and your ID is the only one who can open the launch bay doors.") - to_chat(owner, "If you feel you are not up to this task, give your ID to another operative.") - to_chat(owner, "In your hand you will find a special item capable of triggering a greater challenge for your team. Examine it carefully and consult with your fellow operatives before activating it.") - owner.announce_objectives() - addtimer(CALLBACK(src, .proc/nuketeam_name_assign), 1) - - -/datum/antagonist/nukeop/leader/proc/nuketeam_name_assign() - if(!nuke_team) - return - nuke_team.rename_team(ask_name()) - -/datum/objective_team/nuclear/proc/rename_team(new_name) - syndicate_name = new_name - name = "[syndicate_name] Team" - for(var/I in members) - var/datum/mind/synd_mind = I - var/mob/living/carbon/human/H = synd_mind.current - if(!istype(H)) - continue - var/chosen_name = H.dna.species.random_name(H.gender,0,syndicate_name) - H.fully_replace_character_name(H.real_name,chosen_name) - -/datum/antagonist/nukeop/leader/proc/ask_name() - var/randomname = pick(GLOB.last_names) - var/newname = stripped_input(owner.current,"You are the nuke operative [title]. Please choose a last name for your family.", "Name change",randomname) - if (!newname) - newname = randomname - else - newname = reject_bad_name(newname) - if(!newname) - newname = randomname - - return capitalize(newname) - -/datum/antagonist/nukeop/lone - name = "Lone Operative" - always_new_team = TRUE - send_to_spawnpoint = FALSE //Handled by event - nukeop_outfit = /datum/outfit/syndicate/full - -/datum/antagonist/nukeop/lone/assign_nuke() - if(nuke_team && !nuke_team.tracked_nuke) - nuke_team.memorized_code = random_nukecode() - var/obj/machinery/nuclearbomb/selfdestruct/nuke = locate() in GLOB.nuke_list - if(nuke) - nuke_team.tracked_nuke = nuke - if(nuke.r_code == "ADMIN") - nuke.r_code = nuke_team.memorized_code - else //Already set by admins/something else? - nuke_team.memorized_code = nuke.r_code - else - stack_trace("Station self destruct ot found during lone op team creation.") - nuke_team.memorized_code = null - -/datum/objective_team/nuclear - var/syndicate_name - var/obj/machinery/nuclearbomb/tracked_nuke - var/core_objective = /datum/objective/nuclear - var/memorized_code - -/datum/objective_team/nuclear/New() - ..() - syndicate_name = syndicate_name() - -/datum/objective_team/nuclear/proc/update_objectives() - if(core_objective) - var/datum/objective/O = new core_objective - O.team = src - objectives += O - -/datum/objective_team/nuclear/proc/disk_rescued() - for(var/obj/item/disk/nuclear/D in GLOB.poi_list) - if(!D.onCentCom()) - return FALSE - return TRUE - -/datum/objective_team/nuclear/proc/operatives_dead() - for(var/I in members) - var/datum/mind/operative_mind = I - if(ishuman(operative_mind.current) && (operative_mind.current.stat != DEAD)) - return FALSE - return TRUE - -/datum/objective_team/nuclear/proc/syndies_escaped() - var/obj/docking_port/mobile/S = SSshuttle.getShuttle("syndicate") - return (S && (S.z == ZLEVEL_CENTCOM || S.z == ZLEVEL_TRANSIT)) - -/datum/objective_team/nuclear/proc/get_result() - var/evacuation = SSshuttle.emergency.mode == SHUTTLE_ENDGAME - var/disk_rescued = disk_rescued() - var/syndies_didnt_escape = !syndies_escaped() - var/station_was_nuked = SSticker.mode.station_was_nuked - var/nuke_off_station = SSticker.mode.nuke_off_station - - if(nuke_off_station == NUKE_SYNDICATE_BASE) - return NUKE_RESULT_FLUKE - else if(!disk_rescued && station_was_nuked && !syndies_didnt_escape) - return NUKE_RESULT_NUKE_WIN - else if (!disk_rescued && station_was_nuked && syndies_didnt_escape) - return NUKE_RESULT_NOSURVIVORS - else if (!disk_rescued && !station_was_nuked && nuke_off_station && !syndies_didnt_escape) - return NUKE_RESULT_WRONG_STATION - else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape) - return NUKE_RESULT_WRONG_STATION_DEAD - else if ((disk_rescued || evacuation) && operatives_dead()) - return NUKE_RESULT_CREW_WIN_SYNDIES_DEAD - else if (disk_rescued) - return NUKE_RESULT_CREW_WIN - else if (!disk_rescued && operatives_dead()) - return NUKE_RESULT_DISK_LOST - else if (!disk_rescued && evacuation) - return NUKE_RESULT_DISK_STOLEN - else - return //Undefined result - -/datum/objective_team/nuclear/roundend_report() - var/list/parts = list() - parts += "[syndicate_name] Operatives:" - - switch(get_result()) - if(NUKE_RESULT_FLUKE) - parts += "Humiliating Syndicate Defeat" - parts += "The crew of [station_name()] gave [syndicate_name] operatives back their bomb! The syndicate base was destroyed! Next time, don't lose the nuke!" - if(NUKE_RESULT_NUKE_WIN) - parts += "Syndicate Major Victory!" - parts += "[syndicate_name] operatives have destroyed [station_name()]!" - if(NUKE_RESULT_NOSURVIVORS) - parts += "Total Annihilation" - parts += "[syndicate_name] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion. Next time, don't lose the disk!" - if(NUKE_RESULT_WRONG_STATION) - parts += "Crew Minor Victory" - parts += "[syndicate_name] operatives secured the authentication disk but blew up something that wasn't [station_name()]. Next time, don't do that!" - if(NUKE_RESULT_WRONG_STATION_DEAD) - parts += "[syndicate_name] operatives have earned Darwin Award!" - parts += "[syndicate_name] operatives blew up something that wasn't [station_name()] and got caught in the explosion. Next time, don't do that!" - if(NUKE_RESULT_CREW_WIN_SYNDIES_DEAD) - parts += "Crew Major Victory!" - parts += "The Research Staff has saved the disk and killed the [syndicate_name] Operatives" - if(NUKE_RESULT_CREW_WIN) - parts += "Crew Major Victory" - parts += "The Research Staff has saved the disk and stopped the [syndicate_name] Operatives!" - if(NUKE_RESULT_DISK_LOST) - parts += "Neutral Victory!" - parts += "The Research Staff failed to secure the authentication disk but did manage to kill most of the [syndicate_name] Operatives!" - if(NUKE_RESULT_DISK_STOLEN) - parts += "Syndicate Minor Victory!" - parts += "[syndicate_name] operatives survived the assault but did not achieve the destruction of [station_name()]. Next time, don't lose the disk!" - else - parts += "Neutral Victory" - parts += "Mission aborted!" - - var/text = "
The syndicate operatives were:" - var/purchases = "" - var/TC_uses = 0 - for(var/I in members) - var/datum/mind/syndicate = I - for(var/U in GLOB.uplinks) - var/datum/component/uplink/H = U - if(H.owner == syndicate.key) - TC_uses += H.purchase_log.total_spent - if(H.purchase_log) - purchases += H.purchase_log.generate_render(show_key = FALSE) - else - stack_trace("WARNING: Nuke Op uplink with no purchase_log Owner: [H.owner]") - text += printplayerlist(members) - text += "
" - text += "(Syndicates used [TC_uses] TC) [purchases]" - if(TC_uses == 0 && SSticker.mode.station_was_nuked && !operatives_dead()) - text += "[icon2html('icons/badass.dmi', world, "badass")]" - - parts += text - - return "
[parts.Join("
")]
" diff --git a/code/datums/antagonists/pirate.dm b/code/datums/antagonists/pirate.dm index e0ce38c1e4..ad32e09151 100644 --- a/code/datums/antagonists/pirate.dm +++ b/code/datums/antagonists/pirate.dm @@ -1,7 +1,6 @@ /datum/antagonist/pirate name = "Space Pirate" job_rank = ROLE_TRAITOR - roundend_category = "space pirates" var/datum/objective_team/pirate/crew /datum/antagonist/pirate/greet() @@ -37,6 +36,7 @@ /datum/objective_team/pirate name = "Pirate crew" + var/list/objectives = list() /datum/objective_team/pirate/proc/forge_objectives() var/datum/objective/loot/getbooty = new() @@ -84,11 +84,11 @@ GLOBAL_LIST_INIT(pirate_loot_cache, typecacheof(list( loot_table[lootname] = count else loot_table[lootname] += count - var/list/loot_texts = list() + var/text = "" for(var/key in loot_table) var/amount = loot_table[key] - loot_texts += "[amount] [key][amount > 1 ? "s":""]" - return loot_texts.Join(", ") + text += "[amount] [key][amount > 1 ? "s":""], " + return text /datum/objective/loot/proc/get_loot_value() if(!storage_area) @@ -105,26 +105,31 @@ GLOBAL_LIST_INIT(pirate_loot_cache, typecacheof(list( return ..() || get_loot_value() >= target_value +//These need removal ASAP as everything is converted to datum antags. +/datum/game_mode/proc/auto_declare_completion_pirates() + var/list/datum/mind/pirates = get_antagonists(/datum/antagonist/pirate) + var/datum/objective_team/pirate/crew + var/text = "" + if(pirates.len) + text += "
Space Pirates were:" + for(var/datum/mind/M in pirates) + text += printplayer(M) + if(!crew) + var/datum/antagonist/pirate/P = M.has_antag_datum(/datum/antagonist/pirate) + crew = P.crew + if(crew) + text += "
Loot stolen: " + var/datum/objective/loot/L = locate() in crew.objectives + text += L.loot_listing() + text += "
Total loot value : [L.get_loot_value()]/[L.target_value] credits" -/datum/objective_team/pirate/roundend_report() - var/list/parts = list() - - parts += "Space Pirates were:" - - var/all_dead = TRUE - for(var/datum/mind/M in members) - if(considered_alive(M)) - all_dead = FALSE - parts += printplayerlist(members) - - parts += "Loot stolen: " - var/datum/objective/loot/L = locate() in objectives - parts += L.loot_listing() - parts += "Total loot value : [L.get_loot_value()]/[L.target_value] credits" - - if(L.check_completion() && !all_dead) - parts += "The pirate crew was successful!" - else - parts += "The pirate crew has failed." - - return parts.Join("
") \ No newline at end of file + var/all_dead = TRUE + for(var/datum/mind/M in crew.members) + if(considered_alive(M)) + all_dead = FALSE + break + if(L.check_completion() && !all_dead) + text += "
The pirate crew was successful!" + else + text += "
The pirate crew has failed." + to_chat(world, text) \ No newline at end of file diff --git a/code/datums/antagonists/revolution.dm b/code/datums/antagonists/revolution.dm index 14c6d1ab0e..9db86bdf08 100644 --- a/code/datums/antagonists/revolution.dm +++ b/code/datums/antagonists/revolution.dm @@ -3,7 +3,6 @@ /datum/antagonist/rev name = "Revolutionary" - roundend_category = "revolutionaries" // if by some miracle revolutionaries without revolution happen job_rank = ROLE_REV var/hud_type = "rev" var/datum/objective_team/revolution/rev_team @@ -185,6 +184,7 @@ /datum/objective_team/revolution name = "Revolution" + var/list/objectives = list() var/max_headrevs = 3 /datum/objective_team/revolution/proc/update_objectives(initial = FALSE) @@ -227,56 +227,3 @@ rev.promote() addtimer(CALLBACK(src,.proc/update_heads),HEAD_UPDATE_PERIOD,TIMER_UNIQUE) - - -/datum/objective_team/revolution/roundend_report() - if(!members.len) - return - - var/list/result = list() - - result += "
" - - var/num_revs = 0 - var/num_survivors = 0 - for(var/mob/living/carbon/survivor in GLOB.alive_mob_list) - if(survivor.ckey) - num_survivors++ - if(survivor.mind) - if(is_revolutionary(survivor)) - num_revs++ - if(num_survivors) - result += "Command's Approval Rating: [100 - round((num_revs/num_survivors)*100, 0.1)]%
" - - - var/list/targets = list() - var/list/datum/mind/headrevs = get_antagonists(/datum/antagonist/rev/head) - var/list/datum/mind/revs = get_antagonists(/datum/antagonist/rev,TRUE) - if(headrevs.len) - var/list/headrev_part = list() - headrev_part += "The head revolutionaries were:" - headrev_part += printplayerlist(headrevs,TRUE) - result += headrev_part.Join("
") - - if(revs.len) - var/list/rev_part = list() - rev_part += "The revolutionaries were:" - rev_part += printplayerlist(revs,TRUE) - result += rev_part.Join("
") - - var/list/heads = SSjob.get_all_heads() - if(heads.len) - var/head_text = "The heads of staff were:" - head_text += "
    " - for(var/datum/mind/head in heads) - var/target = (head in targets) - head_text += "
  • " - if(target) - head_text += "Target" - head_text += "[printplayer(head, 1)]
  • " - head_text += "

" - result += head_text - - result += "
" - - return result.Join() \ No newline at end of file diff --git a/code/datums/antagonists/wizard.dm b/code/datums/antagonists/wizard.dm index 7f23215d6c..e1e6dc09c8 100644 --- a/code/datums/antagonists/wizard.dm +++ b/code/datums/antagonists/wizard.dm @@ -5,13 +5,13 @@ /datum/antagonist/wizard name = "Space Wizard" - roundend_category = "wizards/witches" job_rank = ROLE_WIZARD var/give_objectives = TRUE var/strip = TRUE //strip before equipping var/allow_rename = TRUE var/hud_version = "wizard" var/datum/objective_team/wizard/wiz_team //Only created if wizard summons apprentices + var/list/objectives = list() //this should be base datum antag proc and list, todo make lazy var/move_to_lair = TRUE var/outfit_type = /datum/outfit/wizard var/wiz_age = WIZARD_AGE_MIN /* Wizards by nature cannot be too young. */ @@ -45,12 +45,10 @@ /datum/objective_team/wizard name = "wizard team" - var/datum/antagonist/wizard/master_wizard /datum/antagonist/wizard/proc/create_wiz_team() wiz_team = new(owner) wiz_team.name = "[owner.current.real_name] team" - wiz_team.master_wizard = src update_wiz_icons_added(owner.current) /datum/antagonist/wizard/proc/send_to_lair() @@ -285,46 +283,4 @@ var/datum/objective/new_objective = new("Protect Wizard Academy from the intruders") new_objective.owner = owner owner.objectives += new_objective - objectives += new_objective - -//Solo wizard report -/datum/antagonist/wizard/roundend_report() - var/list/parts = list() - - parts += printplayer(owner) - - var/count = 1 - var/wizardwin = 1 - for(var/datum/objective/objective in objectives) - if(objective.check_completion()) - parts += "Objective #[count]: [objective.explanation_text] Success!" - else - parts += "Objective #[count]: [objective.explanation_text] Fail." - wizardwin = 0 - count++ - - if(wizardwin) - parts += "The wizard was successful!" - else - parts += "The wizard has failed!" - - if(owner.spell_list.len>0) - parts += "[owner.name] used the following spells: " - var/list/spell_names = list() - for(var/obj/effect/proc_holder/spell/S in owner.spell_list) - spell_names += S.name - parts += spell_names.Join(", ") - - return parts.Join("
") - -//Wizard with apprentices report -/datum/objective_team/wizard/roundend_report() - var/list/parts = list() - - parts += "Wizards/witches of [master_wizard.owner.name] team were:" - parts += master_wizard.roundend_report() - parts += " " - parts += "[master_wizard.owner.name] apprentices were:" - parts += printplayerlist(members - master_wizard.owner) - - return "
[parts.Join("
")]
" \ No newline at end of file + objectives += new_objective \ No newline at end of file diff --git a/code/datums/components/spooky.dm b/code/datums/components/spooky.dm index a62b7dcaab..3f3b0341ee 100644 --- a/code/datums/components/spooky.dm +++ b/code/datums/components/spooky.dm @@ -57,4 +57,4 @@ var/t = stripped_input(H, "Enter your new skeleton name", H.real_name, null, MAX_NAME_LEN) if(!t) t = "spooky skeleton" - H.fully_replace_character_name(null, t) + H.fully_replace_character_name(H.real_name, t) diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index c22af19396..5f9cf3ad9a 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -1,4 +1,3 @@ - /datum/datacore var/medical[] = list() var/medicalPrintCount = 0 diff --git a/code/datums/datum.dm b/code/datums/datum.dm index 6a3ad57878..4c08b1000d 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -17,7 +17,6 @@ /datum/proc/Destroy(force=FALSE, ...) tag = null weak_reference = null //ensure prompt GCing of weakref. - var/list/timers = active_timers active_timers = null for(var/thing in timers) @@ -25,7 +24,6 @@ if (timer.spent) continue qdel(timer) - var/list/dc = datum_components if(dc) var/all_components = dc[/datum/component] @@ -37,11 +35,4 @@ var/datum/component/C = all_components qdel(C, FALSE, TRUE) dc.Cut() - - var/list/focusers = src.focusers - if(focusers) - for(var/i in 1 to focusers.len) - var/mob/M = focusers[i] - M.set_focus(M) - return QDEL_HINT_QUEUE diff --git a/code/datums/diseases/advance/presets.dm b/code/datums/diseases/advance/presets.dm index d2f6a73365..1a197f0f34 100644 --- a/code/datums/diseases/advance/presets.dm +++ b/code/datums/diseases/advance/presets.dm @@ -1,59 +1,59 @@ -// Cold - +// Cold + /datum/disease/advance/cold/New(var/process = TRUE, var/datum/disease/advance/D, var/copy = FALSE) - if(!D) - name = "Cold" - symptoms = list(new/datum/symptom/sneeze) - ..(process, D, copy) - - -// Flu - + if(!D) + name = "Cold" + symptoms = list(new/datum/symptom/sneeze) + ..(process, D, copy) + + +// Flu + /datum/disease/advance/flu/New(var/process = TRUE, var/datum/disease/advance/D, var/copy = FALSE) - if(!D) - name = "Flu" - symptoms = list(new/datum/symptom/cough) - ..(process, D, copy) - - -// Voice Changing - + if(!D) + name = "Flu" + symptoms = list(new/datum/symptom/cough) + ..(process, D, copy) + + +// Voice Changing + /datum/disease/advance/voice_change/New(var/process = TRUE, var/datum/disease/advance/D, var/copy = FALSE) - if(!D) - name = "Epiglottis Mutation" - symptoms = list(new/datum/symptom/voice_change) - ..(process, D, copy) - - -// Toxin Filter - + if(!D) + name = "Epiglottis Mutation" + symptoms = list(new/datum/symptom/voice_change) + ..(process, D, copy) + + +// Toxin Filter + /datum/disease/advance/heal/New(var/process = TRUE, var/datum/disease/advance/D, var/copy = FALSE) - if(!D) - name = "Liver Enhancer" - symptoms = list(new/datum/symptom/heal) - ..(process, D, copy) - - + if(!D) + name = "Liver Enhancer" + symptoms = list(new/datum/symptom/heal) + ..(process, D, copy) + + // Hallucigen - + /datum/disease/advance/hallucigen/New(var/process = TRUE, var/datum/disease/advance/D, var/copy = FALSE) - if(!D) + if(!D) name = "Second Sight" - symptoms = list(new/datum/symptom/hallucigen) - ..(process, D, copy) - -// Sensory Restoration - + symptoms = list(new/datum/symptom/hallucigen) + ..(process, D, copy) + +// Sensory Restoration + /datum/disease/advance/mind_restoration/New(var/process = TRUE, var/datum/disease/advance/D, var/copy = FALSE) - if(!D) + if(!D) name = "Intelligence Booster" symptoms = list(new/datum/symptom/mind_restoration) - ..(process, D, copy) - -// Sensory Destruction - + ..(process, D, copy) + +// Sensory Destruction + /datum/disease/advance/narcolepsy/New(var/process = TRUE, var/datum/disease/advance/D, var/copy = FALSE) - if(!D) + if(!D) name = "Experimental Insomnia Cure" symptoms = list(new/datum/symptom/narcolepsy) ..(process, D, copy) \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/beard.dm b/code/datums/diseases/advance/symptoms/beard.dm index c7a3ccec89..aa3919f3cf 100644 --- a/code/datums/diseases/advance/symptoms/beard.dm +++ b/code/datums/diseases/advance/symptoms/beard.dm @@ -1,33 +1,33 @@ -/* -////////////////////////////////////// -Facial Hypertrichosis - - Very very Noticable. - Decreases resistance slightly. - Decreases stage speed. - Reduced transmittability - Intense Level. - -BONUS - Makes the mob grow a massive beard, regardless of gender. - -////////////////////////////////////// -*/ - -/datum/symptom/beard - - name = "Facial Hypertrichosis" +/* +////////////////////////////////////// +Facial Hypertrichosis + + Very very Noticable. + Decreases resistance slightly. + Decreases stage speed. + Reduced transmittability + Intense Level. + +BONUS + Makes the mob grow a massive beard, regardless of gender. + +////////////////////////////////////// +*/ + +/datum/symptom/beard + + name = "Facial Hypertrichosis" desc = "The virus increases hair production significantly, causing rapid beard growth." - stealth = -3 - resistance = -1 - stage_speed = -3 - transmittable = -1 - level = 4 - severity = 1 + stealth = -3 + resistance = -1 + stage_speed = -3 + transmittable = -1 + level = 4 + severity = 1 symptom_delay_min = 18 symptom_delay_max = 36 - -/datum/symptom/beard/Activate(datum/disease/advance/A) + +/datum/symptom/beard/Activate(datum/disease/advance/A) if(!..()) return var/mob/living/M = A.affected_mob diff --git a/code/datums/diseases/advance/symptoms/confusion.dm b/code/datums/diseases/advance/symptoms/confusion.dm index 4ff69680ce..209c7b0bf6 100644 --- a/code/datums/diseases/advance/symptoms/confusion.dm +++ b/code/datums/diseases/advance/symptoms/confusion.dm @@ -1,30 +1,30 @@ -/* -////////////////////////////////////// - -Confusion - - Little bit hidden. - Lowers resistance. - Decreases stage speed. - Not very transmittable. - Intense Level. - -Bonus - Makes the affected mob be confused for short periods of time. - -////////////////////////////////////// -*/ - -/datum/symptom/confusion - - name = "Confusion" +/* +////////////////////////////////////// + +Confusion + + Little bit hidden. + Lowers resistance. + Decreases stage speed. + Not very transmittable. + Intense Level. + +Bonus + Makes the affected mob be confused for short periods of time. + +////////////////////////////////////// +*/ + +/datum/symptom/confusion + + name = "Confusion" desc = "The virus interferes with the proper function of the neural system, leading to bouts of confusion and erratic movement." - stealth = 1 - resistance = -1 - stage_speed = -3 - transmittable = 0 - level = 4 - severity = 2 + stealth = 1 + resistance = -1 + stage_speed = -3 + transmittable = 0 + level = 4 + severity = 2 base_message_chance = 25 symptom_delay_min = 10 symptom_delay_max = 30 @@ -32,7 +32,7 @@ Bonus threshold_desc = "Resistance 6: Causes brain damage over time.
\ Transmission 6: Increases confusion duration.
\ Stealth 4: The symptom remains hidden until active." - + /datum/symptom/confusion/Start(datum/disease/advance/A) if(!..()) return @@ -42,20 +42,20 @@ Bonus power = 1.5 if(A.properties["stealth"] >= 4) suppress_warning = TRUE - -/datum/symptom/confusion/Activate(datum/disease/advance/A) + +/datum/symptom/confusion/Activate(datum/disease/advance/A) if(!..()) return var/mob/living/carbon/M = A.affected_mob switch(A.stage) if(1, 2, 3, 4) if(prob(base_message_chance) && !suppress_warning) - to_chat(M, "[pick("Your head hurts.", "Your mind blanks for a moment.")]") + to_chat(M, "[pick("Your head hurts.", "Your mind blanks for a moment.")]") else to_chat(M, "You can't think straight!") M.confused = min(100 * power, M.confused + 8) if(brain_damage) M.adjustBrainLoss(3 * power, 80) M.updatehealth() - - return + + return diff --git a/code/datums/diseases/advance/symptoms/dizzy.dm b/code/datums/diseases/advance/symptoms/dizzy.dm index c7f7198f6b..bb83582425 100644 --- a/code/datums/diseases/advance/symptoms/dizzy.dm +++ b/code/datums/diseases/advance/symptoms/dizzy.dm @@ -50,4 +50,4 @@ Bonus to_chat(M, "A wave of dizziness washes over you!") M.Dizzy(5) if(power >= 2) - M.set_drugginess(5) \ No newline at end of file + M.set_drugginess(5) diff --git a/code/datums/diseases/advance/symptoms/flesh_eating.dm b/code/datums/diseases/advance/symptoms/flesh_eating.dm index c38acc8e9e..2d5d22a63a 100644 --- a/code/datums/diseases/advance/symptoms/flesh_eating.dm +++ b/code/datums/diseases/advance/symptoms/flesh_eating.dm @@ -127,4 +127,4 @@ Bonus M.reagents.add_reagent_list(list("heparin" = 2, "lipolicide" = 2)) if(zombie) M.reagents.add_reagent("romerol", 1) - return 1 \ No newline at end of file + return 1 diff --git a/code/datums/diseases/advance/symptoms/headache.dm b/code/datums/diseases/advance/symptoms/headache.dm index 973de1455b..3a8c82beed 100644 --- a/code/datums/diseases/advance/symptoms/headache.dm +++ b/code/datums/diseases/advance/symptoms/headache.dm @@ -57,4 +57,4 @@ BONUS M.adjustStaminaLoss(25) if(power >= 3 && A.stage >= 5) to_chat(M, "[pick("Your head hurts!", "You feel a burning knife inside your brain!", "A wave of pain fills your head!")]") - M.Stun(35) \ No newline at end of file + M.Stun(35) diff --git a/code/datums/diseases/advance/symptoms/itching.dm b/code/datums/diseases/advance/symptoms/itching.dm index 1da9f5e8d7..1c356247ee 100644 --- a/code/datums/diseases/advance/symptoms/itching.dm +++ b/code/datums/diseases/advance/symptoms/itching.dm @@ -51,4 +51,4 @@ BONUS var/can_scratch = scratch && !M.incapacitated() && get_location_accessible(M, picked_bodypart) M.visible_message("[can_scratch ? "[M] scratches [M.p_their()] [bodypart.name]." : ""]", "Your [bodypart.name] itches. [can_scratch ? " You scratch it." : ""]") if(can_scratch) - bodypart.receive_damage(0.5) \ No newline at end of file + bodypart.receive_damage(0.5) diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm index 3c66e76746..746844f7cb 100644 --- a/code/datums/diseases/advance/symptoms/sensory.dm +++ b/code/datums/diseases/advance/symptoms/sensory.dm @@ -75,4 +75,4 @@ Bonus if(prob(30) && C.has_trauma_type(BRAIN_TRAUMA_SPECIAL)) C.cure_trauma_type(BRAIN_TRAUMA_SPECIAL) if(prob(10) && C.has_trauma_type(BRAIN_TRAUMA_MILD)) - C.cure_trauma_type(BRAIN_TRAUMA_MILD) \ No newline at end of file + C.cure_trauma_type(BRAIN_TRAUMA_MILD) diff --git a/code/datums/diseases/advance/symptoms/shedding.dm b/code/datums/diseases/advance/symptoms/shedding.dm index c5bbb6bc7b..a578289e17 100644 --- a/code/datums/diseases/advance/symptoms/shedding.dm +++ b/code/datums/diseases/advance/symptoms/shedding.dm @@ -1,39 +1,39 @@ -/* -////////////////////////////////////// -Alopecia - +/* +////////////////////////////////////// +Alopecia + Not Noticeable. Increases resistance slightly. - Reduces stage speed slightly. - Transmittable. - Intense Level. - -BONUS - Makes the mob lose hair. - -////////////////////////////////////// -*/ - -/datum/symptom/shedding - name = "Alopecia" + Reduces stage speed slightly. + Transmittable. + Intense Level. + +BONUS + Makes the mob lose hair. + +////////////////////////////////////// +*/ + +/datum/symptom/shedding + name = "Alopecia" desc = "The virus causes rapid shedding of head and body hair." stealth = 0 resistance = 1 - stage_speed = -1 + stage_speed = -1 transmittable = 3 - level = 4 - severity = 1 + level = 4 + severity = 1 base_message_chance = 50 symptom_delay_min = 45 symptom_delay_max = 90 - -/datum/symptom/shedding/Activate(datum/disease/advance/A) + +/datum/symptom/shedding/Activate(datum/disease/advance/A) if(!..()) return var/mob/living/M = A.affected_mob if(prob(base_message_chance)) - to_chat(M, "[pick("Your scalp itches.", "Your skin feels flakey.")]") + to_chat(M, "[pick("Your scalp itches.", "Your skin feels flakey.")]") if(ishuman(M)) var/mob/living/carbon/human/H = M switch(A.stage) @@ -45,11 +45,11 @@ BONUS if(!(H.facial_hair_style == "Shaved") || !(H.hair_style == "Bald")) to_chat(H, "Your hair starts to fall out in clumps...") addtimer(CALLBACK(src, .proc/Shed, H, TRUE), 50) - -/datum/symptom/shedding/proc/Shed(mob/living/carbon/human/H, fullbald) - if(fullbald) - H.facial_hair_style = "Shaved" - H.hair_style = "Bald" - else - H.hair_style = "Balding Hair" + +/datum/symptom/shedding/proc/Shed(mob/living/carbon/human/H, fullbald) + if(fullbald) + H.facial_hair_style = "Shaved" + H.hair_style = "Bald" + else + H.hair_style = "Balding Hair" H.update_hair() \ No newline at end of file diff --git a/code/datums/diseases/advance/symptoms/shivering.dm b/code/datums/diseases/advance/symptoms/shivering.dm index 591626e530..bad9062eb5 100644 --- a/code/datums/diseases/advance/symptoms/shivering.dm +++ b/code/datums/diseases/advance/symptoms/shivering.dm @@ -56,4 +56,4 @@ Bonus M.bodytemperature = min(M.bodytemperature - (get_cold * A.stage), BODYTEMP_COLD_DAMAGE_LIMIT + 1) else M.bodytemperature -= (get_cold * A.stage) - return 1 \ No newline at end of file + return 1 diff --git a/code/datums/diseases/advance/symptoms/sneeze.dm b/code/datums/diseases/advance/symptoms/sneeze.dm index 3648f5d707..8b5b59f71a 100644 --- a/code/datums/diseases/advance/symptoms/sneeze.dm +++ b/code/datums/diseases/advance/symptoms/sneeze.dm @@ -46,6 +46,7 @@ Bonus if(1, 2, 3) if(!suppress_warning) M.emote("sniff") - else - M.emote("sneeze") - A.spread(4 + power) \ No newline at end of file + else + M.emote("sneeze") + A.spread(5) + return diff --git a/code/datums/diseases/advance/symptoms/weight.dm b/code/datums/diseases/advance/symptoms/weight.dm index c97667733d..7052e90bf7 100644 --- a/code/datums/diseases/advance/symptoms/weight.dm +++ b/code/datums/diseases/advance/symptoms/weight.dm @@ -48,4 +48,4 @@ Bonus else to_chat(M, "[pick("So hungry...", "You'd kill someone for a bite of food...", "Hunger cramps seize you...")]") M.overeatduration = max(M.overeatduration - 100, 0) - M.nutrition = max(M.nutrition - 100, 0) \ No newline at end of file + M.nutrition = max(M.nutrition - 100, 0) diff --git a/code/datums/diseases/advance/symptoms/youth.dm b/code/datums/diseases/advance/symptoms/youth.dm index 927be03ed9..6be34684e7 100644 --- a/code/datums/diseases/advance/symptoms/youth.dm +++ b/code/datums/diseases/advance/symptoms/youth.dm @@ -1,35 +1,35 @@ -/* -////////////////////////////////////// -Eternal Youth - - Moderate stealth boost. - Increases resistance tremendously. - Increases stage speed tremendously. - Reduces transmission tremendously. - Critical Level. - -BONUS - Gives you immortality and eternal youth!!! - Can be used to buff your virus - -////////////////////////////////////// -*/ - -/datum/symptom/youth - - name = "Eternal Youth" +/* +////////////////////////////////////// +Eternal Youth + + Moderate stealth boost. + Increases resistance tremendously. + Increases stage speed tremendously. + Reduces transmission tremendously. + Critical Level. + +BONUS + Gives you immortality and eternal youth!!! + Can be used to buff your virus + +////////////////////////////////////// +*/ + +/datum/symptom/youth + + name = "Eternal Youth" desc = "The virus becomes symbiotically connected to the cells in the host's body, preventing and reversing aging. \ The virus, in turn, becomes more resistant, spreads faster, and is harder to spot, although it doesn't thrive as well without a host." - stealth = 3 - resistance = 4 - stage_speed = 4 - transmittable = -4 - level = 5 + stealth = 3 + resistance = 4 + stage_speed = 4 + transmittable = -4 + level = 5 base_message_chance = 100 symptom_delay_min = 25 symptom_delay_max = 50 - -/datum/symptom/youth/Activate(datum/disease/advance/A) + +/datum/symptom/youth/Activate(datum/disease/advance/A) if(!..()) return var/mob/living/M = A.affected_mob diff --git a/code/datums/diseases/beesease.dm b/code/datums/diseases/beesease.dm index dc848ab622..80ec0abe6b 100644 --- a/code/datums/diseases/beesease.dm +++ b/code/datums/diseases/beesease.dm @@ -36,4 +36,4 @@ affected_mob.visible_message("[affected_mob] coughs up a swarm of bees!", \ "You cough up a swarm of bees!") new /mob/living/simple_animal/hostile/poison/bees(affected_mob.loc) - return \ No newline at end of file + return diff --git a/code/datums/diseases/cold.dm b/code/datums/diseases/cold.dm index e9f02b91b6..5915a784ea 100644 --- a/code/datums/diseases/cold.dm +++ b/code/datums/diseases/cold.dm @@ -50,4 +50,4 @@ if(!affected_mob.resistances.Find(/datum/disease/flu)) var/datum/disease/Flu = new /datum/disease/flu(0) affected_mob.ForceContractDisease(Flu) - cure() \ No newline at end of file + cure() diff --git a/code/datums/diseases/cold9.dm b/code/datums/diseases/cold9.dm index 6a21dbfd54..4b65fee700 100644 --- a/code/datums/diseases/cold9.dm +++ b/code/datums/diseases/cold9.dm @@ -36,4 +36,4 @@ if(prob(1)) to_chat(affected_mob, "Your throat feels sore.") if(prob(10)) - to_chat(affected_mob, "You feel stiff.") \ No newline at end of file + to_chat(affected_mob, "You feel stiff.") diff --git a/code/datums/diseases/gbs.dm b/code/datums/diseases/gbs.dm index 77385ebac3..71e4064676 100644 --- a/code/datums/diseases/gbs.dm +++ b/code/datums/diseases/gbs.dm @@ -38,4 +38,4 @@ if(prob(50)) affected_mob.gib() else - return \ No newline at end of file + return diff --git a/code/datums/diseases/magnitis.dm b/code/datums/diseases/magnitis.dm index 91ce1ca71e..4430eee19d 100644 --- a/code/datums/diseases/magnitis.dm +++ b/code/datums/diseases/magnitis.dm @@ -65,4 +65,4 @@ var/iter = rand(1,3) for(i=0,i" - if(((src in SSticker.mode.traitors) || is_nuclear_operative(current)) && ishuman(current)) + if(((src in SSticker.mode.traitors) || (src in SSticker.mode.syndicates)) && ishuman(current)) text = "Uplink: give" var/datum/component/uplink/U = find_syndicate_uplink() if(U) @@ -767,44 +769,17 @@ var/objective_pos var/def_value - - - var/datum/antagonist/target_antag - if (href_list["obj_edit"]) objective = locate(href_list["obj_edit"]) if (!objective) return - - for(var/datum/antagonist/A in antag_datums) - if(objective in A.objectives) - target_antag = A - objective_pos = A.objectives.Find(objective) - break - - if(!target_antag) //Shouldn't happen - stack_trace("objective without antagonist found") - objective_pos = objectives.Find(objective) + objective_pos = objectives.Find(objective) //Text strings are easy to manipulate. Revised for simplicity. var/temp_obj_type = "[objective.type]"//Convert path into a text string. def_value = copytext(temp_obj_type, 19)//Convert last part of path into an objective keyword. if(!def_value)//If it's a custom objective, it will be an empty string. def_value = "custom" - else - switch(antag_datums.len) - if(0) - target_antag = add_antag_datum(/datum/antagonist/custom) - if(1) - target_antag = antag_datums[1] - else - var/datum/antagonist/target = input("Which antagonist gets the objective:", "Antagonist", def_value) as null|anything in antag_datums + "(new custom antag)" - if (QDELETED(target)) - return - else if(target == "(new custom antag)") - target_antag = add_antag_datum(/datum/antagonist/custom) - else - target_antag = target var/new_obj_type = input("Select objective type:", "Objective type", def_value) as null|anything in list("assassinate", "late-assassinate", "maroon", "debrain", "protect", "destroy", "prevent", "hijack", "escape", "survive", "martyr", "steal", "download", "nuclear", "capture", "absorb", "custom") if (!new_obj_type) @@ -904,7 +879,7 @@ switch(new_obj_type) if("download") new_objective = new /datum/objective/download - new_objective.explanation_text = "Download [target_number] research node\s." + new_objective.explanation_text = "Download [target_number] research levels." if("capture") new_objective = new /datum/objective/capture new_objective.explanation_text = "Capture [target_number] lifeforms with an energy net. Live, rare specimens are worth more." @@ -926,15 +901,11 @@ return if (objective) - if(target_antag) - target_antag.objectives -= objective objectives -= objective - target_antag.objectives.Insert(objective_pos, new_objective) + objectives.Insert(objective_pos, new_objective) message_admins("[key_name_admin(usr)] edited [current]'s objective to [new_objective.explanation_text]") log_admin("[key_name(usr)] edited [current]'s objective to [new_objective.explanation_text]") else - if(target_antag) - target_antag.objectives += new_objective objectives += new_objective message_admins("[key_name_admin(usr)] added a new objective for [current]: [new_objective.explanation_text]") log_admin("[key_name(usr)] added a new objective for [current]: [new_objective.explanation_text]") @@ -943,11 +914,6 @@ var/datum/objective/objective = locate(href_list["obj_delete"]) if(!istype(objective)) return - - for(var/datum/antagonist/A in antag_datums) - if(objective in A.objectives) - A.objectives -= objective - break objectives -= objective message_admins("[key_name_admin(usr)] removed an objective for [current]: [objective.explanation_text]") log_admin("[key_name(usr)] removed an objective for [current]: [objective.explanation_text]") @@ -1030,13 +996,11 @@ message_admins("[key_name_admin(usr)] has cult'ed [current].") log_admin("[key_name(usr)] has cult'ed [current].") if("tome") - var/datum/antagonist/cult/C = has_antag_datum(/datum/antagonist/cult,TRUE) - if (C.equip_cultist(current,1)) + if (!SSticker.mode.equip_cultist(current,1)) to_chat(usr, "Spawning tome failed!") if("amulet") - var/datum/antagonist/cult/C = has_antag_datum(/datum/antagonist/cult,TRUE) - if (C.equip_cultist(current)) + if (!SSticker.mode.equip_cultist(current)) to_chat(usr, "Spawning amulet failed!") else if(href_list["clockcult"]) @@ -1107,14 +1071,36 @@ message_admins("[key_name_admin(usr)] has de-nuke op'ed [current].") log_admin("[key_name(usr)] has de-nuke op'ed [current].") if("nuclear") - if(!has_antag_datum(/datum/antagonist/nukeop,TRUE)) - add_antag_datum(/datum/antagonist/nukeop) + if(!(src in SSticker.mode.syndicates)) + SSticker.mode.syndicates += src + SSticker.mode.update_synd_icons_added(src) + if (SSticker.mode.syndicates.len==1) + SSticker.mode.prepare_syndicate_leader(src) + else + current.real_name = "[syndicate_name()] Operative #[SSticker.mode.syndicates.len-1]" special_role = "Syndicate" assigned_role = "Syndicate" + to_chat(current, "You are a [syndicate_name()] agent!") + SSticker.mode.forge_syndicate_objectives(src) + SSticker.mode.greet_syndicate(src) message_admins("[key_name_admin(usr)] has nuke op'ed [current].") log_admin("[key_name(usr)] has nuke op'ed [current].") if("lair") current.forceMove(pick(GLOB.nukeop_start)) + if("dressup") + var/mob/living/carbon/human/H = current + qdel(H.belt) + qdel(H.back) + qdel(H.ears) + qdel(H.gloves) + qdel(H.head) + qdel(H.shoes) + qdel(H.wear_id) + qdel(H.wear_suit) + qdel(H.w_uniform) + + if (!SSticker.mode.equip_syndicate(current)) + to_chat(usr, "Equipping a syndicate failed!") if("tellcode") var/code for (var/obj/machinery/nuclearbomb/bombue in GLOB.machines) @@ -1362,6 +1348,50 @@ T.should_specialise = TRUE add_antag_datum(T) + +/datum/mind/proc/make_Nuke(turf/spawnloc, nuke_code, leader=0, telecrystals = TRUE) + if(!(src in SSticker.mode.syndicates)) + SSticker.mode.syndicates += src + SSticker.mode.update_synd_icons_added(src) + assigned_role = "Syndicate" + special_role = "Syndicate" + SSticker.mode.forge_syndicate_objectives(src) + SSticker.mode.greet_syndicate(src) + current.faction |= "syndicate" + + if(spawnloc) + current.forceMove(spawnloc) + + if(ishuman(current)) + var/mob/living/carbon/human/H = current + qdel(H.belt) + qdel(H.back) + qdel(H.ears) + qdel(H.gloves) + qdel(H.head) + qdel(H.shoes) + qdel(H.wear_id) + qdel(H.wear_suit) + qdel(H.w_uniform) + + SSticker.mode.equip_syndicate(current, telecrystals) + + if (nuke_code) + store_memory("Syndicate Nuclear Bomb Code: [nuke_code]", 0, 0) + to_chat(current, "The nuclear authorization code is: [nuke_code]") + else + var/obj/machinery/nuclearbomb/nuke = locate("syndienuke") in GLOB.nuke_list + if(nuke) + store_memory("Syndicate Nuclear Bomb Code: [nuke.r_code]", 0, 0) + to_chat(current, "The nuclear authorization code is: nuke.r_code") + else + to_chat(current, "You were not provided with a nuclear code. Trying asking your team leader or contacting syndicate command.") + + if (leader) + SSticker.mode.prepare_syndicate_leader(src,nuke_code) + else + current.real_name = "[syndicate_name()] Operative #[SSticker.mode.syndicates.len-1]" + /datum/mind/proc/make_Changling() var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling) if(!C) @@ -1377,11 +1407,16 @@ /datum/mind/proc/make_Cultist() - if(!has_antag_datum(/datum/antagonist/cult,TRUE)) - SSticker.mode.add_cultist(src,FALSE,equip=TRUE) + if(!(src in SSticker.mode.cult)) + SSticker.mode.add_cultist(src,FALSE) special_role = "Cultist" to_chat(current, "You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy your world is, you see that it should be open to the knowledge of Nar-Sie.") to_chat(current, "Assist your new bretheren in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.") + var/datum/antagonist/cult/C + C.cult_memorization(src) + var/mob/living/carbon/human/H = current + if (!SSticker.mode.equip_cultist(current)) + to_chat(H, "Spawning an amulet from your Master failed.") /datum/mind/proc/make_Rev() var/datum/antagonist/rev/head/head = new(src) diff --git a/code/datums/weakrefs.dm b/code/datums/weakrefs.dm index d8adba652c..2347d0f831 100644 --- a/code/datums/weakrefs.dm +++ b/code/datums/weakrefs.dm @@ -16,4 +16,3 @@ /datum/weakref/proc/resolve() var/datum/D = locate(reference) return (!QDELETED(D) && D.weak_reference == src) ? D : null - diff --git a/code/datums/weather/weather_types/radiation_storm.dm b/code/datums/weather/weather_types/radiation_storm.dm index ab8f019d7c..995936e429 100644 --- a/code/datums/weather/weather_types/radiation_storm.dm +++ b/code/datums/weather/weather_types/radiation_storm.dm @@ -25,7 +25,7 @@ /datum/weather/rad_storm/telegraph() ..() - status_alarm(TRUE) + status_alarm("alert") /datum/weather/rad_storm/weather_act(mob/living/L) @@ -49,19 +49,24 @@ if(..()) return priority_announce("The radiation threat has passed. Please return to your workplaces.", "Anomaly Alert") - status_alarm(FALSE) + status_alarm() + sleep(300) + revoke_maint_all_access() // Need to make this a timer at some point. + +/datum/weather/rad_storm/proc/status_alarm(command) //Makes the status displays show the radiation warning for those who missed the announcement. + var/datum/radio_frequency/frequency = SSradio.return_frequency(1435) -/datum/weather/rad_storm/proc/status_alarm(active) //Makes the status displays show the radiation warning for those who missed the announcement. - var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS) if(!frequency) return - var/datum/signal/signal = new - if (active) - signal.data["command"] = "alert" - signal.data["picture_state"] = "radiation" - else - signal.data["command"] = "shuttle" + var/datum/signal/status_signal = new + var/atom/movable/virtualspeaker/virt = new /atom/movable/virtualspeaker(null) + status_signal.source = virt + status_signal.transmission_method = 1 + status_signal.data["command"] = "shuttle" - var/atom/movable/virtualspeaker/virt = new(null) - frequency.post_signal(virt, signal) + if(command == "alert") + status_signal.data["command"] = "alert" + status_signal.data["picture_state"] = "radiation" + + frequency.post_signal(src, status_signal) diff --git a/code/datums/wires/radio.dm b/code/datums/wires/radio.dm index 37d44a1bb0..b7b5e0d2c9 100644 --- a/code/datums/wires/radio.dm +++ b/code/datums/wires/radio.dm @@ -11,7 +11,8 @@ /datum/wires/radio/interactable(mob/user) var/obj/item/device/radio/R = holder - return R.unscrewed + if(R.b_stat) + return TRUE /datum/wires/radio/on_pulse(index) var/obj/item/device/radio/R = holder diff --git a/code/game/area/ai_monitored.dm b/code/game/area/ai_monitored.dm index 9d42b67bf9..a5216fb44c 100644 --- a/code/game/area/ai_monitored.dm +++ b/code/game/area/ai_monitored.dm @@ -28,4 +28,4 @@ for(var/X in motioncameras) var/obj/machinery/camera/cam = X cam.lostTargetRef(WEAKREF(O)) - return \ No newline at end of file + return diff --git a/code/game/area/areas/holodeck.dm b/code/game/area/areas/holodeck.dm index 10e3249d64..51399ca7e1 100644 --- a/code/game/area/areas/holodeck.dm +++ b/code/game/area/areas/holodeck.dm @@ -123,4 +123,4 @@ /area/holodeck/rec_center/thunderdome1218 name = "Holodeck - 1218 AD" - restricted = 1 + restricted = 1 \ No newline at end of file diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 7813783ada..3e0f0112ff 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -414,7 +414,7 @@ for(var/m in buckled_mobs) var/mob/living/buckled_mob = m if(!buckled_mob.Move(newloc, direct)) - forceMove(buckled_mob.loc) + loc = buckled_mob.loc last_move = buckled_mob.last_move inertia_dir = last_move buckled_mob.inertia_dir = last_move @@ -712,4 +712,4 @@ return FALSE if(anchored || throwing) return FALSE - return TRUE + return TRUE \ No newline at end of file diff --git a/code/game/communications.dm b/code/game/communications.dm index b7515cf452..d60a5d8301 100644 --- a/code/game/communications.dm +++ b/code/game/communications.dm @@ -86,55 +86,109 @@ GLOBAL_LIST_EMPTY(all_radios) for(var/freq in GLOB.all_radios) GLOB.all_radios["[freq]"] -= radio -// For information on what objects or departments use what frequencies, -// see __DEFINES/radio.dm. Mappers may also select additional frequencies for -// use in maps, such as in intercoms. +/* +Frequency range: 1200 to 1600 +Radiochat range: 1441 to 1489 (most devices refuse to be tune to other frequency, even during mapmaking) + +Radio: +1459 - standard radio chat +1351 - Science +1353 - Command +1355 - Medical +1357 - Engineering +1359 - Security +1337 - death squad +1443 - Confession Intercom +1349 - Miners +1347 - Cargo techs +1447 - AI Private + +Devices: +1451 - tracking implant +1457 - RSD default + +On the map: +1311 for prison shuttle console (in fact, it is not used) +1435 for status displays +1437 for atmospherics/fire alerts +1439 for engine components +1439 for air pumps, air scrubbers, atmo control +1441 for atmospherics - supply tanks +1443 for atmospherics - distribution loop/mixed air tank +1445 for bot nav beacons +1447 for mulebot, secbot and ed209 control +1449 for airlock controls, electropack, magnets +1451 for toxin lab access +1453 for engineering access +1455 for AI access +*/ GLOBAL_LIST_INIT(radiochannels, list( - "Common" = FREQ_COMMON, - "Science" = FREQ_SCIENCE, - "Command" = FREQ_COMMAND, - "Medical" = FREQ_MEDICAL, - "Engineering" = FREQ_ENGINEERING, - "Security" = FREQ_SECURITY, - "CentCom" = FREQ_CENTCOM, - "Syndicate" = FREQ_SYNDICATE, - "Supply" = FREQ_SUPPLY, - "Service" = FREQ_SERVICE, - "AI Private" = FREQ_AI_PRIVATE, - "Red Team" = FREQ_CTF_RED, - "Blue Team" = FREQ_CTF_BLUE + "Common" = 1459, + "Science" = 1351, + "Command" = 1353, + "Medical" = 1355, + "Engineering" = 1357, + "Security" = 1359, + "CentCom" = 1337, + "Syndicate" = 1213, + "Supply" = 1347, + "Service" = 1349, + "AI Private" = 1447, + "Red Team" = 1215, + "Blue Team" = 1217 )) GLOBAL_LIST_INIT(reverseradiochannels, list( - "[FREQ_COMMON]" = "Common", - "[FREQ_SCIENCE]" = "Science", - "[FREQ_COMMAND]" = "Command", - "[FREQ_MEDICAL]" = "Medical", - "[FREQ_ENGINEERING]" = "Engineering", - "[FREQ_SECURITY]" = "Security", - "[FREQ_CENTCOM]" = "CentCom", - "[FREQ_SYNDICATE]" = "Syndicate", - "[FREQ_SUPPLY]" = "Supply", - "[FREQ_SERVICE]" = "Service", - "[FREQ_AI_PRIVATE]" = "AI Private", - "[FREQ_CTF_RED]" = "Red Team", - "[FREQ_CTF_BLUE]" = "Blue Team" + "1459" = "Common", + "1351" = "Science", + "1353" = "Command", + "1355" = "Medical", + "1357" = "Engineering", + "1359" = "Security", + "1337" = "CentCom", + "1213" = "Syndicate", + "1347" = "Supply", + "1349" = "Service", + "1447" = "AI Private", + "1215" = "Red Team", + "1217" = "Blue Team" )) +//depenging helpers +GLOBAL_VAR_CONST(SYND_FREQ, 1213) //nuke op frequency, coloured dark brown in chat window +GLOBAL_VAR_CONST(SUPP_FREQ, 1347) //supply, coloured light brown in chat window +GLOBAL_VAR_CONST(SERV_FREQ, 1349) //service, coloured green in chat window +GLOBAL_VAR_CONST(SCI_FREQ, 1351) //science, coloured plum in chat window +GLOBAL_VAR_CONST(COMM_FREQ, 1353) //command, colored gold in chat window +GLOBAL_VAR_CONST(MED_FREQ, 1355) //medical, coloured blue in chat window +GLOBAL_VAR_CONST(ENG_FREQ, 1357) //engineering, coloured orange in chat window +GLOBAL_VAR_CONST(SEC_FREQ, 1359) //security, coloured red in chat window +GLOBAL_VAR_CONST(CENTCOM_FREQ, 1337) //centcom frequency, coloured grey in chat window +GLOBAL_VAR_CONST(AIPRIV_FREQ, 1447) //AI private, colored magenta in chat window +GLOBAL_VAR_CONST(REDTEAM_FREQ, 1215) // red team (CTF) frequency, coloured red +GLOBAL_VAR_CONST(BLUETEAM_FREQ, 1217) // blue team (CTF) frequency, coloured blue + +#define TRANSMISSION_WIRE 0 +#define TRANSMISSION_RADIO 1 + +/* filters */ +GLOBAL_VAR_INIT(RADIO_TO_AIRALARM, "1") +GLOBAL_VAR_INIT(RADIO_FROM_AIRALARM, "2") +GLOBAL_VAR_INIT(RADIO_CHAT, "3") //deprecated +GLOBAL_VAR_INIT(RADIO_ATMOSIA, "4") +GLOBAL_VAR_INIT(RADIO_NAVBEACONS, "5") +GLOBAL_VAR_INIT(RADIO_AIRLOCK, "6") +GLOBAL_VAR_INIT(RADIO_MAGNETS, "9") + /datum/radio_frequency + var/frequency as num var/list/list/obj/devices = list() -/datum/radio_frequency/New(freq) - frequency = freq - //If range > 0, only post to devices on the same z_level and within range //Use range = -1, to restrain to the same z_level without limiting range /datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, filter = null as text|null, range = null as num|null) - // Ensure the signal's data is fully filled - signal.source = source - signal.frequency = frequency //Apply filter to the signal. If none supply, broadcast to every devices //_default channel is always checked @@ -163,7 +217,7 @@ GLOBAL_LIST_INIT(reverseradiochannels, list( continue if(start_point.z != end_point.z || (range > 0 && get_dist(start_point, end_point) > range)) continue - device.receive_signal(signal) + device.receive_signal(signal, TRANSMISSION_RADIO, frequency) /datum/radio_frequency/proc/add_listener(obj/device, filter as text|null) if (!filter) @@ -171,7 +225,8 @@ GLOBAL_LIST_INIT(reverseradiochannels, list( var/list/devices_line = devices[filter] if(!devices_line) - devices[filter] = devices_line = list() + devices_line = list() + devices[filter] = devices_line devices_line += device @@ -185,15 +240,70 @@ GLOBAL_LIST_INIT(reverseradiochannels, list( devices -= devices_filter -/obj/proc/receive_signal(datum/signal/signal) + + + +/client/proc/print_pointers() + set name = "Debug Signals" + set category = "Debug" + + if(!holder) + return + + var/datum/signal/S + to_chat(src, "There are [S.pointers.len] pointers:") + for(var/p in S.pointers) + to_chat(src, p) + S = locate(p) + if(istype(S)) + to_chat(src, S.debug_print()) + +/obj/proc/receive_signal(datum/signal/signal, receive_method, receive_param) return /datum/signal var/obj/source - var/frequency = 0 - var/transmission_method - var/data -/datum/signal/New(data, transmission_method = TRANSMISSION_RADIO) - src.data = data || list() - src.transmission_method = transmission_method + var/transmission_method = 0 + //0 = wire + //1 = radio transmission + //2 = subspace transmission + + var/data = list() + var/encryption + + var/frequency = 0 + var/static/list/pointers = list() + +/datum/signal/New() + ..() + pointers += "[REF(src)]" + +/datum/signal/Destroy() + pointers -= "[REF(src)]" + return ..() + +/datum/signal/proc/copy_from(datum/signal/model) + source = model.source + transmission_method = model.transmission_method + data = model.data + encryption = model.encryption + frequency = model.frequency + +/datum/signal/proc/debug_print() + if (source) + . = "signal = {source = '[source]' [COORD(source)]\n" + else + . = "signal = {source = '[source]' ()\n" + for (var/i in data) + . += "data\[\"[i]\"\] = \"[data[i]]\"\n" + if(islist(data[i])) + var/list/L = data[i] + for(var/t in L) + . += "data\[\"[i]\"\] list has: [t]" + +/datum/signal/proc/sanitize_data() + for(var/d in data) + var/val = data[d] + if(istext(val)) + data[d] = html_encode(val) diff --git a/code/game/gamemodes/antag_hud.dm b/code/game/gamemodes/antag_hud.dm index 447a87ce20..b047ff92ea 100644 --- a/code/game/gamemodes/antag_hud.dm +++ b/code/game/gamemodes/antag_hud.dm @@ -48,6 +48,4 @@ newhud.join_hud(current) /datum/mind/proc/leave_all_antag_huds() - for(var/datum/atom_hud/antag/hud in GLOB.huds) - if(hud.hudusers[current]) - hud.leave_hud(current) \ No newline at end of file + for(var/datum/atom_hud/antag/hud in GLOB.huds) \ No newline at end of file diff --git a/code/game/gamemodes/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm index b6ddd5d8fd..3358052c7f 100644 --- a/code/game/gamemodes/antag_spawner.dm +++ b/code/game/gamemodes/antag_spawner.dm @@ -4,7 +4,7 @@ w_class = WEIGHT_CLASS_TINY var/used = 0 -/obj/item/antag_spawner/proc/spawn_antag(client/C, turf/T, kind = "", datum/mind/user) +/obj/item/antag_spawner/proc/spawn_antag(client/C, turf/T, type = "") return /obj/item/antag_spawner/proc/equip_antag(mob/target) @@ -67,16 +67,18 @@ else to_chat(H, "Unable to reach your apprentice! You can either attack the spellbook with the contract to refund your points, or wait and try again later.") -/obj/item/antag_spawner/contract/spawn_antag(client/C, turf/T, kind ,datum/mind/user) +/obj/item/antag_spawner/contract/spawn_antag(client/C, turf/T, school,datum/mind/user) new /obj/effect/particle_effect/smoke(T) var/mob/living/carbon/human/M = new/mob/living/carbon/human(T) C.prefs.copy_to(M) M.key = C.key var/datum/mind/app_mind = M.mind + + var/datum/antagonist/wizard/apprentice/app = new(app_mind) app.master = user - app.school = kind + app.school = school var/datum/antagonist/wizard/master_wizard = user.has_antag_datum(/datum/antagonist/wizard) if(master_wizard) @@ -105,7 +107,7 @@ if(used) to_chat(user, "[src] is out of power!") return FALSE - if(!user.mind.has_antag_datum(/datum/antagonist/nukeop,TRUE)) + if(!(user.mind in SSticker.mode.syndicates)) to_chat(user, "AUTHENTICATION FAILURE. ACCESS DENIED.") return FALSE if(user.z != ZLEVEL_CENTCOM) @@ -131,19 +133,19 @@ else to_chat(user, "Unable to connect to Syndicate command. Please wait and try again later or use the teleporter on your uplink to get your points refunded.") -/obj/item/antag_spawner/nuke_ops/spawn_antag(client/C, turf/T, kind, datum/mind/user) +/obj/item/antag_spawner/nuke_ops/spawn_antag(client/C, turf/T) var/mob/living/carbon/human/M = new/mob/living/carbon/human(T) C.prefs.copy_to(M) M.key = C.key - - var/datum/antagonist/nukeop/new_op = new(M.mind) - new_op.send_to_spawnpoint = FALSE - new_op.nukeop_outfit = /datum/outfit/syndicate/no_crystals - - var/datum/antagonist/nukeop/creator_op = user.has_antag_datum(/datum/antagonist/nukeop,TRUE) - if(creator_op) - M.mind.add_antag_datum(new_op,creator_op.nuke_team) - M.mind.special_role = "Nuclear Operative" + var/code = "BOMB-NOT-FOUND" + var/obj/machinery/nuclearbomb/nuke = locate("syndienuke") in GLOB.nuke_list + if(nuke) + code = nuke.r_code + M.mind.make_Nuke(null, code, 0, FALSE) + var/newname = M.dna.species.random_name(M.gender,0,SSticker.mode.nukeops_lastname) + M.mind.name = newname + M.real_name = newname + M.name = newname //////SYNDICATE BORG /obj/item/antag_spawner/nuke_ops/borg_tele @@ -160,12 +162,8 @@ name = "syndicate medical teleporter" borg_to_spawn = "Medical" -/obj/item/antag_spawner/nuke_ops/borg_tele/spawn_antag(client/C, turf/T, kind, datum/mind/user) +/obj/item/antag_spawner/nuke_ops/borg_tele/spawn_antag(client/C, turf/T) var/mob/living/silicon/robot/R - var/datum/antagonist/nukeop/creator_op = user.has_antag_datum(/datum/antagonist/nukeop,TRUE) - if(!creator_op) - return - switch(borg_to_spawn) if("Medical") R = new /mob/living/silicon/robot/modules/syndicate/medical(T) @@ -176,8 +174,8 @@ if(prob(50)) brainfirstname = pick(GLOB.first_names_female) var/brainopslastname = pick(GLOB.last_names) - if(creator_op.nuke_team.syndicate_name) //the brain inside the syndiborg has the same last name as the other ops. - brainopslastname = creator_op.nuke_team.syndicate_name + if(SSticker.mode.nukeops_lastname) //the brain inside the syndiborg has the same last name as the other ops. + brainopslastname = SSticker.mode.nukeops_lastname var/brainopsname = "[brainfirstname] [brainopslastname]" R.mmi.name = "Man-Machine Interface: [brainopsname]" @@ -187,11 +185,7 @@ R.real_name = R.name R.key = C.key - - var/datum/antagonist/nukeop/new_borg = new(R.mind) - new_borg.send_to_spawnpoint = FALSE - R.mind.add_antag_datum(new_borg,creator_op.nuke_team) - R.mind.special_role = "Syndicate Cyborg" + R.mind.make_Nuke(null, nuke_code = null,leader=0, telecrystals = TRUE) ///////////SLAUGHTER DEMON @@ -228,7 +222,8 @@ to_chat(user, "You can't seem to work up the nerve to shatter the bottle. Perhaps you should try again later.") -/obj/item/antag_spawner/slaughter_demon/spawn_antag(client/C, turf/T, kind = "", datum/mind/user) +/obj/item/antag_spawner/slaughter_demon/spawn_antag(client/C, turf/T, type = "", datum/mind/user) + var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(T) var/mob/living/simple_animal/slaughter/S = new demon_type(holder) S.holder = holder @@ -247,7 +242,6 @@ new_objective2.owner = S.mind new_objective2.explanation_text = "[objective_verb] everyone[user ? " else while you're at it":""]." S.mind.objectives += new_objective2 - S.mind.add_antag_datum(/datum/antagonist/auto_custom) to_chat(S, S.playstyle_string) to_chat(S, "You are currently not currently in the same plane of existence as the station. \ Ctrl+Click a blood pool to manifest.") diff --git a/code/game/gamemodes/blob/blobs/shield.dm b/code/game/gamemodes/blob/blobs/shield.dm index 551ec5d418..fedc2eb6ab 100644 --- a/code/game/gamemodes/blob/blobs/shield.dm +++ b/code/game/gamemodes/blob/blobs/shield.dm @@ -30,4 +30,4 @@ name = initial(name) desc = initial(desc) atmosblock = TRUE - air_update_turf(1) + air_update_turf(1) \ No newline at end of file diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm index 61c0365d30..4f26563da1 100644 --- a/code/game/gamemodes/blob/overmind.dm +++ b/code/game/gamemodes/blob/overmind.dm @@ -4,7 +4,6 @@ GLOBAL_LIST_EMPTY(blob_cores) GLOBAL_LIST_EMPTY(overminds) GLOBAL_LIST_EMPTY(blob_nodes) - /mob/camera/blob name = "Blob Overmind" real_name = "Blob Overmind" @@ -34,12 +33,10 @@ GLOBAL_LIST_EMPTY(blob_nodes) var/manualplace_min_time = 600 //in deciseconds //a minute, to get bearings var/autoplace_max_time = 3600 //six minutes, as long as should be needed var/list/blobs_legit = list() - var/max_count = 0 //The biggest it got before death var/blobwincount = 400 var/victory_in_progress = FALSE /mob/camera/blob/Initialize(mapload, starting_points = 60) - validate_location() blob_points = starting_points manualplace_min_time += world.time autoplace_max_time += world.time @@ -53,17 +50,10 @@ GLOBAL_LIST_EMPTY(blob_nodes) color = blob_reagent_datum.complementary_color if(blob_core) blob_core.update_icon() - SSshuttle.registerHostileEnvironment(src) - .= ..() -/mob/camera/blob/proc/validate_location() - var/turf/T = get_turf(src) - var/area/A = get_area(T) - if(((A && !A.blob_allowed) || !T || !(T.z in GLOB.station_z_levels)) && LAZYLEN(GLOB.blobstart)) - T = get_turf(pick(GLOB.blobstart)) - if(!T) - CRASH("No blobspawnpoints and blob spawned in nullspace.") - forceMove(T) + SSshuttle.registerHostileEnvironment(src) + + .= ..() /mob/camera/blob/Life() if(!blob_core) @@ -83,9 +73,6 @@ GLOBAL_LIST_EMPTY(blob_nodes) max_blob_points = INFINITY blob_points = INFINITY addtimer(CALLBACK(src, .proc/victory), 450) - - if(!victory_in_progress && max_count < blobs_legit.len) - max_count = blobs_legit.len ..() @@ -124,11 +111,6 @@ GLOBAL_LIST_EMPTY(blob_nodes) A.layer = BELOW_MOB_LAYER A.invisibility = 0 A.blend_mode = 0 - var/datum/antagonist/blob/B = mind.has_antag_datum(/datum/antagonist/blob) - if(B) - var/datum/objective/blob_takeover/main_objective = locate() in B.objectives - if(main_objective) - main_objective.completed = TRUE to_chat(world, "[real_name] consumed the station in an unstoppable tide!") SSticker.news_report = BLOB_WIN SSticker.force_ending = 1 @@ -152,6 +134,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) /mob/camera/blob/Login() ..() + sync_mind() to_chat(src, "You are the overmind!") blob_help() update_health_hud() @@ -232,18 +215,12 @@ GLOBAL_LIST_EMPTY(blob_nodes) if(placed) var/obj/structure/blob/B = locate() in range("3x3", NewLoc) if(B) - forceMove(NewLoc) + loc = NewLoc else return 0 else var/area/A = get_area(NewLoc) if(isspaceturf(NewLoc) || istype(A, /area/shuttle)) //if unplaced, can't go on shuttles or space tiles return 0 - forceMove(NewLoc) + loc = NewLoc return 1 - -/mob/camera/blob/mind_initialize() - . = ..() - var/datum/antagonist/blob/B = mind.has_antag_datum(/datum/antagonist/blob) - if(!B) - mind.add_antag_datum(/datum/antagonist/blob) \ No newline at end of file diff --git a/code/game/gamemodes/blob/powers.dm b/code/game/gamemodes/blob/powers.dm index e88cc8fb96..aa1a3e7046 100644 --- a/code/game/gamemodes/blob/powers.dm +++ b/code/game/gamemodes/blob/powers.dm @@ -7,23 +7,22 @@ // Power verbs -/mob/camera/blob/proc/place_blob_core(point_rate, placement_override , pop_override = FALSE) +/mob/camera/blob/proc/place_blob_core(point_rate, placement_override) if(placed && placement_override != -1) return 1 if(!placement_override) - if(!pop_override) - for(var/mob/living/M in range(7, src)) - if("blob" in M.faction) - continue - if(M.client) - to_chat(src, "There is someone too close to place your blob core!") - return 0 - for(var/mob/living/M in view(13, src)) - if("blob" in M.faction) - continue - if(M.client) - to_chat(src, "Someone could see your blob core from here!") - return 0 + for(var/mob/living/M in range(7, src)) + if("blob" in M.faction) + continue + if(M.client) + to_chat(src, "There is someone too close to place your blob core!") + return 0 + for(var/mob/living/M in view(13, src)) + if("blob" in M.faction) + continue + if(M.client) + to_chat(src, "Someone could see your blob core from here!") + return 0 var/turf/T = get_turf(src) if(T.density) to_chat(src, "This spot is too dense to place a blob core on!") @@ -38,12 +37,12 @@ else if(O.density) to_chat(src, "This spot is too dense to place a blob core on!") return 0 - if(!pop_override && world.time <= manualplace_min_time && world.time <= autoplace_max_time) + if(world.time <= manualplace_min_time && world.time <= autoplace_max_time) to_chat(src, "It is too early to place your blob core!") return 0 else if(placement_override == 1) var/turf/T = pick(GLOB.blobstart) - forceMove(T) //got overrided? you're somewhere random, motherfucker + loc = T //got overrided? you're somewhere random, motherfucker if(placed && blob_core) blob_core.forceMove(loc) else @@ -75,7 +74,7 @@ var/node_name = input(src, "Choose a node to jump to.", "Node Jump") in nodes var/obj/structure/blob/node/chosen_node = nodes[node_name] if(chosen_node) - forceMove(chosen_node.loc) + loc = chosen_node.loc /mob/camera/blob/proc/createSpecial(price, blobType, nearEquals, needsNode, turf/T) if(!T) diff --git a/code/game/gamemodes/blob/theblob.dm b/code/game/gamemodes/blob/theblob.dm index b9a8ee6046..0c642692f0 100644 --- a/code/game/gamemodes/blob/theblob.dm +++ b/code/game/gamemodes/blob/theblob.dm @@ -348,4 +348,4 @@ icon_state = "blob" name = "blob" desc = "A thick wall of writhing tendrils." - brute_resist = 0.25 + brute_resist = 0.25 \ No newline at end of file diff --git a/code/game/gamemodes/brother/traitor_bro.dm b/code/game/gamemodes/brother/traitor_bro.dm index 978f871ba2..c1af1601ce 100644 --- a/code/game/gamemodes/brother/traitor_bro.dm +++ b/code/game/gamemodes/brother/traitor_bro.dm @@ -1,3 +1,41 @@ +/datum/objective_team/brother_team + name = "brotherhood" + member_name = "blood brother" + var/list/objectives = list() + var/meeting_area + +/datum/objective_team/brother_team/is_solo() + return FALSE + +/datum/objective_team/brother_team/proc/add_objective(datum/objective/O, needs_target = FALSE) + O.team = src + if(needs_target) + O.find_target() + O.update_explanation_text() + objectives += O + +/datum/objective_team/brother_team/proc/forge_brother_objectives() + objectives = list() + var/is_hijacker = prob(10) + for(var/i = 1 to max(1, CONFIG_GET(number/brother_objectives_amount) + (members.len > 2) - is_hijacker)) + forge_single_objective() + if(is_hijacker) + if(!locate(/datum/objective/hijack) in objectives) + add_objective(new/datum/objective/hijack) + else if(!locate(/datum/objective/escape) in objectives) + add_objective(new/datum/objective/escape) + +/datum/objective_team/brother_team/proc/forge_single_objective() + if(prob(50)) + if(LAZYLEN(active_ais()) && prob(100/GLOB.joined_player_list.len)) + add_objective(new/datum/objective/destroy, TRUE) + else if(prob(30)) + add_objective(new/datum/objective/maroon, TRUE) + else + add_objective(new/datum/objective/assassinate, TRUE) + else + add_objective(new/datum/objective/steal, TRUE) + /datum/game_mode var/list/datum/mind/brothers = list() var/list/datum/objective_team/brother_team/brother_teams = list() @@ -16,7 +54,6 @@ var/list/datum/objective_team/brother_team/pre_brother_teams = list() var/const/team_amount = 2 //hard limit on brother teams if scaling is turned off var/const/min_team_size = 2 - traitors_required = FALSE //Only teams are possible var/meeting_areas = list("The Bar", "Dorms", "Escape Dock", "Arrivals", "Holodeck", "Primary Tool Storage", "Recreation Area", "Chapel", "Library") @@ -55,13 +92,44 @@ team.forge_brother_objectives() for(var/datum/mind/M in team.members) M.add_antag_datum(ANTAG_DATUM_BROTHER, team) - team.update_name() brother_teams += pre_brother_teams return ..() /datum/game_mode/traitor/bros/generate_report() return "It's Syndicate recruiting season. Be alert for potential Syndicate infiltrators, but also watch out for disgruntled employees trying to defect. Unlike Nanotrasen, the Syndicate prides itself in teamwork and will only recruit pairs that share a brotherly trust." +/datum/game_mode/proc/auto_declare_completion_brother() + if(!LAZYLEN(brother_teams)) + return + var/text = "
The blood brothers were:" + var/teamnumber = 1 + for(var/datum/objective_team/brother_team/team in brother_teams) + if(!team.members.len) + continue + text += "
Team #[teamnumber++]" + for(var/datum/mind/M in team.members) + text += printplayer(M) + var/win = TRUE + var/objective_count = 1 + for(var/datum/objective/objective in team.objectives) + if(objective.check_completion()) + text += "
Objective #[objective_count]: [objective.explanation_text] Success! [istype(objective, /datum/objective/crew) ? "(Optional)" : ""]" + SSblackbox.record_feedback("nested tally", "traitor_objective", 1, list("[objective.type]", "SUCCESS")) + else + text += "
Objective #[objective_count]: [objective.explanation_text] Fail. [istype(objective, /datum/objective/crew) ? "(Optional)" : ""]" + SSblackbox.record_feedback("nested tally", "traitor_objective", 1, list("[objective.type]", "FAIL")) + if(!(istype(objective, /datum/objective/crew))) + win = FALSE + objective_count++ + if(win) + text += "
The blood brothers were successful!" + SSblackbox.record_feedback("tally", "brother_success", 1, "SUCCESS") + else + text += "
The blood brothers have failed!" + SSblackbox.record_feedback("tally", "brother_success", 1, "FAIL") + text += "
" + to_chat(world, text) + /datum/game_mode/proc/update_brother_icons_added(datum/mind/brother_mind) var/datum/atom_hud/antag/brotherhud = GLOB.huds[ANTAG_HUD_BROTHER] brotherhud.join_hud(brother_mind.current) diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index ad76d41d47..a70f392d4f 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -94,6 +94,47 @@ GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our th of the Thing being sent to a station in this sector is highly likely. It may be in the guise of any crew member. Trust nobody - suspect everybody. Do not announce this to the crew, \ as paranoia may spread and inhibit workplace efficiency." +/datum/game_mode/proc/auto_declare_completion_changeling() + var/list/changelings = get_antagonists(/datum/antagonist/changeling,TRUE) //Only real lings get a mention + if(changelings.len) + var/text = "
The changelings were:" + for(var/datum/mind/changeling in changelings) + var/datum/antagonist/changeling/ling = changeling.has_antag_datum(/datum/antagonist/changeling) + var/changelingwin = 1 + if(!changeling.current) + changelingwin = 0 + + text += printplayer(changeling) + + //Removed sanity if(changeling) because we -want- a runtime to inform us that the changelings list is incorrect and needs to be fixed. + text += "
Changeling ID: [ling.changelingID]." + text += "
Genomes Extracted: [ling.absorbedcount]" + + if(changeling.objectives.len) + var/count = 1 + for(var/datum/objective/objective in changeling.objectives) + if(objective.check_completion()) + text += "
Objective #[count]: [objective.explanation_text] Success! [istype(objective, /datum/objective/crew) ? "(Optional)" : ""]" + SSblackbox.record_feedback("nested tally", "changeling_objective", 1, list("[objective.type]", "SUCCESS")) + else + text += "
Objective #[count]: [objective.explanation_text] Fail. [istype(objective, /datum/objective/crew) ? "(Optional)" : ""]" + SSblackbox.record_feedback("nested tally", "changeling_objective", 1, list("[objective.type]", "FAIL")) + if(!(istype(objective, /datum/objective/crew))) + changelingwin = 0 + count++ + + if(changelingwin) + text += "
The changeling was successful!" + SSblackbox.record_feedback("tally", "changeling_success", 1, "SUCCESS") + else + text += "
The changeling has failed." + SSblackbox.record_feedback("tally", "changeling_success", 1, "FAIL") + text += "
" + + to_chat(world, text) + + return 1 + /proc/changeling_transform(mob/living/carbon/human/user, datum/changelingprofile/chosen_prof) var/datum/dna/chosen_dna = chosen_prof.dna user.real_name = chosen_prof.name diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm index 1baabbebec..61bd9bb496 100644 --- a/code/game/gamemodes/clock_cult/clock_cult.dm +++ b/code/game/gamemodes/clock_cult/clock_cult.dm @@ -65,16 +65,13 @@ Credit where due: return TRUE return FALSE -/proc/add_servant_of_ratvar(mob/L, silent = FALSE, create_team = TRUE) +/proc/add_servant_of_ratvar(mob/L, silent = FALSE) if(!L || !L.mind) return var/update_type = ANTAG_DATUM_CLOCKCULT if(silent) update_type = ANTAG_DATUM_CLOCKCULT_SILENT - var/datum/antagonist/clockcult/C = new update_type(L.mind) - C.make_team = create_team - C.show_in_roundend = create_team //tutorial scarabs begone - . = L.mind.add_antag_datum(C) + . = L.mind.add_antag_datum(update_type) /proc/remove_servant_of_ratvar(mob/L, silent = FALSE) if(!L || !L.mind) @@ -91,6 +88,7 @@ Credit where due: /////////////// /datum/game_mode + var/datum/mind/eminence //The clockwork Eminence var/list/servants_of_ratvar = list() //The Enlightened servants of Ratvar var/clockwork_explanation = "Defend the Ark of the Clockwork Justiciar and free Ratvar." //The description of the current objective @@ -112,8 +110,6 @@ Credit where due: var/servants_to_serve = list() var/roundstart_player_count var/ark_time //In minutes, how long the Ark waits before activation; this is equal to 30 + (number of players / 5) (max 40 mins.) - - var/datum/objective_team/clockcult/main_clockcult /datum/game_mode/clockwork_cult/pre_setup() if(CONFIG_GET(flag/protect_roles_from_antagonist)) @@ -189,21 +185,22 @@ Credit where due: return FALSE /datum/game_mode/clockwork_cult/check_finished() - if(GLOB.ark_of_the_clockwork_justiciar && !GLOB.ratvar_awakens) // Doesn't end until the Ark is destroyed or completed + var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar + if(G && !GLOB.ratvar_awakens) // Doesn't end until the Ark is destroyed or completed return FALSE - return ..() + . = ..() /datum/game_mode/clockwork_cult/proc/check_clockwork_victory() - return main_clockcult.check_clockwork_victory() - -/datum/game_mode/clockwork_cult/set_round_result() - ..() if(GLOB.clockwork_gateway_activated) SSticker.news_report = CLOCK_SUMMON - SSticker.mode_result = "win - servants completed their objective (summon ratvar)" + return TRUE else SSticker.news_report = CULT_FAILURE - SSticker.mode_result = "loss - servants failed their objective (summon ratvar)" + return FALSE + +/datum/game_mode/clockwork_cult/declare_completion() + ..() + return //Doesn't end until the round does /datum/game_mode/clockwork_cult/generate_report() return "Bluespace monitors near your sector have detected a continuous stream of patterned fluctuations since the station was completed. It is most probable that a powerful entity \ @@ -213,6 +210,30 @@ Credit where due: working for this entity and utilizing highly-advanced technology to cross the great distance at will. If they should turn out to be a credible threat, the task falls on you and \ your crew to dispatch it in a timely manner." +/datum/game_mode/proc/auto_declare_completion_clockwork_cult() + var/text = "" + if(istype(SSticker.mode, /datum/game_mode/clockwork_cult)) //Possibly hacky? + var/datum/game_mode/clockwork_cult/C = SSticker.mode + if(C.check_clockwork_victory()) + text += "Ratvar's servants defended the Ark until its activation!" + SSticker.mode_result = "win - servants completed their objective (summon ratvar)" + else + text += "The Ark was destroyed! Ratvar will rust away for all eternity!" + SSticker.mode_result = "loss - servants failed their objective (summon ratvar)" + text += "
The servants' objective was: [CLOCKCULT_OBJECTIVE]." + text += "
Ratvar's servants had [GLOB.clockwork_caches] Tinkerer's Caches." + text += "
Construction Value(CV) was: [GLOB.clockwork_construction_value]" + for(var/i in SSticker.scripture_states) + if(i != SCRIPTURE_DRIVER) + text += "
[i] scripture was: [SSticker.scripture_states[i] ? "UN":""]LOCKED" + if(SSticker.mode.eminence) + text += "
The Eminence was: [printplayer(SSticker.mode.eminence)]" + if(servants_of_ratvar.len) + text += "
Ratvar's servants were:" + for(var/datum/mind/M in servants_of_ratvar - SSticker.mode.eminence) + text += printplayer(M) + to_chat(world, text) + /datum/game_mode/proc/update_servant_icons_added(datum/mind/M) var/datum/atom_hud/antag/A = GLOB.huds[ANTAG_HUD_CLOCKWORK] A.join_hud(M.current) diff --git a/code/game/gamemodes/clock_cult/clock_effects/spatial_gateway.dm b/code/game/gamemodes/clock_cult/clock_effects/spatial_gateway.dm index 895c38c94a..50076e0919 100644 --- a/code/game/gamemodes/clock_cult/clock_effects/spatial_gateway.dm +++ b/code/game/gamemodes/clock_cult/clock_effects/spatial_gateway.dm @@ -98,12 +98,12 @@ if(severity == 1 && uses) uses = 0 visible_message("[src] is disrupted!") - animate(src, alpha = 0, transform = matrix()*2, time = 10, flags = ANIMATION_END_NOW) + animate(src, alpha = 0, transform = matrix()*2, time = 10, flags_1 = ANIMATION_END_NOW) deltimer(timerid) timerid = QDEL_IN(src, 10) linked_gateway.uses = 0 linked_gateway.visible_message("[linked_gateway] is disrupted!") - animate(linked_gateway, alpha = 0, transform = matrix()*2, time = 10, flags = ANIMATION_END_NOW) + animate(linked_gateway, alpha = 0, transform = matrix()*2, time = 10, flags_1 = ANIMATION_END_NOW) deltimer(linked_gateway.timerid) linked_gateway.timerid = QDEL_IN(linked_gateway, 10) return TRUE @@ -144,13 +144,13 @@ uses = max(0, uses - 1) linked_gateway.uses = max(0, linked_gateway.uses - 1) if(!uses) - animate(src, transform = matrix() * 0.1, time = 10, flags = ANIMATION_END_NOW) - animate(linked_gateway, transform = matrix() * 0.1, time = 10, flags = ANIMATION_END_NOW) + animate(src, transform = matrix() * 0.1, time = 10, flags_1 = ANIMATION_END_NOW) + animate(linked_gateway, transform = matrix() * 0.1, time = 10, flags_1 = ANIMATION_END_NOW) density = FALSE linked_gateway.density = FALSE else - animate(src, transform = matrix() / 1.5, time = 10, flags = ANIMATION_END_NOW) - animate(linked_gateway, transform = matrix() / 1.5, time = 10, flags = ANIMATION_END_NOW) + animate(src, transform = matrix() / 1.5, time = 10, flags_1 = ANIMATION_END_NOW) + animate(linked_gateway, transform = matrix() / 1.5, time = 10, flags_1 = ANIMATION_END_NOW) addtimer(CALLBACK(src, .proc/check_uses), 10) return TRUE diff --git a/code/game/gamemodes/clock_cult/clock_helpers/fabrication_helpers.dm b/code/game/gamemodes/clock_cult/clock_helpers/fabrication_helpers.dm index 806abe3d52..a5af47ff05 100644 --- a/code/game/gamemodes/clock_cult/clock_helpers/fabrication_helpers.dm +++ b/code/game/gamemodes/clock_cult/clock_helpers/fabrication_helpers.dm @@ -132,7 +132,7 @@ var/doortype = /obj/machinery/door/airlock/clockwork if(glass) doortype = /obj/machinery/door/airlock/clockwork/brass - return list("operation_time" = 60, "new_obj_type" = doortype, "power_cost" = POWER_WALL_TOTAL, "spawn_dir" = dir, "transfer_name" = TRUE) + return list("operation_time" = 60, "new_obj_type" = doortype, "power_cost" = POWER_WALL_TOTAL, "spawn_dir" = dir) /obj/machinery/door/airlock/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) return FALSE @@ -188,7 +188,7 @@ //Windoor conversion /obj/machinery/door/window/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) - return list("operation_time" = 30, "new_obj_type" = /obj/machinery/door/window/clockwork, "power_cost" = POWER_STANDARD, "spawn_dir" = dir, "dir_in_new" = TRUE, "transfer_name" = TRUE) + return list("operation_time" = 30, "new_obj_type" = /obj/machinery/door/window/clockwork, "power_cost" = POWER_STANDARD, "spawn_dir" = dir, "dir_in_new" = TRUE) /obj/machinery/door/window/clockwork/fabrication_vals(mob/living/user, obj/item/clockwork/replica_fabricator/fabricator, silent) return FALSE diff --git a/code/game/gamemodes/clock_cult/clock_items/construct_chassis.dm b/code/game/gamemodes/clock_cult/clock_items/construct_chassis.dm index 1b2b867aa5..acf6e43974 100644 --- a/code/game/gamemodes/clock_cult/clock_items/construct_chassis.dm +++ b/code/game/gamemodes/clock_cult/clock_items/construct_chassis.dm @@ -91,8 +91,7 @@ /obj/item/clockwork/construct_chassis/cogscarab/pre_spawn() if(infinite_resources) - //During rounds where they can't interact with the station, let them experiment with builds - construct_type = /mob/living/simple_animal/drone/cogscarab/ratvar + construct_type = /mob/living/simple_animal/drone/cogscarab/ratvar //During rounds where they can't interact with the station, let them experiment with builds /obj/item/clockwork/construct_chassis/cogscarab/post_spawn(mob/living/construct) if(infinite_resources) //Allow them to build stuff and recite scripture diff --git a/code/game/gamemodes/clock_cult/clock_items/replica_fabricator.dm b/code/game/gamemodes/clock_cult/clock_items/replica_fabricator.dm index 24e46e280f..44fa24c134 100644 --- a/code/game/gamemodes/clock_cult/clock_items/replica_fabricator.dm +++ b/code/game/gamemodes/clock_cult/clock_items/replica_fabricator.dm @@ -144,14 +144,10 @@ else if(new_thing_type) if(fabrication_values["dir_in_new"]) - var/atom/A = new new_thing_type(get_turf(target), fabrication_values["spawn_dir"]) //please verify that your new object actually wants to get a dir in New() - if(fabrication_values["transfer_name"]) - A.name = target.name + new new_thing_type(get_turf(target), fabrication_values["spawn_dir"]) //please verify that your new object actually wants to get a dir in New() else var/atom/A = new new_thing_type(get_turf(target)) A.setDir(fabrication_values["spawn_dir"]) - if(fabrication_values["transfer_name"]) - A.name = target.name if(!fabrication_values["no_target_deletion"]) //for some cases where fabrication_vals() modifies the object but doesn't want it deleted qdel(target) adjust_clockwork_power(-fabrication_values["power_cost"]) diff --git a/code/game/gamemodes/clock_cult/clock_mobs/_eminence.dm b/code/game/gamemodes/clock_cult/clock_mobs/_eminence.dm index 8416e4651d..cc91feeb98 100644 --- a/code/game/gamemodes/clock_cult/clock_mobs/_eminence.dm +++ b/code/game/gamemodes/clock_cult/clock_mobs/_eminence.dm @@ -14,6 +14,16 @@ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE var/static/superheated_walls = 0 +/mob/camera/eminence/Initialize() + if(SSticker.mode.eminence) + return INITIALIZE_HINT_QDEL + . = ..() + +/mob/camera/eminence/Destroy(force) + if(!force && mind && SSticker.mode.eminence == mind) + return QDEL_HINT_LETMELIVE + return ..() + /mob/camera/eminence/CanPass(atom/movable/mover, turf/target) return TRUE @@ -29,20 +39,12 @@ /mob/camera/eminence/Login() ..() - var/datum/antagonist/clockcult/C = mind.has_antag_datum(/datum/antagonist/clockcult,TRUE) - if(!C) - add_servant_of_ratvar(src, TRUE) - C = mind.has_antag_datum(/datum/antagonist/clockcult,TRUE) - if(C && C.clock_team) - if(C.clock_team.eminence) - remove_servant_of_ratvar(src,TRUE) - qdel(src) - else - C.clock_team.eminence = src + add_servant_of_ratvar(src, TRUE) to_chat(src, "You have been selected as the Eminence!") to_chat(src, "As the Eminence, you lead the servants. Anything you say will be heard by the entire cult.") to_chat(src, "Though you can move through walls, you're also incorporeal, and largely can't interact with the world except for a few ways.") to_chat(src, "Additionally, unless the herald's beacon is activated, you can't understand any speech while away from Reebe.") + SSticker.mode.eminence = mind eminence_help() for(var/V in actions) var/datum/action/A = V diff --git a/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm b/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm index 495bfaeaa8..8d4e936658 100644 --- a/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm +++ b/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm @@ -17,11 +17,7 @@ return if(kingmaking) return - - var/datum/antagonist/clockcult/C = user.mind.has_antag_datum(/datum/antagonist/clockcult) - if(!C || !C.clock_team) - return - if(C.clock_team.eminence) + if(SSticker.mode.eminence) to_chat(user, "There's already an Eminence!") return if(!GLOB.servants_active) @@ -38,9 +34,7 @@ /obj/structure/destructible/clockwork/eminence_spire/attack_ghost(mob/user) if(!IsAdminGhost(user)) return - - var/datum/antagonist/clockcult/random_cultist = locate() in GLOB.antagonists //if theres no cultists new team without eminence will be created anyway. - if(random_cultist && random_cultist.clock_team && random_cultist.clock_team.eminence) + if(SSticker.mode.eminence) to_chat(user, "There's already an Eminence - too late!") return if(!GLOB.servants_active) diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 67e2225772..f20dd25802 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -2,23 +2,24 @@ /datum/game_mode var/list/datum/mind/cult = list() + var/list/cult_objectives = list() + var/eldergod = 1 //for the summon god objective /proc/iscultist(mob/living/M) return istype(M) && M.mind && M.mind.has_antag_datum(ANTAG_DATUM_CULT) -/datum/objective_team/cult/proc/is_sacrifice_target(datum/mind/mind) - for(var/datum/objective/sacrifice/sac_objective in objectives) - if(mind == sac_objective.target) - return TRUE +/proc/is_sacrifice_target(datum/mind/mind) + if(mind == GLOB.sac_mind) + return TRUE return FALSE - -/proc/is_convertable_to_cult(mob/living/M,datum/objective_team/cult/specific_cult) + +/proc/is_convertable_to_cult(mob/living/M) if(!istype(M)) return FALSE if(M.mind) if(ishuman(M) && (M.mind.assigned_role in list("Captain", "Chaplain"))) return FALSE - if(specific_cult && specific_cult.is_sacrifice_target(M.mind)) + if(is_sacrifice_target(M.mind)) return FALSE if(M.mind.enslaved_to && !iscultist(M.mind.enslaved_to)) return FALSE @@ -54,10 +55,10 @@ var/list/cultists_to_cult = list() //the cultists we'll convert - var/datum/objective_team/cult/main_cult - /datum/game_mode/cult/pre_setup() + cult_objectives += "sacrifice" + if(CONFIG_GET(flag/protect_roles_from_antagonist)) restricted_jobs += protected_jobs @@ -85,19 +86,82 @@ /datum/game_mode/cult/post_setup() + if("sacrifice" in cult_objectives) + var/list/possible_targets = get_unconvertables() + if(!possible_targets.len) + message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.") + for(var/mob/living/carbon/human/player in GLOB.player_list) + if(player.mind && !(player.mind in cultists_to_cult)) + possible_targets += player.mind + if(possible_targets.len > 0) + GLOB.sac_mind = pick(possible_targets) + if(!GLOB.sac_mind) + message_admins("Cult Sacrifice: ERROR - Null target chosen!") + else + var/datum/job/sacjob = SSjob.GetJob(GLOB.sac_mind.assigned_role) + var/datum/preferences/sacface = GLOB.sac_mind.current.client.prefs + var/icon/reshape = get_flat_human_icon(null, sacjob, sacface) + reshape.Shift(SOUTH, 4) + reshape.Shift(EAST, 1) + reshape.Crop(7,4,26,31) + reshape.Crop(-5,-3,26,30) + GLOB.sac_image = reshape + else + message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!") + if(!GLOB.summon_spots.len) + while(GLOB.summon_spots.len < SUMMON_POSSIBILITIES) + var/area/summon = pick(GLOB.sortedAreas - GLOB.summon_spots) + if((summon.z in GLOB.station_z_levels) && summon.valid_territory) + GLOB.summon_spots += summon + cult_objectives += "eldergod" + for(var/datum/mind/cult_mind in cultists_to_cult) - add_cultist(cult_mind, 0, equip=TRUE) + equip_cultist(cult_mind.current) + update_cult_icons_added(cult_mind) + to_chat(cult_mind.current, "You are a member of the cult!") + cult_mind.current.playsound_local(get_turf(cult_mind.current), 'sound/ambience/antag/bloodcult.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change + add_cultist(cult_mind, 0) ..() +/datum/game_mode/proc/equip_cultist(mob/living/carbon/human/mob,tome = 0) + if(!istype(mob)) + return + if (mob.mind) + if (mob.mind.assigned_role == "Clown") + to_chat(mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") + mob.dna.remove_mutation(CLOWNMUT) -/datum/game_mode/proc/add_cultist(datum/mind/cult_mind, stun , equip = FALSE) //BASE + if(tome) + . += cult_give_item(/obj/item/tome, mob) + else + . += cult_give_item(/obj/item/paper/talisman/supply, mob) + to_chat(mob, "These will help you start the cult on this station. Use them well, and remember - you are not the only one.") + +/datum/game_mode/proc/cult_give_item(obj/item/item_path, mob/living/carbon/human/mob) + var/list/slots = list( + "backpack" = slot_in_backpack, + "left pocket" = slot_l_store, + "right pocket" = slot_r_store + ) + + var/T = new item_path(mob) + var/item_name = initial(item_path.name) + var/where = mob.equip_in_one_of_slots(T, slots) + if(!where) + to_chat(mob, "Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1).") + return 0 + else + to_chat(mob, "You have a [item_name] in your [where].") + if(where == "backpack") + var/obj/item/storage/B = mob.back + B.orient2hud(mob) + B.show_to(mob) + return 1 + +/datum/game_mode/proc/add_cultist(datum/mind/cult_mind, stun) //BASE if (!istype(cult_mind)) return 0 - - var/datum/antagonist/cult/new_cultist = new(cult_mind) - new_cultist.give_equipment = equip - - if(cult_mind.add_antag_datum(new_cultist)) + if(cult_mind.add_antag_datum(ANTAG_DATUM_CULT)) if(stun) cult_mind.current.Unconscious(100) return 1 @@ -123,19 +187,25 @@ culthud.leave_hud(cult_mind.current) set_antag_hud(cult_mind.current, null) +/datum/game_mode/cult/proc/get_unconvertables() + var/list/ucs = list() + for(var/mob/living/carbon/human/player in GLOB.player_list) + if(player.mind && !is_convertable_to_cult(player) && !(player.mind in cultists_to_cult)) + ucs += player.mind + return ucs + /datum/game_mode/cult/proc/check_cult_victory() - return main_cult.check_cult_victory() + var/cult_fail = 0 + if(cult_objectives.Find("survive")) + cult_fail += check_survive() //the proc returns 1 if there are not enough cultists on the shuttle, 0 otherwise + if(cult_objectives.Find("eldergod")) + cult_fail += eldergod //1 by default, 0 if the elder god has been summoned at least once + if(cult_objectives.Find("sacrifice")) + if(GLOB.sac_mind && !GLOB.sac_complete) //if the target has been GLOB.sacrificed, ignore this step. otherwise, add 1 to cult_fail + cult_fail++ + return cult_fail //if any objectives aren't met, failure -/datum/game_mode/cult/set_round_result() - ..() - if(check_cult_victory()) - SSticker.mode_result = "win - cult win" - SSticker.news_report = CULT_SUMMON - else - SSticker.mode_result = "loss - staff stopped the cult" - SSticker.news_report = CULT_FAILURE - /datum/game_mode/cult/proc/check_survive() var/acolytes_survived = 0 for(var/datum/mind/cult_mind in cult) @@ -148,6 +218,57 @@ return 1 +/datum/game_mode/cult/declare_completion() + + if(!check_cult_victory()) + SSticker.mode_result = "win - cult win" + to_chat(world, "The cult has succeeded! Nar-sie has snuffed out another torch in the void!") + else + SSticker.mode_result = "loss - staff stopped the cult" + to_chat(world, "The staff managed to stop the cult! Dark words and heresy are no match for Nanotrasen's finest!") + + var/text = "" + + if(cult_objectives.len) + text += "
The cultists' objectives were:" + for(var/obj_count=1, obj_count <= cult_objectives.len, obj_count++) + var/explanation + switch(cult_objectives[obj_count]) + if("survive") + if(!check_survive()) + explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) Success!" + SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_survive", "SUCCESS")) + SSticker.news_report = CULT_ESCAPE + else + explanation = "Make sure at least [acolytes_needed] acolytes escape on the shuttle. ([acolytes_survived] escaped) Fail." + SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_survive", "FAIL")) + SSticker.news_report = CULT_FAILURE + if("sacrifice") + if(GLOB.sac_complete) + explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role]. Success!" + SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_sacrifice", "SUCCESS")) + else + explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role]. Fail." + SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_sacrifice", "FAIL")) + if("eldergod") + if(!eldergod) + explanation = "Summon Nar-Sie. The summoning can only be accomplished in [english_list(GLOB.summon_spots)].Success!" + SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_narsie", "SUCCESS")) + SSticker.news_report = CULT_SUMMON + else + explanation = "Summon Nar-Sie. The summoning can only be accomplished in [english_list(GLOB.summon_spots)]Fail." + SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_narsie", "FAIL")) + SSticker.news_report = CULT_FAILURE + + text += "
Objective #[obj_count]: [explanation]" + if(cult.len) + text += "
The cultists were:" + for(var/datum/mind/M in cult) + text += printplayer(M) + to_chat(world, text) + ..() + return 1 + /datum/game_mode/cult/generate_report() return "Some stations in your sector have reported evidence of blood sacrifice and strange magic. Ties to the Wizards' Federation have been proven not to exist, and many employees \ have disappeared; even Central Command employees light-years away have felt strange presences and at times hysterical compulsions. Interrogations point towards this being the work of \ @@ -155,4 +276,41 @@ devoted to stopping this cult. Note that holy water seems to weaken and eventually return the minds of cultists that ingest it, and mindshield implants will prevent conversion \ altogether." +/datum/game_mode/proc/datum_cult_completion() + var/text = "" + var/cult_fail = 0 + cult_fail += eldergod + if(!GLOB.sac_complete) + cult_fail++ + if(!cult_fail) + SSticker.mode_result = "win - cult win" + to_chat(world, "The cult has succeeded! Nar-sie has snuffed out another torch in the void!") + else + SSticker.mode_result = "loss - staff stopped the cult" + to_chat(world, "The staff managed to stop the cult! Dark words and heresy are no match for Nanotrasen's finest!") + if(cult_objectives.len) + text += "
The cultists' objectives were:" + for(var/obj_count in 1 to 2) + var/explanation + switch(cult_objectives[obj_count]) + if("sacrifice") + if(GLOB.sac_mind) + if(GLOB.sac_complete) + explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role]. Success!" + SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_sacrifice", "SUCCESS")) + else + explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role]. Fail." + SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_sacrifice", "FAIL")) + if("eldergod") + if(!eldergod) + explanation = "Summon Nar-Sie. Success!" + SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_narsie", "SUCCESS")) + SSticker.news_report = CULT_SUMMON + else + explanation = "Summon Nar-Sie. Fail." + SSblackbox.record_feedback("nested tally", "cult_objective", 1, list("cult_narsie", "FAIL")) + SSticker.news_report = CULT_FAILURE + text += "
Objective #[obj_count]: [explanation]" + to_chat(world, text) + #undef CULT_SCALING_COEFFICIENT diff --git a/code/game/gamemodes/cult/cult_comms.dm b/code/game/gamemodes/cult/cult_comms.dm index 2938f5abf4..530b6ebb20 100644 --- a/code/game/gamemodes/cult/cult_comms.dm +++ b/code/game/gamemodes/cult/cult_comms.dm @@ -88,21 +88,19 @@ button_icon_state = "cultvote" /datum/action/innate/cult/mastervote/IsAvailable() - var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - if(!C || C.cult_team.cult_vote_called || !ishuman(owner)) + if(GLOB.cult_vote_called || !ishuman(owner)) return FALSE return ..() /datum/action/innate/cult/mastervote/Activate() - var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - pollCultists(owner,C.cult_team) + pollCultists(owner) -/proc/pollCultists(var/mob/living/Nominee,datum/objective_team/cult/team) //Cult Master Poll +/proc/pollCultists(var/mob/living/Nominee) //Cult Master Poll if(world.time < CULT_POLL_WAIT) to_chat(Nominee, "It would be premature to select a leader while everyone is still settling in, try again in [DisplayTimeText(CULT_POLL_WAIT-world.time)].") return - team.cult_vote_called = TRUE //somebody's trying to be a master, make sure we don't let anyone else try - for(var/datum/mind/B in team.members) + GLOB.cult_vote_called = TRUE //somebody's trying to be a master, make sure we don't let anyone else try + for(var/datum/mind/B in SSticker.mode.cult) if(B.current) B.current.update_action_buttons_icon() if(!B.current.incapacitated()) @@ -110,39 +108,39 @@ to_chat(B.current, "Acolyte [Nominee] has asserted that they are worthy of leading the cult. A vote will be called shortly.") sleep(100) var/list/asked_cultists = list() - for(var/datum/mind/B in team.members) + for(var/datum/mind/B in SSticker.mode.cult) if(B.current && B.current != Nominee && !B.current.incapacitated()) SEND_SOUND(B.current, 'sound/magic/exit_blood.ogg') asked_cultists += B.current var/list/yes_voters = pollCandidates("[Nominee] seeks to lead your cult, do you support [Nominee.p_them()]?", poll_time = 300, group = asked_cultists) if(QDELETED(Nominee) || Nominee.incapacitated()) - team.cult_vote_called = FALSE - for(var/datum/mind/B in team.members) + GLOB.cult_vote_called = FALSE + for(var/datum/mind/B in SSticker.mode.cult) if(B.current) B.current.update_action_buttons_icon() if(!B.current.incapacitated()) to_chat(B.current,"[Nominee] has died in the process of attempting to win the cult's support!") return FALSE if(!Nominee.mind) - team.cult_vote_called = FALSE - for(var/datum/mind/B in team.members) + GLOB.cult_vote_called = FALSE + for(var/datum/mind/B in SSticker.mode.cult) if(B.current) B.current.update_action_buttons_icon() if(!B.current.incapacitated()) to_chat(B.current,"[Nominee] has gone catatonic in the process of attempting to win the cult's support!") return FALSE if(LAZYLEN(yes_voters) <= LAZYLEN(asked_cultists) * 0.5) - team.cult_vote_called = FALSE - for(var/datum/mind/B in team.members) + GLOB.cult_vote_called = FALSE + for(var/datum/mind/B in SSticker.mode.cult) if(B.current) B.current.update_action_buttons_icon() if(!B.current.incapacitated()) to_chat(B.current, "[Nominee] could not win the cult's support and shall continue to serve as an acolyte.") return FALSE - team.cult_mastered = TRUE + GLOB.cult_mastered = TRUE SSticker.mode.remove_cultist(Nominee.mind, TRUE) Nominee.mind.add_antag_datum(ANTAG_DATUM_CULT_MASTER) - for(var/datum/mind/B in team.members) + for(var/datum/mind/B in SSticker.mode.cult) if(B.current) for(var/datum/action/innate/cult/mastervote/vote in B.current.actions) vote.Remove(B.current) @@ -161,9 +159,6 @@ button_icon_state = "sintouch" /datum/action/innate/cult/master/finalreck/Activate() - var/datum/antagonist/cult/antag = owner.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - if(!antag) - return for(var/i in 1 to 4) chant(i) var/list/destinations = list() @@ -174,7 +169,7 @@ to_chat(owner, "You need more space to summon the cult!") return if(do_after(owner, 30, target = owner)) - for(var/datum/mind/B in antag.cult_team.members) + for(var/datum/mind/B in SSticker.mode.cult) if(B.current && B.current.stat != DEAD) var/turf/mobloc = get_turf(B.current) switch(i) @@ -199,7 +194,7 @@ addtimer(CALLBACK(B.current, /mob/.proc/reckon, final), 10) else return - antag.cult_team.reckoning_complete = TRUE + GLOB.reckoning_complete = TRUE Remove(owner) /mob/proc/reckon(turf/final) @@ -274,37 +269,34 @@ var/turf/T = get_turf(ranged_ability_user) if(!isturf(T)) return FALSE - - var/datum/antagonist/cult/C = caller.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - if(target in view(7, get_turf(ranged_ability_user))) - C.cult_team.blood_target = target + GLOB.blood_target = target var/area/A = get_area(target) attached_action.cooldown = world.time + attached_action.base_cooldown addtimer(CALLBACK(attached_action.owner, /mob.proc/update_action_buttons_icon), attached_action.base_cooldown) - C.cult_team.blood_target_image = image('icons/effects/cult_target.dmi', target, "glow", ABOVE_MOB_LAYER) - C.cult_team.blood_target_image.appearance_flags = RESET_COLOR - C.cult_team.blood_target_image.pixel_x = -target.pixel_x - C.cult_team.blood_target_image.pixel_y = -target.pixel_y + GLOB.blood_target_image = image('icons/effects/cult_target.dmi', target, "glow", ABOVE_MOB_LAYER) + GLOB.blood_target_image.appearance_flags = RESET_COLOR + GLOB.blood_target_image.pixel_x = -target.pixel_x + GLOB.blood_target_image.pixel_y = -target.pixel_y for(var/datum/mind/B in SSticker.mode.cult) if(B.current && B.current.stat != DEAD && B.current.client) - to_chat(B.current, "Master [ranged_ability_user] has marked [C.cult_team.blood_target] in the [A.name] as the cult's top priority, get there immediately!") + to_chat(B.current, "Master [ranged_ability_user] has marked [GLOB.blood_target] in the [A.name] as the cult's top priority, get there immediately!") SEND_SOUND(B.current, sound(pick('sound/hallucinations/over_here2.ogg','sound/hallucinations/over_here3.ogg'),0,1,75)) - B.current.client.images += C.cult_team.blood_target_image + B.current.client.images += GLOB.blood_target_image attached_action.owner.update_action_buttons_icon() remove_ranged_ability("The marking rite is complete! It will last for 90 seconds.") - C.cult_team.blood_target_reset_timer = addtimer(CALLBACK(GLOBAL_PROC, .proc/reset_blood_target,C.cult_team), 900, TIMER_STOPPABLE) + GLOB.blood_target_reset_timer = addtimer(CALLBACK(GLOBAL_PROC, .proc/reset_blood_target), 900, TIMER_STOPPABLE) return TRUE return FALSE -/proc/reset_blood_target(datum/objective_team/cult/team) - for(var/datum/mind/B in team.members) +/proc/reset_blood_target() + for(var/datum/mind/B in SSticker.mode.cult) if(B.current && B.current.stat != DEAD && B.current.client) - if(team.blood_target) + if(GLOB.blood_target) to_chat(B.current,"The blood mark has expired!") - B.current.client.images -= team.blood_target_image - QDEL_NULL(team.blood_target_image) - team.blood_target = null + B.current.client.images -= GLOB.blood_target_image + QDEL_NULL(GLOB.blood_target_image) + GLOB.blood_target = null diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index ad0b8d91a1..da222fe521 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -163,7 +163,7 @@ /obj/item/twohanded/required/cult_bastard/afterattack(atom/target, mob/user, proximity, click_parameters) . = ..() - if(dash_toggled) + if(dash_toggled && jaunt.IsAvailable()) jaunt.Teleport(user, target) return if(!proximity) diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index 8d12343a8d..440dfaede6 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -100,9 +100,10 @@ if(cooldowntime > world.time) to_chat(user, "The magic in [src] is weak, it will be ready to use again in [DisplayTimeText(cooldowntime - world.time)].") return - var/choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Bastard Sword") + var/option = "Shielded Robe" + option = input(user, "You study the schematics etched into the forge...", "[src]", option) as null|anything in list("Shielded Robe", "Flagellant's Robe", "Bastard Sword", "Nar-Sien Hardsuit") var/pickedtype - switch(choice) + switch(option) if("Shielded Robe") pickedtype = /obj/item/clothing/suit/hooded/cultrobes/cult_shield if("Flagellant's Robe") diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index 8aebf1d196..2adaa57a2f 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -179,13 +179,6 @@ This file contains the arcane tome files. var/list/shields = list() var/area/A = get_area(src) - var/datum/antagonist/cult/user_antag = user.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - if(!user_antag) - return - - var/datum/objective/eldergod/summon_objective = locate() in user_antag.cult_team.objectives - var/datum/objective/sacrifice/sac_objective = locate() in user_antag.cult_team.objectives - if(!check_rune_turf(Turf, user)) return entered_rune_name = input(user, "Choose a rite to scribe.", "Sigils of Power") as null|anything in GLOB.rune_types @@ -203,20 +196,18 @@ This file contains the arcane tome files. A = get_area(src) if(!src || QDELETED(src) || !Adjacent(user) || user.incapacitated() || !check_rune_turf(Turf, user)) return - - //AAAAAAAAAAAAAAAH, i'm rewriting enough for now so TODO: remove this shit if(ispath(rune_to_scribe, /obj/effect/rune/narsie)) - if(!summon_objective) + if(!("eldergod" in SSticker.mode.cult_objectives)) to_chat(user, "Nar-Sie does not wish to be summoned!") return - if(sac_objective && !sac_objective.check_completion()) + if(!GLOB.sac_complete) to_chat(user, "The sacrifice is not complete. The portal would lack the power to open if you tried!") return - if(summon_objective.check_completion()) + if(!SSticker.mode.eldergod) to_chat(user, "\"I am already here. There is no need to try to summon me now.\"") return - if(!(A in summon_objective.summon_spots)) - to_chat(user, "The Geometer can only be summoned where the veil is weak - in [english_list(summon_objective.summon_spots)]!") + if(!(A in GLOB.summon_spots)) + to_chat(user, "The Geometer can only be summoned where the veil is weak - in [english_list(GLOB.summon_spots)]!") return var/confirm_final = alert(user, "This is the FINAL step to summon Nar-Sie; it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for Nar-Sie!", "No") if(confirm_final == "No") @@ -224,8 +215,8 @@ This file contains the arcane tome files. return Turf = get_turf(user) A = get_area(src) - if(!(A in summon_objective.summon_spots)) // Check again to make sure they didn't move - to_chat(user, "The Geometer can only be summoned where the veil is weak - in [english_list(summon_objective.summon_spots)]!") + if(!(A in GLOB.summon_spots)) // Check again to make sure they didn't move + to_chat(user, "The Geometer can only be summoned where the veil is weak - in [english_list(GLOB.summon_spots)]!") return priority_announce("Figments from an eldritch god are being summoned by [user] into [A.map_name] from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", 'sound/ai/spanomalies.ogg') for(var/B in spiral_range_turfs(1, user, 1)) @@ -266,10 +257,8 @@ This file contains the arcane tome files. to_chat(user, "There is already a rune here.") return FALSE - if(!(T.z in GLOB.station_z_levels) && T.z != ZLEVEL_MINING) to_chat(user, "The veil is not weak enough here.") - return FALSE return TRUE diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index fc6a36376b..33d5f49661 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -349,11 +349,7 @@ structure_check() searches for nearby cultist structures required for the invoca color = RUNE_COLOR_DARKRED var/mob/living/L = pick(myriad_targets) var/is_clock = is_servant_of_ratvar(L) - - var/mob/living/F = invokers[1] - var/datum/antagonist/cult/C = F.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - - var/is_convertable = is_convertable_to_cult(L,C.cult_team) + var/is_convertable = is_convertable_to_cult(L) if(L.stat != DEAD && (is_clock || is_convertable)) invocation = "Mah'weyh pleggh at e'ntrath!" ..() @@ -401,27 +397,17 @@ structure_check() searches for nearby cultist structures required for the invoca return 1 /obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers) - var/mob/living/first_invoker = invokers[1] - if(!first_invoker) - return FALSE - var/datum/antagonist/cult/C = first_invoker.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - if(!C) - return - - var/big_sac = FALSE - if((((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || C.cult_team.is_sacrifice_target(sacrificial.mind)) && invokers.len < 3) + if((((ishuman(sacrificial) || iscyborg(sacrificial)) && sacrificial.stat != DEAD) || is_sacrifice_target(sacrificial.mind)) && invokers.len < 3) for(var/M in invokers) to_chat(M, "[sacrificial] is too greatly linked to the world! You need three acolytes!") log_game("Offer rune failed - not enough acolytes and target is living or sac target") return FALSE if(sacrificial.mind) GLOB.sacrificed += sacrificial.mind - for(var/datum/objective/sacrifice/sac_objective in C.cult_team.objectives) - if(sac_objective.target == sacrificial.mind) - sac_objective.sacced = TRUE - sac_objective.update_explanation_text() - big_sac = TRUE + if(is_sacrifice_target(sacrificial.mind)) + GLOB.sac_complete = TRUE + big_sac = TRUE else GLOB.sacrificed += sacrificial @@ -495,6 +481,7 @@ structure_check() searches for nearby cultist structures required for the invoca sleep(40) if(src) color = RUNE_COLOR_RED + SSticker.mode.eldergod = FALSE new /obj/singularity/narsie/large/cult(T) //Causes Nar-Sie to spawn even if the rune has been removed /obj/effect/rune/narsie/attackby(obj/I, mob/user, params) //Since the narsie rune takes a long time to make, add logging to removal. diff --git a/code/game/gamemodes/devil/game_mode.dm b/code/game/gamemodes/devil/game_mode.dm index 44f3368feb..957e261933 100644 --- a/code/game/gamemodes/devil/game_mode.dm +++ b/code/game/gamemodes/devil/game_mode.dm @@ -3,6 +3,32 @@ var/list/datum/mind/devils = list() var/devil_ascended = 0 // Number of arch devils on station +/datum/game_mode/proc/auto_declare_completion_sintouched() + var/text = "" + if(sintouched.len) + text += "
The sintouched were:" + var/list/sintouchedUnique = uniqueList(sintouched) + for(var/S in sintouchedUnique) + var/datum/mind/sintouched_mind = S + text += printplayer(sintouched_mind) + text += printobjectives(sintouched_mind) + text += "
" + text += "
" + to_chat(world, text) + +/datum/game_mode/proc/auto_declare_completion_devils() + /var/text = "" + if(devils.len) + text += "
The devils were:" + for(var/D in devils) + var/datum/mind/devil = D + text += printplayer(devil) + text += printdevilinfo(devil.current) + text += printobjectives(devil) + text += "
" + text += "
" + to_chat(world, text) + /datum/game_mode/proc/add_devil_objectives(datum/mind/devil_mind, quantity) var/list/validtypes = list(/datum/objective/devil/soulquantity, /datum/objective/devil/soulquality, /datum/objective/devil/sintouch, /datum/objective/devil/buy_target) for(var/i = 1 to quantity) @@ -15,6 +41,18 @@ else objective.find_target() +/datum/game_mode/proc/printdevilinfo(mob/living/ply) + var/datum/antagonist/devil/devilinfo = is_devil(ply) + if(!devilinfo) + return "Target is not a devil." + var/text = "
The devil's true name is: [devilinfo.truename]
" + text += "The devil's bans were:
" + text += " [GLOB.lawlorify[LORE][devilinfo.ban]]
" + text += " [GLOB.lawlorify[LORE][devilinfo.bane]]
" + text += " [GLOB.lawlorify[LORE][devilinfo.obligation]]
" + text += " [GLOB.lawlorify[LORE][devilinfo.banish]]

" + return text + /datum/game_mode/proc/update_devil_icons_added(datum/mind/devil_mind) var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_DEVIL] hud.join_hud(devil_mind.current) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index a0e5a9f147..803e73b9e0 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -19,7 +19,6 @@ var/probability = 0 var/false_report_weight = 0 //How often will this show up incorrectly in a centcom report? var/station_was_nuked = 0 //see nuclearbomb.dm and malfunction.dm - var/nuke_off_station = 0 //Used for tracking where the nuke hit var/round_ends_with_antag_death = 0 //flags the "one verse the station" antags as such var/list/datum/mind/antag_candidates = list() // List of possible starting antags goes here var/list/restricted_jobs = list() // Jobs it doesn't make sense to be. I.E chaplain or AI cultist @@ -74,6 +73,7 @@ /datum/game_mode/proc/pre_setup() return 1 + ///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things /datum/game_mode/proc/post_setup(report) //Gamemodes can override the intercept report. Passing TRUE as the argument will force a report. if(!report) @@ -241,9 +241,55 @@ return 0 +/datum/game_mode/proc/declare_completion() + var/clients = 0 + var/surviving_humans = 0 + var/surviving_total = 0 + var/ghosts = 0 + var/escaped_humans = 0 + var/escaped_total = 0 + + for(var/mob/M in GLOB.player_list) + if(M.client) + clients++ + if(ishuman(M)) + if(!M.stat) + surviving_humans++ + if(M.z == ZLEVEL_CENTCOM) + escaped_humans++ + if(!M.stat) + surviving_total++ + if(M.z == ZLEVEL_CENTCOM) + escaped_total++ + + + if(isobserver(M)) + ghosts++ + + if(clients) + SSblackbox.record_feedback("nested tally", "round_end_stats", clients, list("clients")) + if(ghosts) + SSblackbox.record_feedback("nested tally", "round_end_stats", ghosts, list("ghosts")) + if(surviving_humans) + SSblackbox.record_feedback("nested tally", "round_end_stats", surviving_humans, list("survivors", "human")) + if(surviving_total) + SSblackbox.record_feedback("nested tally", "round_end_stats", surviving_total, list("survivors", "total")) + if(escaped_humans) + SSblackbox.record_feedback("nested tally", "round_end_stats", escaped_humans, list("escapees", "human")) + if(escaped_total) + SSblackbox.record_feedback("nested tally", "round_end_stats", escaped_total, list("escapees", "total")) + + send2irc("Server", "Round just ended.") + if(cult.len && !istype(SSticker.mode, /datum/game_mode/cult)) + datum_cult_completion() + + return 0 + + /datum/game_mode/proc/check_win() //universal trigger to be called at mob death, nuke explosion, etc. To be called from everywhere. return 0 + /datum/game_mode/proc/send_intercept() var/intercepttext = "Central Command Status Summary
" intercepttext += "Central Command has intercepted and partially decoded a Syndicate transmission with vital information regarding their movements. The following report outlines the most \ @@ -405,6 +451,34 @@ for (var/C in GLOB.admins) to_chat(C, msg) +/datum/game_mode/proc/printplayer(datum/mind/ply, fleecheck) + var/text = "
[ply.key] was [ply.name] the [ply.assigned_role] and" + if(ply.current) + if(ply.current.stat == DEAD) + text += " died" + else + text += " survived" + if(fleecheck) + var/turf/T = get_turf(ply.current) + if(!T || !(T.z in GLOB.station_z_levels)) + text += " while fleeing the station" + if(ply.current.real_name != ply.name) + text += " as [ply.current.real_name]" + else + text += " had their body destroyed" + return text + +/datum/game_mode/proc/printobjectives(datum/mind/ply) + var/text = "" + var/count = 1 + for(var/datum/objective/objective in ply.objectives) + if(objective.check_completion()) + text += "
Objective #[count]: [objective.explanation_text] Success!" + else + text += "
Objective #[count]: [objective.explanation_text] Fail." + count++ + return text + //If the configuration option is set to require players to be logged as old enough to play certain jobs, then this proc checks that they are, otherwise it just returns 1 /datum/game_mode/proc/age_check(client/C) if(get_remaining_days(C) == 0) @@ -444,25 +518,15 @@ station_goals += new picked +/datum/game_mode/proc/declare_station_goal_completion() + for(var/V in station_goals) + var/datum/station_goal/G = V + G.print_result() + /datum/game_mode/proc/generate_report() //Generates a small text blurb for the gamemode in centcom report return "Gamemode report for [name] not set. Contact a coder." //By default nuke just ends the round /datum/game_mode/proc/OnNukeExplosion(off_station) - nuke_off_station = off_station if(off_station < 2) station_was_nuked = TRUE //Will end the round on next check. - -//Additional report section in roundend report -/datum/game_mode/proc/special_report() - return - -//Set result and news report here -/datum/game_mode/proc/set_round_result() - SSticker.mode_result = "undefined" - if(station_was_nuked) - SSticker.news_report = STATION_DESTROYED_NUKE - if(EMERGENCY_ESCAPED_OR_ENDGAMED) - SSticker.news_report = STATION_EVACUATED - if(SSshuttle.emergency.is_hijacked()) - SSticker.news_report = SHUTTLE_HIJACK \ No newline at end of file diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index ff2ffce7ee..1c17893a28 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -367,12 +367,12 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( var/sec_left = seconds_remaining() if(!sec_left) timing = FALSE - detonate() + detonate(T.z) else if(world.time >= next_announce) minor_announce("[sec_left] SECONDS UNTIL DOOMSDAY DEVICE ACTIVATION!", "ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4", TRUE) next_announce += DOOMSDAY_ANNOUNCE_INTERVAL -/obj/machinery/doomsday_device/proc/detonate() +/obj/machinery/doomsday_device/proc/detonate(z_level = ZLEVEL_STATION_PRIMARY) sound_to_playing_players('sound/machines/alarm.ogg') sleep(100) for(var/i in GLOB.mob_living_list) diff --git a/code/game/gamemodes/meteor/meteor.dm b/code/game/gamemodes/meteor/meteor.dm index f8e0666015..b7a6580570 100644 --- a/code/game/gamemodes/meteor/meteor.dm +++ b/code/game/gamemodes/meteor/meteor.dm @@ -30,29 +30,30 @@ spawn_meteors(ramp_up_final, wavetype) -/datum/game_mode/meteor/special_report() +/datum/game_mode/meteor/declare_completion() + var/text var/survivors = 0 - var/list/survivor_list = list() for(var/mob/living/player in GLOB.player_list) if(player.stat != DEAD) ++survivors if(player.onCentCom()) - survivor_list += "[player.real_name] escaped to the safety of CentCom." + text += "
[player.real_name] escaped to the safety of CentCom." else if(player.onSyndieBase()) - survivor_list += "[player.real_name] escaped to the (relative) safety of Syndicate Space." + text += "
[player.real_name] escaped to the (relative) safety of Syndicate Space." else - survivor_list += "[player.real_name] survived but is stranded without any hope of rescue." + text += "
[player.real_name] survived but is stranded without any hope of rescue." + if(survivors) - return "The following survived the meteor storm:
[survivor_list.Join("
")]" + to_chat(world, "The following survived the meteor storm:[text]") else - return "Nobody survived the meteor storm!" + to_chat(world, "Nobody survived the meteor storm!") -/datum/game_mode/meteor/set_round_result() - ..() SSticker.mode_result = "end - evacuation" + ..() + return 1 /datum/game_mode/meteor/generate_report() return "[pick("Asteroids have", "Meteors have", "Large rocks have", "Stellar minerals have", "Space hail has", "Debris has")] been detected near your station, and a collision is possible, \ diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index 289de1aabd..780be71694 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -105,7 +105,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event /obj/effect/meteor/Move() if(z != z_original || loc == dest) qdel(src) - return FALSE + return . = ..() //process movement... diff --git a/code/game/gamemodes/miniantags/abduction/abduction.dm b/code/game/gamemodes/miniantags/abduction/abduction.dm index 12987124ac..4eb8642c02 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction.dm @@ -1,5 +1,19 @@ +/datum/objective_team/abductor_team + member_name = "abductor" + var/list/objectives = list() + var/team_number + +/datum/objective_team/abductor_team/is_solo() + return FALSE + +/datum/objective_team/abductor_team/proc/add_objective(datum/objective/O) + O.team = src + O.update_explanation_text() + objectives += O + /datum/game_mode var/list/datum/mind/abductors = list() + var/list/datum/mind/abductees = list() /datum/game_mode/abduction name = "abduction" @@ -50,7 +64,6 @@ antag_candidates -= scientist team.members |= scientist scientist.assigned_role = "Abductor Scientist" - scientist.special_role = "Abductor Scientist" log_game("[scientist.key] (ckey) has been selected as [team.name] abductor scientist.") if(!agent) @@ -58,7 +71,6 @@ antag_candidates -= agent team.members |= agent agent.assigned_role = "Abductor Agent" - agent.special_role = "Abductor Agent" log_game("[agent.key] (ckey) has been selected as [team.name] abductor agent.") abductor_teams += team @@ -87,6 +99,35 @@ return ..() return ..() +/datum/game_mode/abduction/declare_completion() + for(var/datum/objective_team/abductor_team/team in abductor_teams) + var/won = TRUE + for(var/datum/objective/O in team.objectives) + if(!O.check_completion()) + won = FALSE + if(won) + to_chat(world, "[team.name] team fulfilled its mission!") + else + to_chat(world, "[team.name] team failed its mission.") + ..() + return TRUE + +/datum/game_mode/proc/auto_declare_completion_abduction() + var/text = "" + if(abductors.len) + text += "
The abductors were:" + for(var/datum/mind/abductor_mind in abductors) + text += printplayer(abductor_mind) + text += printobjectives(abductor_mind) + text += "
" + if(abductees.len) + text += "
The abductees were:" + for(var/datum/mind/abductee_mind in abductees) + text += printplayer(abductee_mind) + text += printobjectives(abductee_mind) + text += "
" + to_chat(world, text) + // LANDMARKS /obj/effect/landmark/abductor var/team_number = 1 diff --git a/code/game/gamemodes/miniantags/abduction/gland.dm b/code/game/gamemodes/miniantags/abduction/gland.dm index 70aecaba5e..22edb79c80 100644 --- a/code/game/gamemodes/miniantags/abduction/gland.dm +++ b/code/game/gamemodes/miniantags/abduction/gland.dm @@ -236,10 +236,11 @@ /obj/item/organ/heart/gland/plasma/activate() to_chat(owner, "You feel bloated.") - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, owner, "A massive stomachache overcomes you."), 150) - addtimer(CALLBACK(src, .proc/vomit_plasma), 200) - -/obj/item/organ/heart/gland/plasma/proc/vomit_plasma() + sleep(150) + if(!owner) + return + to_chat(owner, "A massive stomachache overcomes you.") + sleep(50) if(!owner) return owner.visible_message("[owner] vomits a cloud of plasma!") diff --git a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm index cf1329aec9..c3a591a278 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm @@ -151,18 +151,13 @@ var/mob/living/mob_occupant = occupant if(mob_occupant.stat != DEAD) if(href_list["experiment"]) - flash = Experiment(occupant,href_list["experiment"],usr) + flash = Experiment(occupant,href_list["experiment"]) updateUsrDialog() add_fingerprint(usr) -/obj/machinery/abductor/experiment/proc/Experiment(mob/occupant,type,mob/user) +/obj/machinery/abductor/experiment/proc/Experiment(mob/occupant,type) LAZYINITLIST(history) var/mob/living/carbon/human/H = occupant - - var/datum/antagonist/abductor/user_abductor = user.mind.has_antag_datum(/datum/antagonist/abductor) - if(!user_abductor) - return "Authorization failure. Contact mothership immidiately." - var/point_reward = 0 if(H in history) return "Specimen already in database." @@ -187,8 +182,15 @@ if(3) to_chat(H, "You feel intensely watched.") sleep(5) - user_abductor.team.abductees += H.mind - H.mind.add_antag_datum(/datum/antagonist/abductee) + to_chat(H, "Your mind snaps!") + H.gain_trauma_type(BRAIN_TRAUMA_MILD) + to_chat(H, "You can't remember how you got here...") + var/objtype = (prob(75) ? /datum/objective/abductee/random : pick(subtypesof(/datum/objective/abductee/) - /datum/objective/abductee/random)) + var/datum/objective/abductee/O = new objtype() + SSticker.mode.abductees += H.mind + H.mind.objectives += O + H.mind.announce_objectives() + SSticker.mode.update_abductor_icons_added(H.mind) for(var/obj/item/organ/heart/gland/G in H.internal_organs) G.Start() diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm index f8a1df3cb8..ff426ab625 100644 --- a/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm +++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm @@ -1,8 +1,8 @@ /datum/round_event_control/spawn_swarmer name = "Spawn Swarmer Shell" typepath = /datum/round_event/spawn_swarmer - weight = 7 - max_occurrences = 1 //Only once okay fam + weight = 0 + max_occurrences = 0 //Only once okay fam earliest_start = 18000 //30 minutes min_players = 15 diff --git a/code/game/gamemodes/miniantags/monkey/monkey.dm b/code/game/gamemodes/miniantags/monkey/monkey.dm index 8e02d41441..379031dce9 100644 --- a/code/game/gamemodes/miniantags/monkey/monkey.dm +++ b/code/game/gamemodes/miniantags/monkey/monkey.dm @@ -105,18 +105,13 @@ monkey_mind.special_role = null -/datum/game_mode/monkey/set_round_result() - ..() +/datum/game_mode/monkey/declare_completion() if(check_monkey_victory()) SSticker.mode_result = "win - monkey win" + to_chat(world, "The monkeys have overthrown their captors! Eeek eeeek!!") else SSticker.mode_result = "loss - staff stopped the monkeys" - -/datum/game_mode/monkey/special_report() - if(check_monkey_victory()) - return "The monkeys have overthrown their captors! Eeek eeeek!!" - else - return "The staff managed to contain the monkey infestation!" + to_chat(world, "The staff managed to contain the monkey infestation!") /datum/game_mode/monkey/generate_report() return "Reports of an ancient [pick("retrovirus", "flesh eating bacteria", "disease", "magical curse blamed on viruses", "banana blight")] outbreak that turn humans into monkeys has been reported in your quadrant. Any such infections may be treated with banana juice. If an outbreak occurs, ensure the station is quarantined to prevent a largescale outbreak at CentCom." diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm index 2ebc21adac..5e1a97675b 100644 --- a/code/game/gamemodes/miniantags/morph/morph.dm +++ b/code/game/gamemodes/miniantags/morph/morph.dm @@ -227,7 +227,6 @@ player_mind.assigned_role = "Morph" player_mind.special_role = "Morph" SSticker.mode.traitors |= player_mind - player_mind.add_antag_datum(/datum/antagonist/auto_custom) to_chat(S, S.playstyle_string) SEND_SOUND(S, sound('sound/magic/mutate.ogg')) message_admins("[key_name_admin(S)] has been made into a morph by an event.") diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm index 441689fb9b..727203b150 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant.dm @@ -87,7 +87,6 @@ mind.assigned_role = "revenant" mind.special_role = "Revenant" SSticker.mode.traitors |= mind //Necessary for announcing - mind.add_antag_datum(/datum/antagonist/auto_custom) AddSpell(new /obj/effect/proc_holder/spell/targeted/night_vision/revenant(null)) AddSpell(new /obj/effect/proc_holder/spell/targeted/revenant_transmit(null)) AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/defile(null)) @@ -375,7 +374,7 @@ return var/key_of_revenant message_admins("Revenant ectoplasm was left undestroyed for 1 minute and is reforming into a new revenant.") - forceMove(drop_location()) //In case it's in a backpack or someone's hand + loc = get_turf(src) //In case it's in a backpack or someone's hand revenant.forceMove(loc) if(client_to_revive) for(var/mob/M in GLOB.dead_mob_list) diff --git a/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm b/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm index e62665f21b..f1f9624380 100644 --- a/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm +++ b/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm @@ -38,7 +38,6 @@ player_mind.assigned_role = "Slaughter Demon" player_mind.special_role = "Slaughter Demon" SSticker.mode.traitors |= player_mind - player_mind.add_antag_datum(/datum/antagonist/auto_custom) to_chat(S, S.playstyle_string) to_chat(S, "You are currently not currently in the same plane of existence as the station. Blood Crawl near a blood pool to manifest.") SEND_SOUND(S, 'sound/magic/demon_dies.ogg') diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index f3dee00303..94c372ef23 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -1,3 +1,7 @@ +/datum/game_mode + var/list/datum/mind/syndicates = list() + var/nukeops_lastname = "" + /datum/game_mode/nuclear name = "nuclear emergency" config_tag = "nuclear" @@ -14,10 +18,11 @@ Crew: Defend the nuclear authentication disk and ensure that it leaves with you on the emergency shuttle." var/const/agents_possible = 5 //If we ever need more syndicate agents. - var/nukes_left = 1 // Call 3714-PRAY right now and order more nukes! Limited offer! - var/list/pre_nukeops = list() - var/datum/objective_team/nuclear/nuke_team + var/nukes_left = 1 // Call 3714-PRAY right now and order more nukes! Limited offer! + var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station + var/syndies_didnt_escape = 0 //Used for tracking if the syndies got the shuttle off of the z-level + var/list/pre_nukeops = list() /datum/game_mode/nuclear/pre_setup() var/n_agents = min(round(num_players() / 10), antag_candidates.len, agents_possible) @@ -28,23 +33,120 @@ new_op.special_role = "Nuclear Operative" log_game("[new_op.key] (ckey) has been selected as a nuclear operative") return TRUE + +//////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////// +/datum/game_mode/proc/update_synd_icons_added(datum/mind/synd_mind) + var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS] + opshud.join_hud(synd_mind.current) + set_antag_hud(synd_mind.current, "synd") + +/datum/game_mode/proc/update_synd_icons_removed(datum/mind/synd_mind) + var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS] + opshud.leave_hud(synd_mind.current) + set_antag_hud(synd_mind.current, null) + //////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////// /datum/game_mode/nuclear/post_setup() - //Assign leader - var/datum/mind/leader_mind = pre_nukeops[1] - var/datum/antagonist/nukeop/L = leader_mind.add_antag_datum(/datum/antagonist/nukeop/leader) - nuke_team = L.nuke_team - //Assign the remaining operatives - for(var/i = 2 to pre_nukeops.len) - var/datum/mind/nuke_mind = pre_nukeops[i] - nuke_mind.add_antag_datum(/datum/antagonist/nukeop,nuke_team) + var/nuke_code = random_nukecode() + var/agent_number = 1 + var/datum/mind/leader = pick(pre_nukeops) + syndicates += pre_nukeops + for(var/i = 1 to pre_nukeops.len) + var/datum/mind/op = pre_nukeops[i] + + forge_syndicate_objectives(op) + greet_syndicate(op) + equip_syndicate(op.current) + + if(nuke_code) + op.store_memory("Syndicate Nuclear Bomb Code: [nuke_code]", 0, 0) + to_chat(op.current, "The nuclear authorization code is: [nuke_code]") + + if(op == leader) + op.current.forceMove(pick(GLOB.nukeop_leader_start)) + prepare_syndicate_leader(op, nuke_code) + else + op.current.forceMove(GLOB.nukeop_start[((i - 1) % GLOB.nukeop_start.len) + 1]) + op.current.real_name = "[syndicate_name()] Operative #[agent_number++]" + + update_synd_icons_added(op) + op.current.playsound_local(get_turf(op.current), 'sound/ambience/antag/ops.ogg',100,0) + + var/obj/machinery/nuclearbomb/nuke = locate("syndienuke") in GLOB.nuke_list + if(nuke) + nuke.r_code = nuke_code return ..() +/datum/game_mode/proc/prepare_syndicate_leader(datum/mind/synd_mind, nuke_code) + var/leader_title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord") + addtimer(CALLBACK(src, .proc/nuketeam_name_assign, synd_mind), 1) + synd_mind.current.real_name = "[syndicate_name()] [leader_title]" + to_chat(synd_mind.current, "You are the Syndicate [leader_title] for this mission. You are responsible for the distribution of telecrystals and your ID is the only one who can open the launch bay doors.") + to_chat(synd_mind.current, "If you feel you are not up to this task, give your ID to another operative.") + to_chat(synd_mind.current, "In your hand you will find a special item capable of triggering a greater challenge for your team. Examine it carefully and consult with your fellow operatives before activating it.") + + var/obj/item/device/nuclear_challenge/challenge = new /obj/item/device/nuclear_challenge + synd_mind.current.put_in_hands(challenge, TRUE) + + var/static/id_cache = typecacheof(/obj/item/card/id) + var/list/foundIDs = typecache_filter_list(synd_mind.current.GetAllContents(), id_cache) + if(foundIDs.len) + for(var/i in 1 to foundIDs.len) + var/obj/item/card/id/ID = foundIDs[i] + ID.name = "lead agent card" + ID.access += ACCESS_SYNDICATE_LEADER + else + message_admins("Warning: Nuke Ops spawned without access to leave their spawn area!") + + var/obj/item/device/radio/headset/syndicate/alt/A = locate() in synd_mind.current + if(A) + A.command = TRUE + + if(nuke_code) + var/obj/item/paper/P = new + P.info = "The nuclear authorization code is: [nuke_code]" + P.name = "nuclear bomb code" + var/mob/living/carbon/human/H = synd_mind.current + H.put_in_hands(P, TRUE) + H.update_icons() + else + nuke_code = "code will be provided later" + return + +/datum/game_mode/proc/nuketeam_name_assign(datum/mind/synd_mind) + nukeops_lastname = nukelastname(synd_mind.current) + NukeNameAssign(nukeops_lastname, syndicates) + + +/datum/game_mode/proc/forge_syndicate_objectives(datum/mind/syndicate) + var/datum/objective/nuclear/syndobj = new + syndobj.owner = syndicate + syndicate.objectives += syndobj + + +/datum/game_mode/proc/greet_syndicate(datum/mind/syndicate, you_are=1) + if(you_are) + to_chat(syndicate.current, "You are a [syndicate_name()] agent!") + syndicate.announce_objectives() + +/datum/game_mode/proc/equip_syndicate(mob/living/carbon/human/synd_mob, telecrystals = TRUE) + synd_mob.set_species(/datum/species/human) //Plasamen burn up otherwise, and lizards are vulnerable to asimov AIs + + if(telecrystals) + synd_mob.equipOutfit(/datum/outfit/syndicate) + else + synd_mob.equipOutfit(/datum/outfit/syndicate/no_crystals) + return TRUE + /datum/game_mode/nuclear/OnNukeExplosion(off_station) ..() nukes_left-- + var/obj/docking_port/mobile/Shuttle = SSshuttle.getShuttle("syndicate") + syndies_didnt_escape = (Shuttle && (Shuttle.z == ZLEVEL_CENTCOM || Shuttle.z == ZLEVEL_TRANSIT)) ? 0 : 1 + nuke_off_station = off_station /datum/game_mode/nuclear/check_win() if (nukes_left == 0) @@ -52,8 +154,8 @@ return ..() /datum/game_mode/proc/are_operatives_dead() - for(var/datum/mind/operative_mind in get_antagonists(/datum/antagonist/nukeop)) - if(ishuman(operative_mind.current) && (operative_mind.current.stat != DEAD)) + for(var/datum/mind/operative_mind in syndicates) + if(ishuman(operative_mind.current) && (operative_mind.current.stat!=2)) return FALSE return TRUE @@ -62,55 +164,142 @@ return replacementmode.check_finished() if((SSshuttle.emergency.mode == SHUTTLE_ENDGAME) || station_was_nuked) return TRUE - if(nuke_team.operatives_dead()) + if(are_operatives_dead()) var/obj/machinery/nuclearbomb/N pass(N) //suppress unused warning if(N.bomb_set) //snaaaaaaaaaake! It's not over yet! return FALSE //its a static var btw ..() -/datum/game_mode/nuclear/set_round_result() +/datum/game_mode/nuclear/declare_completion() + var/disk_rescued = 1 + for(var/obj/item/disk/nuclear/D in GLOB.poi_list) + if(!D.onCentCom()) + disk_rescued = 0 + break + var/crew_evacuated = (SSshuttle.emergency.mode == SHUTTLE_ENDGAME) + + if(nuke_off_station == NUKE_SYNDICATE_BASE) + SSticker.mode_result = "loss - syndicate nuked - disk secured" + to_chat(world, "Humiliating Syndicate Defeat") + to_chat(world, "The crew of [station_name()] gave [syndicate_name()] operatives back their bomb! The syndicate base was destroyed! Next time, don't lose the nuke!") + + SSticker.news_report = NUKE_SYNDICATE_BASE + + else if(!disk_rescued && station_was_nuked && !syndies_didnt_escape) + SSticker.mode_result = "win - syndicate nuke" + to_chat(world, "Syndicate Major Victory!") + to_chat(world, "[syndicate_name()] operatives have destroyed [station_name()]!") + + SSticker.news_report = STATION_NUKED + + else if (!disk_rescued && station_was_nuked && syndies_didnt_escape) + SSticker.mode_result = "halfwin - syndicate nuke - did not evacuate in time" + to_chat(world, "Total Annihilation") + to_chat(world, "[syndicate_name()] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion. Next time, don't lose the disk!") + + SSticker.news_report = STATION_NUKED + + else if (!disk_rescued && !station_was_nuked && nuke_off_station && !syndies_didnt_escape) + SSticker.mode_result = "halfwin - blew wrong station" + to_chat(world, "Crew Minor Victory") + to_chat(world, "[syndicate_name()] operatives secured the authentication disk but blew up something that wasn't [station_name()]. Next time, don't do that!") + + SSticker.news_report = NUKE_MISS + + else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape) + SSticker.mode_result = "halfwin - blew wrong station - did not evacuate in time" + to_chat(world, "[syndicate_name()] operatives have earned Darwin Award!") + to_chat(world, "[syndicate_name()] operatives blew up something that wasn't [station_name()] and got caught in the explosion. Next time, don't do that!") + + SSticker.news_report = NUKE_MISS + + else if ((disk_rescued || SSshuttle.emergency.mode != SHUTTLE_ENDGAME) && are_operatives_dead()) + SSticker.mode_result = "loss - evacuation - disk secured - syndi team dead" + to_chat(world, "Crew Major Victory!") + to_chat(world, "The Research Staff has saved the disk and killed the [syndicate_name()] Operatives") + + SSticker.news_report = OPERATIVES_KILLED + + else if (disk_rescued) + SSticker.mode_result = "loss - evacuation - disk secured" + to_chat(world, "Crew Major Victory") + to_chat(world, "The Research Staff has saved the disk and stopped the [syndicate_name()] Operatives!") + + SSticker.news_report = OPERATIVES_KILLED + + else if (!disk_rescued && are_operatives_dead()) + SSticker.mode_result = "halfwin - evacuation - disk not secured" + to_chat(world, "Neutral Victory!") + to_chat(world, "The Research Staff failed to secure the authentication disk but did manage to kill most of the [syndicate_name()] Operatives!") + + SSticker.news_report = OPERATIVE_SKIRMISH + + else if (!disk_rescued && crew_evacuated) + SSticker.mode_result = "halfwin - detonation averted" + to_chat(world, "Syndicate Minor Victory!") + to_chat(world, "[syndicate_name()] operatives survived the assault but did not achieve the destruction of [station_name()]. Next time, don't lose the disk!") + + SSticker.news_report = OPERATIVE_SKIRMISH + + else if (!disk_rescued && !crew_evacuated) + SSticker.mode_result = "halfwin - interrupted" + to_chat(world, "Neutral Victory") + to_chat(world, "Round was mysteriously interrupted!") + + SSticker.news_report = OPERATIVE_SKIRMISH + ..() - var result = nuke_team.get_result() - switch(result) - if(NUKE_RESULT_FLUKE) - SSticker.mode_result = "loss - syndicate nuked - disk secured" - SSticker.news_report = NUKE_SYNDICATE_BASE - if(NUKE_RESULT_NUKE_WIN) - SSticker.mode_result = "win - syndicate nuke" - SSticker.news_report = STATION_NUKED - if(NUKE_RESULT_NOSURVIVORS) - SSticker.mode_result = "halfwin - syndicate nuke - did not evacuate in time" - SSticker.news_report = STATION_NUKED - if(NUKE_RESULT_WRONG_STATION) - SSticker.mode_result = "halfwin - blew wrong station" - SSticker.news_report = NUKE_MISS - if(NUKE_RESULT_WRONG_STATION_DEAD) - SSticker.mode_result = "halfwin - blew wrong station - did not evacuate in time" - SSticker.news_report = NUKE_MISS - if(NUKE_RESULT_CREW_WIN_SYNDIES_DEAD) - SSticker.mode_result = "loss - evacuation - disk secured - syndi team dead" - SSticker.news_report = OPERATIVES_KILLED - if(NUKE_RESULT_CREW_WIN) - SSticker.mode_result = "loss - evacuation - disk secured" - SSticker.news_report = OPERATIVES_KILLED - if(NUKE_RESULT_DISK_LOST) - SSticker.mode_result = "halfwin - evacuation - disk not secured" - SSticker.news_report = OPERATIVE_SKIRMISH - if(NUKE_RESULT_DISK_STOLEN) - SSticker.mode_result = "halfwin - detonation averted" - SSticker.news_report = OPERATIVE_SKIRMISH - else - SSticker.mode_result = "halfwin - interrupted" - SSticker.news_report = OPERATIVE_SKIRMISH + return /datum/game_mode/nuclear/generate_report() return "One of Central Command's trading routes was recently disrupted by a raid carried out by the Gorlex Marauders. They seemed to only be after one ship - a highly-sensitive \ transport containing a nuclear fission explosive, although it is useless without the proper code and authorization disk. While the code was likely found in minutes, the only disk that \ can activate this explosive is on your station. Ensure that it is protected at all times, and remain alert for possible intruders." +/datum/game_mode/proc/auto_declare_completion_nuclear() + if( syndicates.len || (SSticker && istype(SSticker.mode, /datum/game_mode/nuclear)) ) + var/text = "
The syndicate operatives were:" + var/purchases = "" + var/TC_uses = 0 + for(var/datum/mind/syndicate in syndicates) + text += printplayer(syndicate) + for(var/datum/component/uplink/H in GLOB.uplinks) + if(H.purchase_log) + purchases += H.purchase_log.generate_render() + else + stack_trace("WARNING: Uplink with no purchase_log in nuclear mode! Owner: [H.owner]") + text += "
" + text += "(Syndicates used [TC_uses] TC) [purchases]" + if(TC_uses == 0 && station_was_nuked && !are_operatives_dead()) + text += "[icon2html('icons/badass.dmi', world, "badass")]" + to_chat(world, text) + return TRUE + + +/proc/nukelastname(mob/M) //--All praise goes to NEO|Phyte, all blame goes to DH, and it was Cindi-Kate's idea. Also praise Urist for copypasta ho. + var/randomname = pick(GLOB.last_names) + var/newname = copytext(sanitize(input(M,"You are the nuke operative [pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord")]. Please choose a last name for your family.", "Name change",randomname)),1,MAX_NAME_LEN) + + if (!newname) + newname = randomname + + else + if (newname == "Unknown" || newname == "floor" || newname == "wall" || newname == "rwall" || newname == "_") + to_chat(M, "That name is reserved.") + return nukelastname(M) + + return capitalize(newname) + +/proc/NukeNameAssign(lastname,list/syndicates) + for(var/datum/mind/synd_mind in syndicates) + var/mob/living/carbon/human/H = synd_mind.current + synd_mind.name = H.dna.species.random_name(H.gender,0,lastname) + synd_mind.current.real_name = synd_mind.name + return + /proc/is_nuclear_operative(mob/M) - return M && istype(M) && M.mind && M.mind.has_antag_datum(/datum/antagonist/nukeop) + return M && istype(M) && M.mind && SSticker && SSticker.mode && M.mind in SSticker.mode.syndicates /datum/outfit/syndicate name = "Syndicate Operative - Basic" @@ -123,28 +312,18 @@ l_pocket = /obj/item/pinpointer/nuke/syndicate id = /obj/item/card/id/syndicate belt = /obj/item/gun/ballistic/automatic/pistol - backpack_contents = list(/obj/item/storage/box/syndie=1,\ - /obj/item/kitchen/knife/combat/survival) + backpack_contents = list(/obj/item/storage/box/syndie=1) var/tc = 25 - var/command_radio = FALSE - - -/datum/outfit/syndicate/leader - name = "Syndicate Leader - Basic" - id = /obj/item/card/id/syndicate/nuke_leader - r_hand = /obj/item/device/nuclear_challenge - command_radio = TRUE /datum/outfit/syndicate/no_crystals tc = 0 + /datum/outfit/syndicate/post_equip(mob/living/carbon/human/H) var/obj/item/device/radio/R = H.ears - R.set_frequency(FREQ_SYNDICATE) - R.freqlock = TRUE - if(command_radio) - R.command = TRUE + R.set_frequency(GLOB.SYND_FREQ) + R.freqlock = 1 if(tc) var/obj/item/device/radio/uplink/nuclear/U = new(H, H.key, tc) @@ -169,5 +348,4 @@ r_hand = /obj/item/gun/ballistic/automatic/shotgun/bulldog backpack_contents = list(/obj/item/storage/box/syndie=1,\ /obj/item/tank/jetpack/oxygen/harness=1,\ - /obj/item/gun/ballistic/automatic/pistol=1,\ - /obj/item/kitchen/knife/combat/survival) + /obj/item/gun/ballistic/automatic/pistol=1) diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index 94d8478cbb..908ecd797f 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -77,16 +77,16 @@ icon = 'icons/obj/machines/nuke_terminal.dmi' icon_state = "nuclearbomb_base" anchored = TRUE //stops it being moved + use_tag = TRUE /obj/machinery/nuclearbomb/syndicate - use_tag = TRUE //ui_style = "syndicate" // actually the nuke op bomb is a stole nt bomb /obj/machinery/nuclearbomb/syndicate/get_cinematic_type(off_station) var/datum/game_mode/nuclear/NM = SSticker.mode switch(off_station) if(0) - if(istype(NM) && !NM.nuke_team.syndies_escaped()) + if(istype(NM) && NM.syndies_didnt_escape) return CINEMATIC_ANNIHILATION else return CINEMATIC_NUKE_WIN diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm index 7047729294..2df573dc6d 100644 --- a/code/game/gamemodes/nuclear/pinpointer.dm +++ b/code/game/gamemodes/nuclear/pinpointer.dm @@ -71,9 +71,9 @@ target = null var/list/possible_targets = list() var/turf/here = get_turf(src) - for(var/V in get_antagonists(/datum/antagonist/nukeop)) + for(var/V in SSticker.mode.syndicates) var/datum/mind/M = V - if(ishuman(M.current) && M.current.stat != DEAD) + if(M.current && M.current.stat != DEAD) possible_targets |= M.current var/mob/living/closest_operative = get_closest_atom(/mob/living/carbon/human, possible_targets, here) if(closest_operative) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 0c25895ab3..46f96961c9 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -47,9 +47,9 @@ . = list() for(var/V in GLOB.data_core.locked) var/datum/data/record/R = V - var/datum/mind/M = R.fields["mindref"] - if(M) - . += M + var/mob/M = R.fields["reference"] + if(M && M.mind) + . += M.mind /datum/objective/proc/find_target() var/list/datum/mind/owners = get_owners() @@ -537,25 +537,25 @@ GLOBAL_LIST_EMPTY(possible_items_special) var/captured_amount = 0 var/area/centcom/holding/A = locate() in GLOB.sortedAreas for(var/mob/living/carbon/human/M in A)//Humans. - if(M.stat == DEAD)//Dead folks are worth less. + if(M.stat==2)//Dead folks are worth less. captured_amount+=0.5 continue captured_amount+=1 for(var/mob/living/carbon/monkey/M in A)//Monkeys are almost worthless, you failure. captured_amount+=0.1 for(var/mob/living/carbon/alien/larva/M in A)//Larva are important for research. - if(M.stat == DEAD) + if(M.stat==2) captured_amount+=0.5 continue captured_amount+=1 for(var/mob/living/carbon/alien/humanoid/M in A)//Aliens are worth twice as much as humans. if(istype(M, /mob/living/carbon/alien/humanoid/royal/queen))//Queens are worth three times as much as humans. - if(M.stat == DEAD) + if(M.stat==2) captured_amount+=1.5 else captured_amount+=3 continue - if(M.stat == DEAD) + if(M.stat==2) captured_amount+=1 continue captured_amount+=2 diff --git a/code/game/gamemodes/objective_team.dm b/code/game/gamemodes/objective_team.dm index 1483f356d2..7789a167c7 100644 --- a/code/game/gamemodes/objective_team.dm +++ b/code/game/gamemodes/objective_team.dm @@ -3,7 +3,6 @@ var/list/datum/mind/members = list() var/name = "team" var/member_name = "member" - var/list/objectives = list() //common objectives, these won't be added or removed automatically, subtypes handle this, this is here for bookkeeping purposes. /datum/objective_team/New(starting_members) . = ..() @@ -13,6 +12,7 @@ add_member(M) else add_member(starting_members) + members += starting_members /datum/objective_team/proc/is_solo() return members.len == 1 @@ -21,14 +21,4 @@ members |= new_member /datum/objective_team/proc/remove_member(datum/mind/member) - members -= member - -//Display members/victory/failure/objectives for the team -/datum/objective_team/proc/roundend_report() - var/list/report = list() - - report += "[name]:" - report += "The [member_name]s were:" - report += printplayerlist(members) - - return report.Join("
") \ No newline at end of file + members -= member \ No newline at end of file diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index cbfdb98c69..4fa9532b42 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -169,22 +169,62 @@ return FALSE return TRUE - -/datum/game_mode/revolution/set_round_result() - ..() +////////////////////////////////////////////////////////////////////// +//Announces the end of the game with all relavent information stated// +////////////////////////////////////////////////////////////////////// +/datum/game_mode/revolution/declare_completion() if(finished == 1) SSticker.mode_result = "win - heads killed" + to_chat(world, "The heads of staff were killed or exiled! The revolutionaries win!") + SSticker.news_report = REVS_WIN + else if(finished == 2) SSticker.mode_result = "loss - rev heads killed" - SSticker.news_report = REVS_LOSE + to_chat(world, "The heads of staff managed to stop the revolution!") -//TODO What should be displayed for revs in non-rev rounds -/datum/game_mode/revolution/special_report() - if(finished == 1) - return "The heads of staff were killed or exiled! The revolutionaries win!" - else if(finished == 2) - return "The heads of staff managed to stop the revolution!" + SSticker.news_report = REVS_LOSE + ..() + return TRUE + +/datum/game_mode/proc/auto_declare_completion_revolution() + var/list/targets = list() + var/list/datum/mind/headrevs = get_antagonists(/datum/antagonist/rev/head) + var/list/datum/mind/revs = get_antagonists(/datum/antagonist/rev,TRUE) + if(headrevs.len) + var/num_revs = 0 + var/num_survivors = 0 + for(var/mob/living/carbon/survivor in GLOB.alive_mob_list) + if(survivor.ckey) + num_survivors++ + if(survivor.mind) + if(is_revolutionary(survivor)) + num_revs++ + if(num_survivors) + to_chat(world, "[GLOB.TAB]Command's Approval Rating: [100 - round((num_revs/num_survivors)*100, 0.1)]%" ) + var/text = "
The head revolutionaries were:" + for(var/datum/mind/headrev in headrevs) + text += printplayer(headrev, 1) + text += "
" + to_chat(world, text) + + if(revs.len) + var/text = "
The revolutionaries were:" + for(var/datum/mind/rev in revs) + text += printplayer(rev, 1) + text += "
" + to_chat(world, text) + + if(revs.len || headrevs.len) + var/text = "
The heads of staff were:" + var/list/heads = SSjob.get_all_heads() + for(var/datum/mind/head in heads) + var/target = (head in targets) + if(target) + text += "Target" + text += printplayer(head, 1) + text += "
" + to_chat(world, text) /datum/game_mode/revolution/generate_report() return "Employee unrest has spiked in recent weeks, with several attempted mutinies on heads of staff. Some crew have been observed using flashbulb devices to blind their colleagues, \ diff --git a/code/game/gamemodes/sandbox/h_sandbox.dm b/code/game/gamemodes/sandbox/h_sandbox.dm index 13b4234622..101a33e551 100644 --- a/code/game/gamemodes/sandbox/h_sandbox.dm +++ b/code/game/gamemodes/sandbox/h_sandbox.dm @@ -27,7 +27,7 @@ GLOBAL_VAR_INIT(hsboxspawn, TRUE) //items that shouldn't spawn on the floor because they would bug or act weird var/global/list/spawn_forbidden = list( /obj/item/tk_grab, /obj/item/implant, // not implanter, the actual thing that is inside you - /obj/item/assembly, /obj/item/device/onetankbomb, /obj/item/device/pda/ai, + /obj/item/assembly, /obj/item/device/onetankbomb, /obj/item/radio, /obj/item/device/pda/ai, /obj/item/smallDelivery, /obj/item/projectile, /obj/item/borg/sight, /obj/item/borg/stun, /obj/item/robot_module) diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 42c96cb5c0..7c93a89a36 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -27,7 +27,6 @@ var/traitors_possible = 4 //hard limit on traitors if scaling is turned off var/num_modifier = 0 // Used for gamemodes, that are a child of traitor, that need more than the usual. var/antag_datum = ANTAG_DATUM_TRAITOR //what type of antag to create - var/traitors_required = TRUE //Will allow no traitors /datum/game_mode/traitor/pre_setup() @@ -56,7 +55,7 @@ log_game("[traitor.key] (ckey) has been selected as a [traitor_name]") antag_candidates.Remove(traitor) - return !traitors_required || pre_traitors.len > 0 + return pre_traitors.len > 0 /datum/game_mode/traitor/post_setup() @@ -86,10 +85,80 @@ new_antag.should_specialise = TRUE character.add_antag_datum(new_antag) + + +/datum/game_mode/traitor/declare_completion() + ..() + return//Traitors will be checked as part of check_extra_completion. Leaving this here as a reminder. + + +/datum/game_mode/proc/auto_declare_completion_traitor() + if(traitors.len) + var/text = "
The [traitor_name]s were:" + for(var/datum/mind/traitor in traitors) + var/traitorwin = TRUE + + text += printplayer(traitor) + + var/TC_uses = 0 + var/uplink_true = FALSE + var/purchases = "" + for(var/datum/component/uplink/H in GLOB.uplinks) + if(H && H.owner && H.owner == traitor.key) + TC_uses += H.spent_telecrystals + uplink_true = TRUE + purchases += H.purchase_log.generate_render(FALSE) + + var/objectives = "" + if(traitor.objectives.len)//If the traitor had no objectives, don't need to process this. + var/count = 1 + for(var/datum/objective/objective in traitor.objectives) + if(objective.check_completion()) + objectives += "
Objective #[count]: [objective.explanation_text] Success! [istype(objective, /datum/objective/crew) ? "(Optional)" : ""]" + SSblackbox.record_feedback("nested tally", "traitor_objective", 1, list("[objective.type]", "SUCCESS")) + else + objectives += "
Objective #[count]: [objective.explanation_text] Fail. [istype(objective, /datum/objective/crew) ? "(Optional)" : ""]" + SSblackbox.record_feedback("nested tally", "traitor_objective", 1, list("[objective.type]", "FAIL")) + if(!(istype(objective, /datum/objective/crew))) + traitorwin = FALSE + count++ + + if(uplink_true) + text += " (used [TC_uses] TC) [purchases]" + if(TC_uses==0 && traitorwin) + var/static/icon/badass = icon('icons/badass.dmi', "badass") + text += "[icon2html(badass, world)]" + + text += objectives + + var/special_role_text + if(traitor.special_role) + special_role_text = lowertext(traitor.special_role) + else + special_role_text = "antagonist" + + + if(traitorwin) + text += "
The [special_role_text] was successful!" + SSblackbox.record_feedback("tally", "traitor_success", 1, "SUCCESS") + else + text += "
The [special_role_text] has failed!" + SSblackbox.record_feedback("tally", "traitor_success", 1, "FAIL") + SEND_SOUND(traitor.current, 'sound/ambience/ambifailure.ogg') + + text += "
" + + text += "
The code phrases were: [GLOB.syndicate_code_phrase]
\ + The code responses were: [GLOB.syndicate_code_response]
" + to_chat(world, text) + + return TRUE + /datum/game_mode/traitor/generate_report() return "Although more specific threats are commonplace, you should always remain vigilant for Syndicate agents aboard your station. Syndicate communications have implied that many \ Nanotrasen employees are Syndicate agents with hidden memories that may be activated at a moment's notice, so it's possible that these agents might not even know their positions." + /datum/game_mode/proc/update_traitor_icons_added(datum/mind/traitor_mind) var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR] traitorhud.join_hud(traitor_mind.current) diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm index 21de0fc2f9..c59ad05cd5 100644 --- a/code/game/gamemodes/wizard/artefact.dm +++ b/code/game/gamemodes/wizard/artefact.dm @@ -213,7 +213,7 @@ righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' var/mob/living/carbon/human/target = null var/list/mob/living/carbon/human/possible = list() - var/obj/item/linked_item = null + var/obj/item/link = null var/cooldown_time = 30 //3s var/cooldown = 0 max_integrity = 10 @@ -237,10 +237,10 @@ cooldown = world.time +cooldown_time return - if(!linked_item) + if(!link) if(I.loc == user && istype(I) && I.w_class <= WEIGHT_CLASS_SMALL) if (user.transferItemToLoc(I,src)) - linked_item = I + link = I to_chat(user, "You attach [I] to the doll.") update_targets() @@ -255,11 +255,11 @@ return if(user.zone_selected == "chest") - if(linked_item) + if(link) target = null - linked_item.forceMove(drop_location()) - to_chat(user, "You remove the [linked_item] from the doll.") - linked_item = null + link.loc = get_turf(src) + to_chat(user, "You remove the [link] from the doll.") + link = null update_targets() return @@ -291,10 +291,10 @@ /obj/item/voodoo/proc/update_targets() possible = list() - if(!linked_item) + if(!link) return for(var/mob/living/carbon/human/H in GLOB.alive_mob_list) - if(md5(H.dna.uni_identity) in linked_item.fingerprints) + if(md5(H.dna.uni_identity) in link.fingerprints) possible |= H /obj/item/voodoo/proc/GiveHint(mob/victim,force=0) diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index 8b80b9ab69..6b6780e6be 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -64,6 +64,7 @@ to_chat(user, "\"Come now, do not capture your bretheren's soul.\"") return add_logs(user, M, "captured [M.name]'s soul", src) + transfer_soul("VICTIM", M, user) ///////////////////Options for using captured souls/////////////////////////////////////// @@ -141,8 +142,7 @@ if("VICTIM") var/mob/living/carbon/human/T = target - var/datum/antagonist/cult/C = user.mind.has_antag_datum(/datum/antagonist/cult,TRUE) - if(C && C.cult_team.is_sacrifice_target(T.mind)) + if(is_sacrifice_target(T.mind)) if(iscultist(user)) to_chat(user, "\"This soul is mine. SACRIFICE THEM!\"") else diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index 1d423802d1..5302ebd39b 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -47,7 +47,7 @@ for(var/datum/mind/wizard in wizards) if(isliving(wizard.current) && wizard.current.stat!=DEAD) return FALSE - + for(var/obj/item/phylactery/P in GLOB.poi_list) //TODO : IsProperlyDead() if(P.mind && P.mind.has_antag_datum(/datum/antagonist/wizard)) return FALSE @@ -55,19 +55,68 @@ if(SSevents.wizardmode) //If summon events was active, turn it off SSevents.toggleWizardmode() SSevents.resetFrequency() - + return TRUE -/datum/game_mode/wizard/set_round_result() - ..() +/datum/game_mode/wizard/declare_completion() if(finished) SSticker.mode_result = "loss - wizard killed" + to_chat(world, "The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!") + SSticker.news_report = WIZARD_KILLED + ..() + return 1 -/datum/game_mode/wizard/special_report() - if(finished) - return "The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!" +/datum/game_mode/proc/auto_declare_completion_wizard() + if(wizards.len) + var/text = "
the wizards/witches were:" + + for(var/datum/mind/wizard in wizards) + + text += "
[wizard.key] was [wizard.name] (" + if(wizard.current) + if(wizard.current.stat == DEAD) + text += "died" + else + text += "survived" + if(wizard.current.real_name != wizard.name) + text += " as [wizard.current.real_name]" + else + text += "body destroyed" + text += ")" + + var/count = 1 + var/wizardwin = 1 + for(var/datum/objective/objective in wizard.objectives) + if(objective.check_completion()) + text += "
Objective #[count]: [objective.explanation_text] Success! [istype(objective, /datum/objective/crew) ? "(Optional)" : ""]" + SSblackbox.record_feedback("nested tally", "wizard_objective", 1, list("[objective.type]", "SUCCESS")) + else + text += "
Objective #[count]: [objective.explanation_text] Fail. [istype(objective, /datum/objective/crew) ? "(Optional)" : ""]" + SSblackbox.record_feedback("nested tally", "wizard_objective", 1, list("[objective.type]", "FAIL")) + if(!(istype(objective, /datum/objective/crew))) + wizardwin = 0 + count++ + + if(wizard.current && wizardwin) + text += "
The wizard was successful!" + SSblackbox.record_feedback("tally", "wizard_success", 1, "SUCCESS") + else + text += "
The wizard has failed!" + SSblackbox.record_feedback("tally", "wizard_success", 1, "FAIL") + if(wizard.spell_list.len>0) + text += "
[wizard.name] used the following spells: " + var/i = 1 + for(var/obj/effect/proc_holder/spell/S in wizard.spell_list) + text += "[S.name]" + if(wizard.spell_list.len > i) + text += ", " + i++ + text += "
" + + to_chat(world, text) + return 1 //returns whether the mob is a wizard (or apprentice) /proc/iswizard(mob/living/M) return M.mind && M.mind.has_antag_datum(/datum/antagonist/wizard,TRUE) diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm index 6156ee1d86..61d5627354 100644 --- a/code/game/machinery/PDApainter.dm +++ b/code/game/machinery/PDApainter.dm @@ -134,7 +134,7 @@ return if(storedpda) - storedpda.forceMove(drop_location()) + storedpda.loc = get_turf(src.loc) storedpda = null update_icon() else diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 14a4ed7f94..61a5d7271d 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -15,7 +15,7 @@ state_open = TRUE circuit = /obj/item/circuitboard/machine/sleeper var/efficiency = 1 - var/min_health = -25 + var/min_health = 30 var/list/available_chems var/controls_inside = FALSE var/list/possible_chems = list( @@ -42,7 +42,7 @@ I += M.rating efficiency = initial(efficiency)* E - min_health = initial(min_health) * E + min_health = initial(min_health) - (10*E) available_chems = list() for(var/i in 1 to I) available_chems |= possible_chems[i] diff --git a/code/game/machinery/airlock_control.dm b/code/game/machinery/airlock_control.dm index 2170636f43..01651e6e08 100644 --- a/code/game/machinery/airlock_control.dm +++ b/code/game/machinery/airlock_control.dm @@ -8,7 +8,7 @@ /obj/machinery/door/airlock/receive_signal(datum/signal/signal) - if(!signal) + if(!signal || signal.encryption) return if(id_tag != signal.data["tag"] || !signal.data["command"]) @@ -52,13 +52,15 @@ /obj/machinery/door/airlock/proc/send_status() if(radio_connection) - var/datum/signal/signal = new(list( - "tag" = id_tag, - "timestamp" = world.time, - "door_status" = density ? "closed" : "open", - "lock_status" = locked ? "locked" : "unlocked" - )) - radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) + var/datum/signal/signal = new + signal.transmission_method = 1 //radio signal + signal.data["tag"] = id_tag + signal.data["timestamp"] = world.time + + signal.data["door_status"] = density?("closed"):("open") + signal.data["lock_status"] = locked?("locked"):("unlocked") + + radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = GLOB.RADIO_AIRLOCK) /obj/machinery/door/airlock/open(surpress_send) @@ -77,10 +79,10 @@ SSradio.remove_object(src, frequency) if(new_frequency) frequency = new_frequency - radio_connection = SSradio.add_object(src, frequency, RADIO_AIRLOCK) + radio_connection = SSradio.add_object(src, frequency, GLOB.RADIO_AIRLOCK) /obj/machinery/door/airlock/Destroy() - if(frequency) + if(frequency && SSradio) SSradio.remove_object(src,frequency) return ..() @@ -95,7 +97,7 @@ var/id_tag var/master_tag - var/frequency = FREQ_AIRLOCK_CONTROL + var/frequency = 1449 var/datum/radio_frequency/radio_connection @@ -113,34 +115,36 @@ icon_state = "airlock_sensor_off" /obj/machinery/airlock_sensor/attack_hand(mob/user) - var/datum/signal/signal = new(list( - "tag" = master_tag, - "command" = "cycle" - )) + var/datum/signal/signal = new + signal.transmission_method = 1 //radio signal + signal.data["tag"] = master_tag + signal.data["command"] = "cycle" - radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) + radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = GLOB.RADIO_AIRLOCK) flick("airlock_sensor_cycle", src) /obj/machinery/airlock_sensor/process() if(on) + var/datum/signal/signal = new + signal.transmission_method = 1 //radio signal + signal.data["tag"] = id_tag + signal.data["timestamp"] = world.time + var/datum/gas_mixture/air_sample = return_air() + var/pressure = round(air_sample.return_pressure(),0.1) alert = (pressure < ONE_ATMOSPHERE*0.8) - var/datum/signal/signal = new(list( - "tag" = id_tag, - "timestamp" = world.time, - "pressure" = num2text(pressure) - )) + signal.data["pressure"] = num2text(pressure) - radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK) + radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = GLOB.RADIO_AIRLOCK) update_icon() /obj/machinery/airlock_sensor/proc/set_frequency(new_frequency) SSradio.remove_object(src, frequency) frequency = new_frequency - radio_connection = SSradio.add_object(src, frequency, RADIO_AIRLOCK) + radio_connection = SSradio.add_object(src, frequency, GLOB.RADIO_AIRLOCK) /obj/machinery/airlock_sensor/Initialize() . = ..() @@ -148,4 +152,4 @@ /obj/machinery/airlock_sensor/Destroy() SSradio.remove_object(src,frequency) - return ..() \ No newline at end of file + return ..() diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index b216d1752f..4cd7e7f0fe 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -53,7 +53,7 @@ radio = new(src) radio.keyslot = new radio_key - radio.subspace_transmission = TRUE + radio.subspace_transmission = 1 radio.canhear_range = 0 radio.recalculateChannels() diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 3b6e423d93..89a4e8b130 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -280,7 +280,7 @@ playsound(loc, 'sound/arcade/lose.ogg', 50, 1, extrarange = -3, falloff = 10) if(emagged) usr.gib() - SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "hp", (emagged ? "emagged":"normal"))) + SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "hp", (emagged ? "emagged":"normal"))) blocked = FALSE return diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm index 94f5e63afb..f5115c7e2a 100644 --- a/code/game/machinery/computer/atmos_alert.dm +++ b/code/game/machinery/computer/atmos_alert.dm @@ -6,7 +6,7 @@ icon_keyboard = "atmos_key" var/list/priority_alarms = list() var/list/minor_alarms = list() - var/receive_frequency = FREQ_ATMOS_ALARMS + var/receive_frequency = 1437 var/datum/radio_frequency/radio_connection light_color = LIGHT_COLOR_CYAN @@ -57,10 +57,10 @@ /obj/machinery/computer/atmos_alert/proc/set_frequency(new_frequency) SSradio.remove_object(src, receive_frequency) receive_frequency = new_frequency - radio_connection = SSradio.add_object(src, receive_frequency, RADIO_ATMOSIA) + radio_connection = SSradio.add_object(src, receive_frequency, GLOB.RADIO_ATMOSIA) /obj/machinery/computer/atmos_alert/receive_signal(datum/signal/signal) - if(!signal) + if(!signal || signal.encryption) return var/zone = signal.data["zone"] diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm index 968ebbf5cb..2d1d771203 100644 --- a/code/game/machinery/computer/atmos_control.dm +++ b/code/game/machinery/computer/atmos_control.dm @@ -11,7 +11,7 @@ var/on = TRUE var/id_tag - var/frequency = FREQ_ATMOS_STORAGE + var/frequency = 1441 var/datum/radio_frequency/radio_connection /obj/machinery/air_sensor/update_icon() @@ -19,29 +19,31 @@ /obj/machinery/air_sensor/process_atmos() if(on) + var/datum/signal/signal = new var/datum/gas_mixture/air_sample = return_air() - var/datum/signal/signal = new(list( + signal.transmission_method = 1 //radio signal + signal.data = list( "sigtype" = "status", "id_tag" = id_tag, "timestamp" = world.time, "pressure" = air_sample.return_pressure(), "temperature" = air_sample.temperature, "gases" = list() - )) + ) var/total_moles = air_sample.total_moles() if(total_moles) for(var/gas_id in air_sample.gases) var/gas_name = air_sample.gases[gas_id][GAS_META][META_GAS_NAME] signal.data["gases"][gas_name] = air_sample.gases[gas_id][MOLES] / total_moles * 100 - radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) + radio_connection.post_signal(src, signal, filter = GLOB.RADIO_ATMOSIA) /obj/machinery/air_sensor/proc/set_frequency(new_frequency) SSradio.remove_object(src, frequency) frequency = new_frequency - radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA) + radio_connection = SSradio.add_object(src, frequency, GLOB.RADIO_ATMOSIA) /obj/machinery/air_sensor/Initialize() . = ..() @@ -64,7 +66,7 @@ icon_keyboard = "atmos_key" circuit = /obj/item/circuitboard/computer/atmos_control - var/frequency = FREQ_ATMOS_STORAGE + var/frequency = 1441 var/list/sensors = list( "n2_sensor" = "Nitrogen Tank", "o2_sensor" = "Oxygen Tank", @@ -115,7 +117,7 @@ return data /obj/machinery/computer/atmos_control/receive_signal(datum/signal/signal) - if(!signal) + if(!signal || signal.encryption) return var/id_tag = signal.data["id_tag"] @@ -127,7 +129,7 @@ /obj/machinery/computer/atmos_control/proc/set_frequency(new_frequency) SSradio.remove_object(src, frequency) frequency = new_frequency - radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA) + radio_connection = SSradio.add_object(src, frequency, GLOB.RADIO_ATMOSIA) ///////////////////////////////////////////////////////////// // LARGE TANK CONTROL @@ -136,7 +138,7 @@ /obj/machinery/computer/atmos_control/tank var/input_tag var/output_tag - frequency = FREQ_ATMOS_STORAGE + frequency = 1441 circuit = /obj/item/circuitboard/computer/atmos_control/tank var/list/input_info @@ -145,7 +147,7 @@ // This hacky madness is the evidence of the fact that a lot of machines were never meant to be constructable, im so sorry you had to see this /obj/machinery/computer/atmos_control/tank/proc/reconnect(mob/user) var/list/IO = list() - var/datum/radio_frequency/freq = SSradio.return_frequency(FREQ_ATMOS_STORAGE) + var/datum/radio_frequency/freq = SSradio.return_frequency(1441) var/list/devices = freq.devices["_default"] for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices) var/list/text = splittext(U.id_tag, "_") @@ -192,7 +194,10 @@ /obj/machinery/computer/atmos_control/tank/ui_act(action, params) if(..() || !radio_connection) return - var/datum/signal/signal = new(list("sigtype" = "command")) + var/datum/signal/signal = new + signal.transmission_method = 1 + signal.source = src + signal.data = list("sigtype" = "command") switch(action) if("reconnect") reconnect(usr) @@ -209,10 +214,10 @@ target = Clamp(target, 0, 50 * ONE_ATMOSPHERE) signal.data += list("tag" = output_tag, "set_internal_pressure" = target) . = TRUE - radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) + radio_connection.post_signal(src, signal, filter = GLOB.RADIO_ATMOSIA) /obj/machinery/computer/atmos_control/tank/receive_signal(datum/signal/signal) - if(!signal) + if(!signal || signal.encryption) return var/id_tag = signal.data["tag"] @@ -222,4 +227,4 @@ else if(output_tag == id_tag) output_info = signal.data else - ..(signal) + ..(signal) \ No newline at end of file diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index f77de02d1a..6223011736 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -28,6 +28,7 @@ var/const/STATE_TOGGLE_EMERGENCY = 10 var/const/STATE_PURCHASE = 11 + var/status_display_freq = "1435" var/stat_msg1 var/stat_msg2 @@ -227,7 +228,7 @@ log_game("[key_name(usr)] answered [currmsg.title] comm message. Answer : [currmsg.answered]") if(currmsg) currmsg.answer_callback.Invoke() - + state = STATE_VIEWMESSAGE if("status") state = STATE_STATUSDISPLAY @@ -463,9 +464,8 @@ if (authenticated==2) dat += "

Captain Functions" dat += "
\[ Make a Captain's Announcement \]" - var/cross_servers_count = length(CONFIG_GET(keyed_string_list/cross_server)) - if(cross_servers_count) - dat += "
\[ Send a message to [cross_servers_count == 1 ? "an " : ""]allied station[cross_servers_count > 1 ? "s" : ""] \]" + if(CONFIG_GET(string/cross_server_address)) + dat += "
\[ Send a message to an allied station \]" if(SSmapping.config.allow_custom_shuttles) dat += "
\[ Purchase Shuttle \]" dat += "
\[ Change Alert Level \]" @@ -693,12 +693,16 @@ /obj/machinery/computer/communications/proc/post_status(command, data1, data2) - var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS) + var/datum/radio_frequency/frequency = SSradio.return_frequency(1435) if(!frequency) return - var/datum/signal/status_signal = new(list("command" = command)) + var/datum/signal/status_signal = new + status_signal.source = src + status_signal.transmission_method = 1 + status_signal.data["command"] = command + switch(command) if("message") status_signal.data["msg1"] = data1 diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm index 2f446948da..a3ec6ba6ec 100644 --- a/code/game/machinery/computer/message.dm +++ b/code/game/machinery/computer/message.dm @@ -1,4 +1,3 @@ - // Allows you to monitor messages that passes the server. diff --git a/code/game/machinery/computer/telecrystalconsoles.dm b/code/game/machinery/computer/telecrystalconsoles.dm index e2b6f9152a..959253036b 100644 --- a/code/game/machinery/computer/telecrystalconsoles.dm +++ b/code/game/machinery/computer/telecrystalconsoles.dm @@ -51,7 +51,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E /obj/machinery/computer/telecrystals/uplinker/proc/ejectuplink() if(uplinkholder) - uplinkholder.forceMove(drop_location()) + uplinkholder.loc = get_turf(src.loc) uplinkholder = null update_icon() @@ -154,8 +154,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E /obj/machinery/computer/telecrystals/boss/proc/getDangerous()//This scales the TC assigned with the round population. ..() - var/list/nukeops = get_antagonists(/datum/antagonist/nukeop) - var/danger = GLOB.joined_player_list.len - nukeops.len + var/danger = GLOB.joined_player_list.len - SSticker.mode.syndicates.len danger = Ceiling(danger, 10) scaleTC(danger) @@ -224,4 +223,4 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E src.updateUsrDialog() return -#undef NUKESCALINGMODIFIER +#undef NUKESCALINGMODIFIER \ No newline at end of file diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm index fda8964609..7261c44fc5 100644 --- a/code/game/machinery/computer/teleporter.dm +++ b/code/game/machinery/computer/teleporter.dm @@ -161,8 +161,12 @@ var/list/areaindex = list() if(regime_set == "Teleporter") for(var/obj/item/device/radio/beacon/R in GLOB.teleportbeacons) - if(is_eligible(R)) - L[avoid_assoc_duplicate_keys(R.loc.loc.name, areaindex)] = R + var/turf/T = get_turf(R) + if(!T) + continue + if(T.z == ZLEVEL_CENTCOM || T.z > ZLEVEL_SPACEMAX) + continue + L[avoid_assoc_duplicate_keys(T.loc.name, areaindex)] = R for(var/obj/item/implant/tracking/I in GLOB.tracked_implants) if(!I.imp_in || !ismob(I.loc)) @@ -172,8 +176,12 @@ if(M.stat == DEAD) if(M.timeofdeath + 6000 < world.time) continue - if(is_eligible(I)) - L[avoid_assoc_duplicate_keys(M.real_name, areaindex)] = I + var/turf/T = get_turf(M) + if(!T) + continue + if(T.z == ZLEVEL_CENTCOM) + continue + L[avoid_assoc_duplicate_keys(M.real_name, areaindex)] = I var/desc = input("Please select a location to lock in.", "Locking Computer") as null|anything in L target = L[desc] @@ -184,8 +192,12 @@ to_chat(user, "No connected stations located.") return for(var/obj/machinery/teleport/station/R in S) - if(is_eligible(R)) - L[avoid_assoc_duplicate_keys(R.loc.loc.name, areaindex)] = R + var/turf/T = get_turf(R) + if(!T || !R.teleporter_hub || !R.teleporter_console) + continue + if(T.z == ZLEVEL_CENTCOM || T.z > ZLEVEL_SPACEMAX) + continue + L[avoid_assoc_duplicate_keys(T.loc.name, areaindex)] = R var/desc = input("Please select a station to lock in.", "Locking Computer") as null|anything in L target = L[desc] if(target) @@ -197,15 +209,4 @@ trg.teleporter_hub.update_icon() if(trg.teleporter_console) trg.teleporter_console.stat &= ~NOPOWER - trg.teleporter_console.update_icon() - -/obj/machinery/computer/teleporter/proc/is_eligible(atom/movable/AM) - var/turf/T = get_turf(AM) - if(!T) - return FALSE - if(T.z == ZLEVEL_CENTCOM || T.z > ZLEVEL_SPACEMAX) - return FALSE - var/area/A = get_area(T) - if(!A || A.noteleport) - return FALSE - return TRUE + trg.teleporter_console.update_icon() \ No newline at end of file diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index 97830393bd..99cbded13a 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -157,15 +157,15 @@ if(istype(P, /obj/item/crowbar)) playsound(src.loc, P.usesound, 50, 1) state = 2 - circuit.forceMove(drop_location()) + circuit.loc = src.loc components.Remove(circuit) circuit = null if(components.len == 0) to_chat(user, "You remove the circuit board.") else to_chat(user, "You remove the circuit board and other components.") - for(var/atom/movable/AM in components) - AM.forceMove(drop_location()) + for(var/atom/movable/A in components) + A.loc = src.loc desc = initial(desc) req_components = null components = null @@ -186,9 +186,9 @@ qdel(O) new_machine.component_parts = list() for(var/obj/O in src) - O.moveToNullspace() + O.loc = null new_machine.component_parts += O - circuit.moveToNullspace() + circuit.loc = null new_machine.RefreshParts() qdel(src) return @@ -257,5 +257,4 @@ for(var/X in components) var/obj/item/I = X I.forceMove(loc) - ..() diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 9be9d8db6b..d30554d258 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -209,27 +209,23 @@ /obj/machinery/door/airlock/narsie_act() var/turf/T = get_turf(src) var/runed = prob(20) - var/obj/machinery/door/airlock/cult/A if(glass) if(runed) - A = new/obj/machinery/door/airlock/cult/glass(T) + new/obj/machinery/door/airlock/cult/glass(T) else - A = new/obj/machinery/door/airlock/cult/unruned/glass(T) + new/obj/machinery/door/airlock/cult/unruned/glass(T) else if(runed) - A = new/obj/machinery/door/airlock/cult(T) + new/obj/machinery/door/airlock/cult(T) else - A = new/obj/machinery/door/airlock/cult/unruned(T) - A.name = name + new/obj/machinery/door/airlock/cult/unruned(T) qdel(src) /obj/machinery/door/airlock/ratvar_act() //Airlocks become pinion airlocks that only allow servants - var/obj/machinery/door/airlock/clockwork/A if(glass) - A = new/obj/machinery/door/airlock/clockwork/brass(get_turf(src)) + new/obj/machinery/door/airlock/clockwork/brass(get_turf(src)) else - A = new/obj/machinery/door/airlock/clockwork(get_turf(src)) - A.name = name + new/obj/machinery/door/airlock/clockwork(get_turf(src)) qdel(src) /obj/machinery/door/airlock/Destroy() @@ -1040,7 +1036,7 @@ panel_open = TRUE update_icon(AIRLOCK_OPENING) visible_message("[src]'s panel is blown off in a spray of deadly shrapnel!") - charge.forceMove(drop_location()) + charge.loc = get_turf(src) charge.ex_act(EXPLODE_DEVASTATE) detonated = 1 charge = null @@ -1344,7 +1340,7 @@ else ae = electronics electronics = null - ae.forceMove(drop_location()) + ae.loc = src.loc qdel(src) /obj/machinery/door/airlock/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) diff --git a/code/game/machinery/doors/alarmlock.dm b/code/game/machinery/doors/alarmlock.dm index 1649082138..5630b3ffb0 100644 --- a/code/game/machinery/doors/alarmlock.dm +++ b/code/game/machinery/doors/alarmlock.dm @@ -7,7 +7,7 @@ glass = TRUE var/datum/radio_frequency/air_connection - var/air_frequency = FREQ_ATMOS_ALARMS + var/air_frequency = 1437 autoclose = FALSE /obj/machinery/door/airlock/alarmlock/New() @@ -22,7 +22,7 @@ /obj/machinery/door/airlock/alarmlock/Initialize() . = ..() SSradio.remove_object(src, air_frequency) - air_connection = SSradio.add_object(src, air_frequency, RADIO_TO_AIRALARM) + air_connection = SSradio.add_object(src, air_frequency, GLOB.RADIO_TO_AIRALARM) open() /obj/machinery/door/airlock/alarmlock/receive_signal(datum/signal/signal) @@ -41,4 +41,4 @@ close() if("minor", "clear") autoclose = FALSE - open() \ No newline at end of file + open() diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index 13cd90210c..4c0d4a1804 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -112,8 +112,8 @@ return 0 if(!forced) - Radio.set_frequency(FREQ_SECURITY) - Radio.talk_into(src, "Timer has expired. Releasing prisoner.", FREQ_SECURITY) + Radio.set_frequency(GLOB.SEC_FREQ) + Radio.talk_into(src, "Timer has expired. Releasing prisoner.", GLOB.SEC_FREQ, get_default_language()) timing = FALSE activation_time = null diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 0b3a51466d..30ae436289 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -96,7 +96,7 @@ /obj/machinery/door/Move() var/turf/T = loc - . = ..() + ..() move_update_air(T) /obj/machinery/door/CanPass(atom/movable/mover, turf/target) diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index bd98e687b4..fd66892048 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -1,66 +1,66 @@ -/obj/machinery/door/poddoor - name = "blast door" - desc = "A heavy duty blast door that opens mechanically." - icon = 'icons/obj/doors/blastdoor.dmi' - icon_state = "closed" - var/id = 1 +/obj/machinery/door/poddoor + name = "blast door" + desc = "A heavy duty blast door that opens mechanically." + icon = 'icons/obj/doors/blastdoor.dmi' + icon_state = "closed" + var/id = 1 sub_door = TRUE - explosion_block = 3 + explosion_block = 3 heat_proof = TRUE safe = FALSE - max_integrity = 600 - armor = list(melee = 50, bullet = 100, laser = 100, energy = 100, bomb = 50, bio = 100, rad = 100, fire = 100, acid = 70) - resistance_flags = FIRE_PROOF - damage_deflection = 70 - -/obj/machinery/door/poddoor/preopen - icon_state = "open" + max_integrity = 600 + armor = list(melee = 50, bullet = 100, laser = 100, energy = 100, bomb = 50, bio = 100, rad = 100, fire = 100, acid = 70) + resistance_flags = FIRE_PROOF + damage_deflection = 70 + +/obj/machinery/door/poddoor/preopen + icon_state = "open" density = FALSE - opacity = 0 - -/obj/machinery/door/poddoor/ert - desc = "A heavy duty blast door that only opens for dire emergencies." - -//special poddoors that open when emergency shuttle docks at centcom -/obj/machinery/door/poddoor/shuttledock - var/checkdir = 4 //door won't open if turf in this dir is `turftype` - var/turftype = /turf/open/space - -/obj/machinery/door/poddoor/shuttledock/proc/check() - var/turf/T = get_step(src, checkdir) - if(!istype(T, turftype)) - INVOKE_ASYNC(src, .proc/open) - else - INVOKE_ASYNC(src, .proc/close) - + opacity = 0 + +/obj/machinery/door/poddoor/ert + desc = "A heavy duty blast door that only opens for dire emergencies." + +//special poddoors that open when emergency shuttle docks at centcom +/obj/machinery/door/poddoor/shuttledock + var/checkdir = 4 //door won't open if turf in this dir is `turftype` + var/turftype = /turf/open/space + +/obj/machinery/door/poddoor/shuttledock/proc/check() + var/turf/T = get_step(src, checkdir) + if(!istype(T, turftype)) + INVOKE_ASYNC(src, .proc/open) + else + INVOKE_ASYNC(src, .proc/close) + /obj/machinery/door/poddoor/CollidedWith(atom/movable/AM) - if(density) - return 0 - else - return ..() - -//"BLAST" doors are obviously stronger than regular doors when it comes to BLASTS. -/obj/machinery/door/poddoor/ex_act(severity, target) - if(severity == 3) - return - ..() - -/obj/machinery/door/poddoor/do_animate(animation) - switch(animation) - if("opening") - flick("opening", src) - if("closing") - flick("closing", src) - -/obj/machinery/door/poddoor/update_icon() - if(density) - icon_state = "closed" - else - icon_state = "open" - -/obj/machinery/door/poddoor/try_to_activate_door(mob/user) - return - -/obj/machinery/door/poddoor/try_to_crowbar(obj/item/I, mob/user) - if(stat & NOPOWER) - open(1) + if(density) + return 0 + else + return ..() + +//"BLAST" doors are obviously stronger than regular doors when it comes to BLASTS. +/obj/machinery/door/poddoor/ex_act(severity, target) + if(severity == 3) + return + ..() + +/obj/machinery/door/poddoor/do_animate(animation) + switch(animation) + if("opening") + flick("opening", src) + if("closing") + flick("closing", src) + +/obj/machinery/door/poddoor/update_icon() + if(density) + icon_state = "closed" + else + icon_state = "open" + +/obj/machinery/door/poddoor/try_to_activate_door(mob/user) + return + +/obj/machinery/door/poddoor/try_to_crowbar(obj/item/I, mob/user) + if(stat & NOPOWER) + open(1) diff --git a/code/game/machinery/doors/shutters.dm b/code/game/machinery/doors/shutters.dm index 77267a49a4..0cd33b1925 100644 --- a/code/game/machinery/doors/shutters.dm +++ b/code/game/machinery/doors/shutters.dm @@ -26,4 +26,4 @@ /obj/machinery/door/poddoor/shutters/close(ignorepower = 0) ..() - layer = CLOSED_DOOR_LAYER \ No newline at end of file + layer = CLOSED_DOOR_LAYER diff --git a/code/game/machinery/doors/unpowered.dm b/code/game/machinery/doors/unpowered.dm index 2960335813..4b7ec4b3dd 100644 --- a/code/game/machinery/doors/unpowered.dm +++ b/code/game/machinery/doors/unpowered.dm @@ -1,25 +1,25 @@ -/obj/machinery/door/unpowered - +/obj/machinery/door/unpowered + /obj/machinery/door/unpowered/CollidedWith(atom/movable/AM) - if(src.locked) - return - ..() - return - - -/obj/machinery/door/unpowered/attackby(obj/item/I, mob/user, params) - if(locked) - return - else - return ..() - -/obj/machinery/door/unpowered/emag_act() - return - -/obj/machinery/door/unpowered/shuttle - icon = 'icons/turf/shuttle.dmi' - name = "door" - icon_state = "door1" - opacity = 1 + if(src.locked) + return + ..() + return + + +/obj/machinery/door/unpowered/attackby(obj/item/I, mob/user, params) + if(locked) + return + else + return ..() + +/obj/machinery/door/unpowered/emag_act() + return + +/obj/machinery/door/unpowered/shuttle + icon = 'icons/turf/shuttle.dmi' + name = "door" + icon_state = "door1" + opacity = 1 density = TRUE explosion_block = 1 \ No newline at end of file diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index bd1a553863..2313afec3b 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -192,8 +192,7 @@ add_atom_colour("#7D1919", FIXED_COLOUR_PRIORITY) /obj/machinery/door/window/ratvar_act() - var/obj/machinery/door/window/clockwork/C = new(loc, dir) - C.name = name + new/obj/machinery/door/window/clockwork(src.loc, dir) qdel(src) /obj/machinery/door/window/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) @@ -276,7 +275,7 @@ else ae = electronics electronics = null - ae.forceMove(drop_location()) + ae.loc = src.loc qdel(src) return @@ -496,4 +495,4 @@ /obj/machinery/door/window/brigdoor/security/holding/southright dir = SOUTH icon_state = "rightsecure" - base_state = "rightsecure" + base_state = "rightsecure" \ No newline at end of file diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm index cdfb72a6ef..c13dfc9b88 100644 --- a/code/game/machinery/doppler_array.dm +++ b/code/game/machinery/doppler_array.dm @@ -19,10 +19,6 @@ GLOBAL_LIST_EMPTY(doppler_arrays) GLOB.doppler_arrays -= src return ..() -/obj/machinery/doppler_array/examine(mob/user) - ..() - to_chat(user, "Its dish is facing to the [dir2text(dir)].") - /obj/machinery/doppler_array/process() return PROCESS_KILL diff --git a/code/game/machinery/embedded_controller/airlock_controller.dm b/code/game/machinery/embedded_controller/airlock_controller.dm index 35b700801d..f34191370d 100644 --- a/code/game/machinery/embedded_controller/airlock_controller.dm +++ b/code/game/machinery/embedded_controller/airlock_controller.dm @@ -17,7 +17,7 @@ var/target_state = AIRLOCK_STATE_CLOSED var/sensor_pressure = null -/datum/computer/file/embedded_program/airlock_controller/receive_signal(datum/signal/signal) +/datum/computer/file/embedded_program/airlock_controller/receive_signal(datum/signal/signal, receive_method, receive_param) var/receive_tag = signal.data["tag"] if(!receive_tag) return @@ -68,17 +68,19 @@ state = AIRLOCK_STATE_CLOSED process_again = 1 else - post_signal(new /datum/signal(list( - "tag" = interior_door_tag, - "command" = "secure_close" - ))) + var/datum/signal/signal = new + signal.data["tag"] = interior_door_tag + signal.data["command"] = "secure_close" + post_signal(signal) else if(memory["pump_status"] != "off") - post_signal(new /datum/signal(list( + var/datum/signal/signal = new + signal.data = list( "tag" = airpump_tag, "power" = 0, - "sigtype" = "command" - ))) + "sigtype"="command" + ) + post_signal(signal) if(AIRLOCK_STATE_PRESSURIZE) if(target_state < state) @@ -87,15 +89,16 @@ state = AIRLOCK_STATE_INOPEN process_again = 1 else - post_signal(new /datum/signal(list( - "tag" = interior_door_tag, - "command" = "secure_open" - ))) + var/datum/signal/signal = new + signal.data["tag"] = interior_door_tag + signal.data["command"] = "secure_open" + post_signal(signal) else - var/datum/signal/signal = new(list( + var/datum/signal/signal = new + signal.data = list( "tag" = airpump_tag, - "sigtype" = "command" - )) + "sigtype"="command" + ) if(memory["pump_status"] == "siphon") signal.data["stabalize"] = 1 else if(memory["pump_status"] != "release") @@ -111,27 +114,29 @@ state = AIRLOCK_STATE_DEPRESSURIZE process_again = 1 else - post_signal(new /datum/signal(list( - "tag" = interior_door_tag, - "command" = "secure_close" - ))) + var/datum/signal/signal = new + signal.data["tag"] = interior_door_tag + signal.data["command"] = "secure_close" + post_signal(signal) else if(target_state < state) if(memory["exterior_status"] == "closed") state = AIRLOCK_STATE_PRESSURIZE process_again = 1 else - post_signal(new /datum/signal(list( - "tag" = exterior_door_tag, - "command" = "secure_close" - ))) + var/datum/signal/signal = new + signal.data["tag"] = exterior_door_tag + signal.data["command"] = "secure_close" + post_signal(signal) else if(memory["pump_status"] != "off") - post_signal(new /datum/signal(list( + var/datum/signal/signal = new + signal.data = list( "tag" = airpump_tag, "power" = 0, - "sigtype" = "command" - ))) + "sigtype"="command" + ) + post_signal(signal) if(AIRLOCK_STATE_DEPRESSURIZE) var/target_pressure = ONE_ATMOSPHERE*0.05 @@ -143,10 +148,10 @@ if(memory["exterior_status"] == "open") state = AIRLOCK_STATE_OUTOPEN else - post_signal(new /datum/signal(list( - "tag" = exterior_door_tag, - "command" = "secure_open" - ))) + var/datum/signal/signal = new + signal.data["tag"] = exterior_door_tag + signal.data["command"] = "secure_open" + post_signal(signal) else if(target_state < state) state = AIRLOCK_STATE_CLOSED process_again = 1 @@ -154,10 +159,12 @@ state = AIRLOCK_STATE_CLOSED process_again = 1 else - var/datum/signal/signal = new(list( + var/datum/signal/signal = new + signal.transmission_method = 1 //radio signal + signal.data = list( "tag" = airpump_tag, - "sigtype" = "command" - )) + "sigtype"="command" + ) if(memory["pump_status"] == "release") signal.data["purge"] = 1 else if(memory["pump_status"] != "siphon") @@ -174,17 +181,19 @@ state = AIRLOCK_STATE_CLOSED process_again = 1 else - post_signal(new /datum/signal(list( - "tag" = exterior_door_tag, - "command" = "secure_close" - ))) + var/datum/signal/signal = new + signal.data["tag"] = exterior_door_tag + signal.data["command"] = "secure_close" + post_signal(signal) else if(memory["pump_status"] != "off") - post_signal(new /datum/signal(list( + var/datum/signal/signal = new + signal.data = list( "tag" = airpump_tag, "power" = 0, - "sigtype" = "command" - ))) + "sigtype"="command" + ) + post_signal(signal) memory["sensor_pressure"] = sensor_pressure memory["processing"] = state != target_state @@ -200,7 +209,7 @@ name = "airlock console" density = FALSE - frequency = FREQ_AIRLOCK_CONTROL + frequency = 1449 power_channel = ENVIRON // Setup parameters only @@ -284,4 +293,4 @@
[state_options]"} - return output \ No newline at end of file + return output diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm index 2ead1d99d7..16691160f2 100644 --- a/code/game/machinery/embedded_controller/embedded_controller_base.dm +++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm @@ -11,7 +11,7 @@ /datum/computer/file/embedded_program/proc/receive_user_command(command) -/datum/computer/file/embedded_program/proc/receive_signal(datum/signal/signal) +/datum/computer/file/embedded_program/proc/receive_signal(datum/signal/signal, receive_method, receive_param) return null /datum/computer/file/embedded_program/process() @@ -43,9 +43,13 @@ /obj/machinery/embedded_controller/proc/post_signal(datum/signal/signal, comm_line) return 0 -/obj/machinery/embedded_controller/receive_signal(datum/signal/signal) - if(istype(signal) && program) - program.receive_signal(signal) +/obj/machinery/embedded_controller/receive_signal(datum/signal/signal, receive_method, receive_param) + if(!signal || signal.encryption) + return + + if(program) + program.receive_signal(signal, receive_method, receive_param) + //spawn(5) program.process() //no, program.process sends some signals and machines respond and we here again and we lag -rastaf0 /obj/machinery/embedded_controller/Topic(href, href_list) if(..()) diff --git a/code/game/machinery/embedded_controller/simple_vent_controller.dm b/code/game/machinery/embedded_controller/simple_vent_controller.dm index 2a5faef0e1..af945c7ccb 100644 --- a/code/game/machinery/embedded_controller/simple_vent_controller.dm +++ b/code/game/machinery/embedded_controller/simple_vent_controller.dm @@ -5,27 +5,34 @@ /datum/computer/file/embedded_program/simple_vent_controller/receive_user_command(command) switch(command) if("vent_inactive") - post_signal(new /datum/signal(list( + var/datum/signal/signal = new + signal.data = list( "tag" = airpump_tag, - "sigtype" = "command", - "power" = 0 - ))) + "sigtype"="command" + ) + signal.data["power"] = 0 + post_signal(signal) if("vent_pump") - post_signal(new /datum/signal(list( + var/datum/signal/signal = new + signal.data = list( "tag" = airpump_tag, - "sigtype" = "command", - "stabalize" = 1, - "power" = 1 - ))) + "sigtype"="command" + ) + signal.data["stabalize"] = 1 + signal.data["power"] = 1 + post_signal(signal) if("vent_clear") - post_signal(new /datum/signal(list( + var/datum/signal/signal = new + signal.transmission_method = 1 //radio signal + signal.data = list( "tag" = airpump_tag, - "sigtype" = "command", - "purge" = 1, - "power" = 1 - ))) + "sigtype"="command" + ) + signal.data["purge"] = 1 + signal.data["power"] = 1 + post_signal(signal) /datum/computer/file/embedded_program/simple_vent_controller/process() return 0 @@ -38,7 +45,7 @@ name = "vent controller" density = FALSE - frequency = FREQ_ATMOS_CONTROL + frequency = 1229 power_channel = ENVIRON // Setup parameters only diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 10a552564b..d6d8c93ed1 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -75,7 +75,7 @@ Possible to do for anyone motivated enough: replay_stop() if(record_mode) record_stop() - + QDEL_NULL(disk) holopads -= src @@ -256,12 +256,12 @@ Possible to do for anyone motivated enough: temp = "" if(outgoing_call) outgoing_call.Disconnect() - + else if(href_list["disk_eject"]) if(disk && !replay_mode) disk.forceMove(drop_location()) disk = null - + else if(href_list["replay_stop"]) replay_stop() else if(href_list["replay_start"]) @@ -424,7 +424,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ if(masters[user]) var/obj/effect/overlay/holo_pad_hologram/H = masters[user] step_to(H, new_turf) - H.forceMove(new_turf) + H.loc = new_turf var/area/holo_area = get_area(src) var/area/eye_area = new_turf.loc @@ -505,7 +505,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ current_delay += entry[2] var/time_delta = world.time - record_start - current_delay - + if(time_delta >= 1) disk.record.entries += list(list(HOLORECORD_DELAY,time_delta)) disk.record.entries += list(list(HOLORECORD_SAY,message)) diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index 7aa3859cdf..198d368d59 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -213,4 +213,4 @@ to_chat(user, "[attached ? attached : "No one"] is attached.") #undef IV_TAKING -#undef IV_INJECTING \ No newline at end of file +#undef IV_INJECTING diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm index 8263795c60..aa3bf465f2 100644 --- a/code/game/machinery/magnet.dm +++ b/code/game/machinery/magnet.dm @@ -15,7 +15,7 @@ use_power = IDLE_POWER_USE idle_power_usage = 50 - var/freq = FREQ_MAGNETS // radio frequency + var/freq = 1449 // radio frequency var/electricity_level = 1 // intensity of the magnetic pull var/magnetic_field = 1 // the range of magnetic attraction var/code = 0 // frequency code, they should be different unless you have a group of magnets working together or something @@ -33,7 +33,7 @@ var/turf/T = loc hide(T.intact) center = T - SSradio.add_object(src, freq, RADIO_MAGNETS) + SSradio.add_object(src, freq, GLOB.RADIO_MAGNETS) return INITIALIZE_HINT_LATELOAD /obj/machinery/magnetic_module/LateInitialize() @@ -198,7 +198,7 @@ anchored = TRUE use_power = IDLE_POWER_USE idle_power_usage = 45 - var/frequency = FREQ_MAGNETS + var/frequency = 1449 var/code = 0 var/list/magnets = list() var/title = "Magnetic Control Console" @@ -224,7 +224,7 @@ if(path) // check for default path filter_path() // renders rpath - radio_connection = SSradio.add_object(src, frequency, RADIO_MAGNETS) + radio_connection = SSradio.add_object(src, frequency, GLOB.RADIO_MAGNETS) /obj/machinery/magnetic_controller/Destroy() SSradio.remove_object(src, frequency) @@ -278,7 +278,11 @@ if(href_list["radio-op"]) // Prepare signal beforehand, because this is a radio operation - var/datum/signal/signal = new(list("code" = code)) + var/datum/signal/signal = new + signal.transmission_method = 1 // radio transmission + signal.source = src + signal.frequency = frequency + signal.data["code"] = code // Apply any necessary commands switch(href_list["radio-op"]) @@ -298,7 +302,7 @@ // Broadcast the signal - radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS) + radio_connection.post_signal(src, signal, filter = GLOB.RADIO_MAGNETS) spawn(1) updateUsrDialog() // pretty sure this increases responsiveness @@ -341,7 +345,11 @@ looping = 1 // Prepare the radio signal - var/datum/signal/signal = new(list("code" = code)) + var/datum/signal/signal = new + signal.transmission_method = 1 // radio transmission + signal.source = src + signal.frequency = frequency + signal.data["code"] = code if(pathpos > rpath.len) // if the position is greater than the length, we just loop through the list! pathpos = 1 @@ -362,7 +370,7 @@ // Broadcast the signal spawn() - radio_connection.post_signal(src, signal, filter = RADIO_MAGNETS) + radio_connection.post_signal(src, signal, filter = GLOB.RADIO_MAGNETS) if(speed == 10) sleep(1) @@ -385,4 +393,4 @@ if(!(nextchar in list(";", "&", "*", " "))) // if char is a separator, ignore rpath += copytext(path, i, i+1) // else, add to list - // there doesn't HAVE to be separators but it makes paths syntatically visible + // there doesn't HAVE to be separators but it makes paths syntatically visible \ No newline at end of file diff --git a/code/game/machinery/navbeacon.dm b/code/game/machinery/navbeacon.dm index fe2926f150..e62d25e5fa 100644 --- a/code/game/machinery/navbeacon.dm +++ b/code/game/machinery/navbeacon.dm @@ -15,7 +15,7 @@ var/open = FALSE // true if cover is open var/locked = TRUE // true if controls are locked - var/freq = FREQ_NAV_BEACON + var/freq = 1445 // radio frequency var/location = "" // location response text var/list/codes // assoc. list of transponder codes var/codes_txt = "" // codes as set on map: "tag1;tag2" or "tag1=value;tag2=value" @@ -205,4 +205,4 @@ Transponder Codes: