diff --git a/.editorconfig b/.editorconfig index 471170c449e..59f09ca6fd9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -16,5 +16,9 @@ indent_style = space [*.md] trim_trailing_whitespace = false +[*.sql] +indent_style = space +indent_size = 2 + [Dockerfile] indent_style = space diff --git a/SQL/database_changelog.md b/SQL/database_changelog.md index 42bb72672a2..12b3f4cbad8 100644 --- a/SQL/database_changelog.md +++ b/SQL/database_changelog.md @@ -22,4 +22,8 @@ Database migrated to DBCore. Schema will start at MAJOR 1, MINOR 1. ### 11/21/22 - 1.2 - silicons -persist_keyed_strings added. +`persist_keyed_strings` added. + +### 2/4/23 - 1.3 - silicons + +`character` table added. diff --git a/SQL/database_schema.sql b/SQL/database_schema.sql index 0c40797a67f..b99026520e8 100644 --- a/SQL/database_schema.sql +++ b/SQL/database_schema.sql @@ -16,6 +16,32 @@ CREATE TABLE IF NOT EXISTS `%_PREFIX_%schema_revision` ( PRIMARY KEY (`major`, `minor`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +-- Player lookup table -- +-- Used to look up player ID from ckey, as well as -- +-- store last computerid/ip for a ckey. -- +CREATE TABLE IF NOT EXISTS `%_PREFIX_%player_lookup` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `ckey` varchar(32) NOT NULL, + `firstseen` datetime NOT NULL, + `lastseen` datetime NOT NULL, + `ip` varchar(18) NOT NULL, + `computerid` varchar(32) NOT NULL, + `lastadminrank` varchar(32) NOT NULL DEFAULT 'Player', + `playerid` int(11), + PRIMARY KEY (`id`), + UNIQUE KEY `ckey` (`ckey`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- Primary player table -- +-- Allows for one-to-many player-ckey association. -- +CREATE TABLE IF NOT EXISTS `%_PREFIX_%player` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `flags` int(24) NOT NULL DEFAULT 0, + `firstseen` datetime NOT NULL DEFAULT Now(), + `lastseen` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + -- -- Table structure for table `round` -- @@ -31,6 +57,47 @@ CREATE TABLE IF NOT EXISTS `%_PREFIX_%round` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +-- Connection log -- +-- Logs all connections to the server. -- +CREATE TABLE IF NOT EXISTS `%_PREFIX_%connection_log` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `datetime` datetime NOT NULL, + `serverip` varchar(16) NOT NULL, + `ckey` varchar(32) NOT NULL, + `ip` varchar(16) NOT NULL, + `computerid` varchar(32) NOT NULL, + PRIMARY KEY(`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- Persistence - Object Storage: Strings -- +CREATE TABLE IF NOT EXISTS `%_PREFIX_%persist_keyed_strings` ( + `created` DATETIME NOT NULL DEFAULT Now(), + `modified` DATETIME NOT NULL, + `key` VARCHAR(64) NOT NULL, + `value` MEDIUMTEXT NULL, + `group` VARCHAR(64) NOT NULL, + `revision` INT(11) NOT NULL, + PRIMARY KEY(`key`, `group`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- /datum/character - Character Table -- +CREATE TABLE IF NOT EXISTS `%_PREFIX_%character` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `created` DATETIME NOT NULL DEFAULT Now(), + `last_played` DATETIME NULL, + `last_persisted` DATETIME NULL, + `playerid` INT(11) NOT NULL, + `canonical_name` VARCHAR(128) NOT NULL, + `persist_data` MEDIUMTEXT NULL, + `character_type` VARCHAR(64) NOT NULL, + PRIMARY KEY(`id`), + CONSTRAINT `character_has_player` FOREIGN KEY (`playerid`) + REFERENCES `%_PREFIX_%player` (`id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + UNIQUE (`playerid`, `canonical_name`, `character_type`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + CREATE TABLE IF NOT EXISTS `%_PREFIX_%admin` ( `id` int(11) NOT NULL AUTO_INCREMENT, `ckey` varchar(32) NOT NULL, @@ -86,29 +153,6 @@ CREATE TABLE IF NOT EXISTS `%_PREFIX_%feedback` ( PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; -CREATE TABLE IF NOT EXISTS `%_PREFIX_%player_lookup` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `ckey` varchar(32) NOT NULL, - `firstseen` datetime NOT NULL, - `lastseen` datetime NOT NULL, - `ip` varchar(18) NOT NULL, - `computerid` varchar(32) NOT NULL, - `lastadminrank` varchar(32) NOT NULL DEFAULT 'Player', - `playerid` int(11), - PRIMARY KEY (`id`), - UNIQUE KEY `ckey` (`ckey`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; - ---- Primary player table --- ---- Allows for one-to-many player-ckey association. --- -CREATE TABLE IF NOT EXISTS `%_PREFIX_%player` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `flags` int(24) NOT NULL DEFAULT 0, - `firstseen` datetime NOT NULL DEFAULT Now(), - `lastseen` datetime NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; - CREATE TABLE IF NOT EXISTS `%_PREFIX_%poll_option` ( `id` int(11) NOT NULL AUTO_INCREMENT, `pollid` int(11) NOT NULL, @@ -226,25 +270,3 @@ CREATE TABLE IF NOT EXISTS `%_PREFIX_%population` ( `time` DATETIME NOT NULL , PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; - -CREATE TABLE IF NOT EXISTS `%_PREFIX_%connection_log` ( - `id` INT(11) NOT NULL AUTO_INCREMENT, - `datetime` datetime NOT NULL, - `serverip` varchar(16) NOT NULL, - `ckey` varchar(32) NOT NULL, - `ip` varchar(16) NOT NULL, - `computerid` varchar(32) NOT NULL, - PRIMARY KEY(`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; - -/* Object Persistence Store */ -/* These are not multi-server synchronization safe! It is expected that you DO NOT share these databases */ -CREATE TABLE IF NOT EXISTS `%_PREFIX_%persist_keyed_strings` ( - `created` DATETIME NOT NULL DEFAULT Now(), - `modified` DATETIME NOT NULL, - `key` VARCHAR(64) NOT NULL, - `value` MEDIUMTEXT NULL, - `group` VARCHAR(64) NOT NULL, - `revision` INT(11) NOT NULL, - PRIMARY KEY(`key`, `group`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; diff --git a/SQL/database_schema_prefixed.sql b/SQL/database_schema_prefixed.sql index deca75a12e6..d09dac1427e 100644 --- a/SQL/database_schema_prefixed.sql +++ b/SQL/database_schema_prefixed.sql @@ -2,7 +2,7 @@ * make sure to bump schema version and mark changes in database_changelog.md! * * default prefix is rp_ - * find replace case sensitive %_PREFIX_% + * find replace case sensitive rp_ * PRESERVE ANY vr_'s! We need to replace those tables and features at some point, that's how we konw. **/ @@ -16,6 +16,32 @@ CREATE TABLE IF NOT EXISTS `rp_schema_revision` ( PRIMARY KEY (`major`, `minor`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +-- Player lookup table -- +-- Used to look up player ID from ckey, as well as -- +-- store last computerid/ip for a ckey. -- +CREATE TABLE IF NOT EXISTS `rp_player_lookup` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `ckey` varchar(32) NOT NULL, + `firstseen` datetime NOT NULL, + `lastseen` datetime NOT NULL, + `ip` varchar(18) NOT NULL, + `computerid` varchar(32) NOT NULL, + `lastadminrank` varchar(32) NOT NULL DEFAULT 'Player', + `playerid` int(11), + PRIMARY KEY (`id`), + UNIQUE KEY `ckey` (`ckey`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- Primary player table -- +-- Allows for one-to-many player-ckey association. -- +CREATE TABLE IF NOT EXISTS `rp_player` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `flags` int(24) NOT NULL DEFAULT 0, + `firstseen` datetime NOT NULL DEFAULT Now(), + `lastseen` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + -- -- Table structure for table `round` -- @@ -31,6 +57,47 @@ CREATE TABLE IF NOT EXISTS `rp_round` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +-- Connection log -- +-- Logs all connections to the server. -- +CREATE TABLE IF NOT EXISTS `rp_connection_log` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `datetime` datetime NOT NULL, + `serverip` varchar(16) NOT NULL, + `ckey` varchar(32) NOT NULL, + `ip` varchar(16) NOT NULL, + `computerid` varchar(32) NOT NULL, + PRIMARY KEY(`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- Persistence - Object Storage: Strings -- +CREATE TABLE IF NOT EXISTS `rp_persist_keyed_strings` ( + `created` DATETIME NOT NULL DEFAULT Now(), + `modified` DATETIME NOT NULL, + `key` VARCHAR(64) NOT NULL, + `value` MEDIUMTEXT NULL, + `group` VARCHAR(64) NOT NULL, + `revision` INT(11) NOT NULL, + PRIMARY KEY(`key`, `group`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- /datum/character - Character Table -- +CREATE TABLE IF NOT EXISTS `rp_character` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `created` DATETIME NOT NULL DEFAULT Now(), + `last_played` DATETIME NULL, + `last_persisted` DATETIME NULL, + `playerid` INT(11) NOT NULL, + `canonical_name` VARCHAR(128) NOT NULL, + `persist_data` MEDIUMTEXT NULL, + `character_type` VARCHAR(64) NOT NULL, + PRIMARY KEY(`id`), + CONSTRAINT `character_has_player` FOREIGN KEY (`playerid`) + REFERENCES `rp_player` (`id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + UNIQUE (`playerid`, `canonical_name`, `character_type`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + CREATE TABLE IF NOT EXISTS `rp_admin` ( `id` int(11) NOT NULL AUTO_INCREMENT, `ckey` varchar(32) NOT NULL, @@ -86,27 +153,6 @@ CREATE TABLE IF NOT EXISTS `rp_feedback` ( PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; -CREATE TABLE IF NOT EXISTS `rp_player_lookup` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `ckey` varchar(32) NOT NULL, - `firstseen` datetime NOT NULL, - `lastseen` datetime NOT NULL, - `ip` varchar(18) NOT NULL, - `computerid` varchar(32) NOT NULL, - `lastadminrank` varchar(32) NOT NULL DEFAULT 'Player', - `playerid` int(11), - PRIMARY KEY (`id`), - UNIQUE KEY `ckey` (`ckey`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; - -CREATE TABLE IF NOT EXISTS `rp_player` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `flags` int(24) NOT NULL DEFAULT 0, - `firstseen` datetime NOT NULL DEFAULT Now(), - `lastseen` datetime NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; - CREATE TABLE IF NOT EXISTS `rp_poll_option` ( `id` int(11) NOT NULL AUTO_INCREMENT, `pollid` int(11) NOT NULL, @@ -224,25 +270,3 @@ CREATE TABLE IF NOT EXISTS `rp_population` ( `time` DATETIME NOT NULL , PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; - -CREATE TABLE IF NOT EXISTS `rp_connection_log` ( - `id` INT(11) NOT NULL AUTO_INCREMENT, - `datetime` datetime NOT NULL, - `serverip` varchar(16) NOT NULL, - `ckey` varchar(32) NOT NULL, - `ip` varchar(16) NOT NULL, - `computerid` varchar(32) NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; - -/* Object Persistence Store */ -/* These are not multi-server synchronization safe! It is expected that you DO NOT share these databases */ -CREATE TABLE IF NOT EXISTS `rp_persist_keyed_strings` ( - `created` DATETIME NOT NULL DEFAULT Now(), - `modified` DATETIME NOT NULL, - `key` VARCHAR(64) NOT NULL, - `value` MEDIUMTEXT NULL, - `group` VARCHAR(64) NOT NULL, - `revision` INT(11) NOT NULL, - PRIMARY KEY(`key`, `group`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; diff --git a/citadel.dme b/citadel.dme index 73712768a1b..1006aa1dc72 100644 --- a/citadel.dme +++ b/citadel.dme @@ -67,7 +67,6 @@ #include "code\__DEFINES\movespeed_modification.dm" #include "code\__DEFINES\objects.dm" #include "code\__DEFINES\parameters_world.dm" -#include "code\__DEFINES\persistence.dm" #include "code\__DEFINES\planets.dm" #include "code\__DEFINES\plants.dm" #include "code\__DEFINES\qdel.dm" @@ -193,6 +192,7 @@ #include "code\__DEFINES\languages\translation.dm" #include "code\__DEFINES\mapping\multiz.dm" #include "code\__DEFINES\misc\message_ranges.dm" +#include "code\__DEFINES\mobs\characteristics.dm" #include "code\__DEFINES\mobs\grab.dm" #include "code\__DEFINES\mobs\health.dm" #include "code\__DEFINES\mobs\intent.dm" @@ -443,6 +443,7 @@ #include "code\controllers\configuration\entries\lobby.dm" #include "code\controllers\configuration\entries\logging.dm" #include "code\controllers\configuration\entries\resources.dm" +#include "code\controllers\configuration\entries\skills.dm" #include "code\controllers\configuration\entries\urls.dm" #include "code\controllers\configuration_old\configuration.dm" #include "code\controllers\configuration_old\configuration_vr.dm" @@ -485,6 +486,7 @@ #include "code\controllers\subsystem\planets.dm" #include "code\controllers\subsystem\plants.dm" #include "code\controllers\subsystem\radiation.dm" +#include "code\controllers\subsystem\repository.dm" #include "code\controllers\subsystem\server_maint.dm" #include "code\controllers\subsystem\shuttles.dm" #include "code\controllers\subsystem\sonar.dm" @@ -527,6 +529,7 @@ #include "code\controllers\subsystem\persistence\_persistence.dm" #include "code\controllers\subsystem\persistence\bunker.dm" #include "code\controllers\subsystem\persistence\objects.dm" +#include "code\controllers\subsystem\persistence\objects\characters.dm" #include "code\controllers\subsystem\persistence\objects\unique_string.dm" #include "code\controllers\subsystem\processing\chemistry.dm" #include "code\controllers\subsystem\processing\circuits.dm" @@ -562,6 +565,7 @@ #include "code\datums\position_point_vector.dm" #include "code\datums\profile.dm" #include "code\datums\progressbar.dm" +#include "code\datums\prototype.dm" #include "code\datums\radiation_wave.dm" #include "code\datums\recipe.dm" #include "code\datums\soul_link.dm" @@ -2063,16 +2067,15 @@ #include "code\modules\catalogue\cataloguer_vr.dm" #include "code\modules\client\client procs_vr.dm" #include "code\modules\client\client.dm" +#include "code\modules\client\client_data.dm" #include "code\modules\client\client_procs.dm" -#include "code\modules\client\data.dm" -#include "code\modules\client\database.dm" -#include "code\modules\client\player_details.dm" +#include "code\modules\client\player_data.dm" #include "code\modules\client\spam_prevention.dm" #include "code\modules\client\statpanel.dm" #include "code\modules\client\throttling.dm" #include "code\modules\client\ui_style.dm" #include "code\modules\client\viewport.dm" -#include "code\modules\client\winset_wrappers.dm" +#include "code\modules\client\wrappers.dm" #include "code\modules\client\verbs\minimap.dm" #include "code\modules\client\verbs\ooc.dm" #include "code\modules\client\verbs\panic_bunker_player.dm" @@ -2512,9 +2515,9 @@ #include "code\modules\integrated_electronics\subtypes\time.dm" #include "code\modules\integrated_electronics\subtypes\trig.dm" #include "code\modules\integrated_electronics\~defines\~defines.dm" -#include "code\modules\jobs\_alt_title.dm" #include "code\modules\jobs\access.dm" #include "code\modules\jobs\access_datum.dm" +#include "code\modules\jobs\alt_title.dm" #include "code\modules\jobs\department.dm" #include "code\modules\jobs\job.dm" #include "code\modules\jobs\jobs.dm" @@ -2870,7 +2873,6 @@ #include "code\modules\mob\perspective.dm" #include "code\modules\mob\say.dm" #include "code\modules\mob\say_vr.dm" -#include "code\modules\mob\skillset.dm" #include "code\modules\mob\status_procs.dm" #include "code\modules\mob\throwing.dm" #include "code\modules\mob\transform_procs.dm" @@ -2885,6 +2887,24 @@ #include "code\modules\mob\_modifiers\traits.dm" #include "code\modules\mob\_modifiers\traits_phobias.dm" #include "code\modules\mob\_modifiers\unholy.dm" +#include "code\modules\mob\characteristics\helpers.dm" +#include "code\modules\mob\characteristics\holder.dm" +#include "code\modules\mob\characteristics\mob.dm" +#include "code\modules\mob\characteristics\presets.dm" +#include "code\modules\mob\characteristics\skill.dm" +#include "code\modules\mob\characteristics\stat.dm" +#include "code\modules\mob\characteristics\talent.dm" +#include "code\modules\mob\characteristics\ui.dm" +#include "code\modules\mob\characteristics\skills\engineering.dm" +#include "code\modules\mob\characteristics\skills\logistics.dm" +#include "code\modules\mob\characteristics\skills\medical.dm" +#include "code\modules\mob\characteristics\skills\misc.dm" +#include "code\modules\mob\characteristics\skills\science.dm" +#include "code\modules\mob\characteristics\skills\security.dm" +#include "code\modules\mob\characteristics\skills\service.dm" +#include "code\modules\mob\characteristics\skills\voidcraft.dm" +#include "code\modules\mob\characteristics\stats\gaming.dm" +#include "code\modules\mob\characteristics\talents\placeholder.dm" #include "code\modules\mob\dead\death.dm" #include "code\modules\mob\dead\observer\free_vr.dm" #include "code\modules\mob\dead\observer\login.dm" @@ -3679,7 +3699,6 @@ #include "code\modules\preferences\preference_setup\loadout\loadout_utility.dm" #include "code\modules\preferences\preference_setup\loadout\loadout_xeno.dm" #include "code\modules\preferences\preference_setup\occupation\occupation.dm" -#include "code\modules\preferences\preference_setup\skills\skills.dm" #include "code\modules\preferences\preference_setup\vore\01_ears.dm" #include "code\modules\preferences\preference_setup\vore\02_size.dm" #include "code\modules\preferences\preference_setup\vore\03_egg.dm" @@ -3935,6 +3954,7 @@ #include "code\modules\rogueminer_vr\wrappers.dm" #include "code\modules\rogueminer_vr\zone_console.dm" #include "code\modules\rogueminer_vr\zonemaster.dm" +#include "code\modules\roles\role.dm" #include "code\modules\security levels\keycard authentication.dm" #include "code\modules\security levels\security levels.dm" #include "code\modules\shieldgen\directional_shield.dm" diff --git a/code/__DEFINES/controllers/_subsystems.dm b/code/__DEFINES/controllers/_subsystems.dm index 0865d039242..7dafd0b4ff6 100644 --- a/code/__DEFINES/controllers/_subsystems.dm +++ b/code/__DEFINES/controllers/_subsystems.dm @@ -72,18 +72,20 @@ DEFINE_BITFIELD(runlevels, list( *? The numbers just define the ordering, they are meaningless otherwise. */ -#define INIT_ORDER_FAIL2TOPIC 104 -#define INIT_ORDER_STATPANELS 103 -#define INIT_ORDER_PROTOTYPES 102 -#define INIT_ORDER_DBCORE 101 -#define INIT_ORDER_INPUT 100 -#define INIT_ORDER_JOBS 99 -#define INIT_ORDER_CHARACTERS 98 -#define INIT_ORDER_SOUNDS 95 +// todo: tg init brackets + +#define INIT_ORDER_FAIL2TOPIC 200 +#define INIT_ORDER_TIMER 195 +#define INIT_ORDER_DBCORE 190 +#define INIT_ORDER_REPOSITORY 180 +#define INIT_ORDER_STATPANELS 170 +#define INIT_ORDER_INPUT 160 +#define INIT_ORDER_JOBS 150 +#define INIT_ORDER_CHARACTERS 140 +#define INIT_ORDER_SOUNDS 130 +#define INIT_ORDER_GARBAGE 120 #define INIT_ORDER_VIS 80 -#define INIT_ORDER_GARBAGE 70 #define INIT_ORDER_SERVER_MAINT 65 -#define INIT_ORDER_TIMER 60 #define INIT_ORDER_INSTRUMENTS 50 #define INIT_ORDER_EARLY_ASSETS 48 #define INIT_ORDER_SQLITE 40 @@ -125,40 +127,63 @@ DEFINE_BITFIELD(runlevels, list( *? If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child) */ +//? Background Subsystems - Below normal +// Any ../subsystem/.. is here unless it doesn't have SS_BACKGROUND in subsystem_flags! +// This means by default, ../subsystem/processing/.. is here! + +#define FIRE_PRIORITY_RADIATION 10 //! laggy as hell, bottom barrel until optimizations are done. +#define FIRE_PRIORITY_GARBAGE 15 +#define FIRE_PRIORITY_CHARACTERS 25 +#define FIRE_PRIORITY_PARALLAX 30 +#define FIRE_PRIORITY_AIR 35 +#define FIRE_PRIORITY_PROCESS 45 +// DEFAULT PRIORITY IS HERE +#define FIRE_PRIORITY_PLANETS 75 + +//? Normal Subsystems - Above background, below ticker +// Any ../subsystem/.. without SS_TICKER or SS_BACKGROUND in subsystem_flags is here! + #define FIRE_PRIORITY_PING 5 #define FIRE_PRIORITY_SHUTTLES 5 -#define FIRE_PRIORITY_NIGHTSHIFT 6 #define FIRE_PRIORITY_PLANTS 5 +#define FIRE_PRIORITY_NIGHTSHIFT 6 #define FIRE_PRIORITY_VOTE 9 -#define FIRE_PRIORITY_AI 10 #define FIRE_PRIORITY_VIS 10 #define FIRE_PRIORITY_SERVER_MAINT 10 #define FIRE_PRIORITY_ZMIMIC 10 -#define FIRE_PRIORITY_GARBAGE 15 #define FIRE_PRIORITY_ALARMS 20 -#define FIRE_PRIORITY_CHARSETUP 25 #define FIRE_PRIORITY_SPACEDRIFT 25 #define FIRE_PRIORITY_AIRFLOW 30 -#define FIRE_PRIORITY_PARALLAX 30 -#define FIRE_PRIORITY_AIR 35 #define FIRE_PRIORITY_OBJ 40 -#define FIRE_PRIORITY_PROCESS 45 -#define FIRE_PRIORITY_DEFAULT 50 -#define FIRE_PRIORITY_LIGHTING 50 -#define FIRE_PRIORITY_PLANETS 75 -#define FIRE_PRIORITY_INSTRUMENTS 90 -#define FIRE_PRIORITY_MACHINES 100 -#define FIRE_PRIORITY_ASSETS 105 -#define FIRE_PRIORITY_TGUI 110 -#define FIRE_PRIORITY_PROJECTILES 150 -#define FIRE_PRIORITY_THROWING 150 +// DEFAULT PRIORITY IS HERE +#define FIRE_PRIORITY_LIGHTING 50 +#define FIRE_PRIORITY_INSTRUMENTS 90 +#define FIRE_PRIORITY_ASSET_LOADING 100 +#define FIRE_PRIORITY_MACHINES 100 +#define FIRE_PRIORITY_TGUI 110 +#define FIRE_PRIORITY_STATPANELS 400 +#define FIRE_PRIORITY_OVERLAYS 500 + +//? Ticker Subsystems - Highest priority +// Any subsystem flagged with SS_TICKER is here! +// Do not unnecessarily set your subsystem as TICKER. +// Is your feature as important as movement, chat, or timers? +// Probably not! Go to normal bracket instead! + +#define FIRE_PRIORITY_AI 10 //! WHY IS THIS SSTICKER??? +// DEFAULT PRIORITY IS HERE +#define FIRE_PRIORITY_PROJECTILES 150 //! this probably shouldn't be ssticker +#define FIRE_PRIORITY_THROWING 150 //! this probably shouldn't be ssticker #define FIRE_PRIORITY_CHAT 400 -#define FIRE_PRIORITY_STATPANELS 400 -#define FIRE_PRIORITY_OVERLAYS 500 -#define FIRE_PRIORITY_SMOOTHING 500 +#define FIRE_PRIORITY_SMOOTHING 500 //! this probably shouldn't be ssticker #define FIRE_PRIORITY_TIMER 700 #define FIRE_PRIORITY_INPUT 1000 //! Never drop input. +//? Special + +/// This is used as the default regardless of bucket. Check above. +#define FIRE_PRIORITY_DEFAULT 50 + /** * Create a new timer and add it to the queue. * Arguments: diff --git a/code/__DEFINES/controllers/dbcore.dm b/code/__DEFINES/controllers/dbcore.dm index 8f9f885f19f..fffb47bc476 100644 --- a/code/__DEFINES/controllers/dbcore.dm +++ b/code/__DEFINES/controllers/dbcore.dm @@ -15,4 +15,4 @@ * * make sure you add an update to the schema_version stable in the db changelog */ -#define DB_MINOR_VERSION 2 +#define DB_MINOR_VERSION 3 diff --git a/code/__DEFINES/controllers/persistence.dm b/code/__DEFINES/controllers/persistence.dm index cf9383192a9..3bfee20bca8 100644 --- a/code/__DEFINES/controllers/persistence.dm +++ b/code/__DEFINES/controllers/persistence.dm @@ -1,3 +1,26 @@ -//! Object Storage System - Strings +//? Object Storage System - Groups + /// default group for null groups -#define OBJECT_PERSISTENCE_STRING_GROUP_NULL "" +#define OBJECT_PERSISTENCE_GROUP_NONE "" +/// group for map persistence key +#define OBJECT_PERSISTENCE_GROUP_FOR_MAP_KEY(_key) "map_[_key]" + +//? Object Storage System - Character Types + +/// /datum/character/human +#define OBJECT_PERSISTENCE_CHARACTER_TYPE_HUMAN "human" + +//? legacy below + +// Direct filename paths + +#define PERSISTENCE_FILE_BUNKER_PASSTHROUGH "data/persistence/bunker_passthrough.json" + +// Filenames for putting under directories + +#define PERSISTENCE_FILENAME_OBJECTS "objects.json" + +// Directories + +#define PERSISTENCE_MAP_ROOT_DIRECTORY "data/persistence/maps" + diff --git a/code/__DEFINES/controllers/prototypes.dm b/code/__DEFINES/controllers/prototypes.dm deleted file mode 100644 index 1075e03a048..00000000000 --- a/code/__DEFINES/controllers/prototypes.dm +++ /dev/null @@ -1,5 +0,0 @@ -//! types -/// dud for testing -#define YAML_PROTOTYPE_DUD "Dud" -/// lore datums -#define YAML_PROTOTYPE_LORE "Lore" diff --git a/code/__DEFINES/directional.dm b/code/__DEFINES/directional.dm index 77f57458101..e1efa3d8a91 100644 --- a/code/__DEFINES/directional.dm +++ b/code/__DEFINES/directional.dm @@ -30,6 +30,7 @@ #define DIRFLIP(d) turn(d, 180) /// Inverse direction, taking into account UP|DOWN if necessary. +//? STOP USING THIS. Use global.reverse_dir!! #define REVERSE_DIR(dir) ( ((dir & 85) << 1) | ((dir & 170) >> 1) ) /// Create directional subtypes for a path to simplify mapping. diff --git a/code/__DEFINES/maps.dm b/code/__DEFINES/maps.dm index ed01ed8b588..0c80e8dc553 100644 --- a/code/__DEFINES/maps.dm +++ b/code/__DEFINES/maps.dm @@ -46,7 +46,7 @@ require only minor tweaks. // helpers for modifying jobs, used in various job_changes.dm files #define MAP_JOB_CHECK if(SSmapping.config.map_name != JOB_MODIFICATION_MAP_NAME) { return; } #define MAP_JOB_CHECK_BASE if(SSmapping.config.map_name != JOB_MODIFICATION_MAP_NAME) { return ..(); } -#define MAP_REMOVE_JOB(jobpath) /datum/job/##jobpath/map_check() { return (SSmapping.config.map_name != JOB_MODIFICATION_MAP_NAME) && ..() } +#define MAP_REMOVE_JOB(jobpath) /datum/role/job/##jobpath/map_check() { return (SSmapping.config.map_name != JOB_MODIFICATION_MAP_NAME) && ..() } #define SPACERUIN_MAP_EDGE_PAD 15 diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index b5bdb1b8017..fbb3f1e3dcd 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -110,7 +110,7 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s #define ANNOUNCER_NAME "Facility PA" -#define DEFAULT_JOB_TYPE /datum/job/station/assistant +#define DEFAULT_JOB_TYPE /datum/role/job/station/assistant //Assistant/Visitor/Whatever #define USELESS_JOB "Visitor" diff --git a/code/__DEFINES/mobs/characteristics.dm b/code/__DEFINES/mobs/characteristics.dm new file mode 100644 index 00000000000..2a826b65248 --- /dev/null +++ b/code/__DEFINES/mobs/characteristics.dm @@ -0,0 +1,56 @@ +//! General + +// none yet + +//! Skills + +//? skill levels. +//? These must be SEQUENTIAL FROM 1 TO X. +#define CHARACTER_SKILL_UNTRAINED 1 +#define CHARACTER_SKILL_NOVICE 2 +#define CHARACTER_SKILL_TRAINED 3 +#define CHARACTER_SKILL_EXPERIENCED 4 +#define CHARACTER_SKILL_PROFESSIONAL 5 + +#define CHARACTER_SKILL_ENUM_MIN 1 +#define CHARACTER_SKILL_ENUM_MAX 5 + +//? Skill costs +/// baseline skillpoints +#define SKILLPOINTS_BASELINE 36 +/// for a negligible gain from the last level +#define SKILLCOST_INCREMENT_NEGLIGIBLE 1 +/// for a mild gain from the last level +#define SKILLCOST_INCREMENT_MINOR 2 +/// for a moderate gain from the last level +#define SKILLCOST_INCREMENT_MODERATE 3 +/// for a major gain from the last level +#define SKILLCOST_INCREMENT_MAJOR 4 +/// for an extreme gain from the last level +#define SKILLCOST_INCREMENT_EXTREME 6 + +//? Skill scaling +/// constant * 2 ** level diff +#define SKILL_SCALING_EXPONENTIAL_HARD 1 +/// constant * level diff +#define SKILL_SCALING_LINEAR 2 +/// constant * 1.5 ** level diff +#define SKILL_SCALING_EXPONENTIAL_SOFT 3 + +//! Stats + +//? stat datatypes +/// a number +#define CHARACTER_STAT_NUMERIC "num" +/// text data +#define CHARACTER_STAT_STRING "str" +/// boolean +#define CHARACTER_STAT_BOOL "bool" +/// a datum of some kind - NOT RECOMMENDED +#define CHARACTER_STAT_DATUM "datum" +/// unknown +#define CHARACTER_STAT_UNKNOWN "unkw" + +//! Talents + +// none yet diff --git a/code/__DEFINES/persistence.dm b/code/__DEFINES/persistence.dm deleted file mode 100644 index f1d8285b0ba..00000000000 --- a/code/__DEFINES/persistence.dm +++ /dev/null @@ -1,11 +0,0 @@ -// Direct filename paths - -#define PERSISTENCE_FILE_BUNKER_PASSTHROUGH "data/persistence/bunker_passthrough.json" - -// Filenames for putting under directories - -#define PERSISTENCE_FILENAME_OBJECTS "objects.json" - -// Directories - -#define PERSISTENCE_MAP_ROOT_DIRECTORY "data/persistence/maps" diff --git a/code/__DEFINES/preferences/data_keys_character.dm b/code/__DEFINES/preferences/data_keys_character.dm index 449267e6cf3..0a6577cc64a 100644 --- a/code/__DEFINES/preferences/data_keys_character.dm +++ b/code/__DEFINES/preferences/data_keys_character.dm @@ -16,3 +16,6 @@ #define CHARACTER_DATA_JOBS "jobs" #define CHARACTER_DATA_ALT_TITLES "alt_titles" #define CHARACTER_DATA_OVERFLOW_MODE "overflow_mode" + +//? Skills +#define CHARACTER_DATA_SKILLS "skills" diff --git a/code/__DEFINES/preferences/load_order.dm b/code/__DEFINES/preferences/load_order.dm index 748ab0aec58..c9f0f3ed583 100644 --- a/code/__DEFINES/preferences/load_order.dm +++ b/code/__DEFINES/preferences/load_order.dm @@ -10,3 +10,5 @@ #define PREFERENCE_LOAD_ORDER_LORE_FACTION 55 // language loads last as intrinsincs need to load first #define PREFERENCE_LOAD_ORDER_LANGUAGE 60 +// occupations load last as lore stuff need to load first +#define PREFERENCE_LOAD_ORDER_OCCUPATIONS 70 diff --git a/code/__DEFINES/preferences/procs.dm b/code/__DEFINES/preferences/procs.dm index 6a7b98b8264..ecd12baafed 100644 --- a/code/__DEFINES/preferences/procs.dm +++ b/code/__DEFINES/preferences/procs.dm @@ -14,5 +14,5 @@ #define PREF_COPY_TO_DO_NOT_RENDER (1<<23) /// helper -#define PREF_COPY_TO_IS_SPAWNING (flags & (PREF_COPY_TO_FOR_ROUNDSTART | PREF_COPY_TO_FOR_LATEJOIN | PREF_COPY_TO_FOR_GHOSTROLE)) +#define PREF_COPYING_TO_CHECK_IS_SPAWNING(flags) (flags & (PREF_COPY_TO_FOR_ROUNDSTART | PREF_COPY_TO_FOR_LATEJOIN | PREF_COPY_TO_FOR_GHOSTROLE)) diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 0e8f06f93dd..622fe7c6efd 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -315,8 +315,7 @@ GLOBAL_LIST_INIT(testing_global_profiler, list("_PROFILE_NAME" = "Global")) M = C.mob else if(istype(whom, /datum/mind)) var/datum/mind/mind = whom - key = mind.key - ckey = ckey(key) + ckey = mind.ckey if(mind.current) M = mind.current if(M.client) diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index e2cd3f28288..3d461e80e53 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -42,7 +42,7 @@ var/datum/category_collection/underwear/global_underwear = new() //!Backpacks - The load order here is important to maintain. Don't go swapping these around. var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt", "Messenger Bag", "RIG", "Duffle Bag") var/global/list/pdachoicelist = list("Default", "Slim", "Old", "Rugged","Minimalist", "Holographic", "Wrist-Bound") -var/global/list/exclude_jobs = list(/datum/job/station/ai,/datum/job/station/cyborg) +var/global/list/exclude_jobs = list(/datum/role/job/station/ai,/datum/role/job/station/cyborg) //* Visual nets GLOBAL_LIST_EMPTY(visual_nets) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index f12963cdc39..d579c56b9f7 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -861,7 +861,7 @@ GLOBAL_LIST_EMPTY(friendly_animal_types) return 0 /* //For creating consistent icons for human looking simple animals -/proc/get_flat_human_icon(icon_id, datum/job/J, datum/preferences/prefs, dummy_key, showDirs = GLOB.cardinals, outfit_override = null) +/proc/get_flat_human_icon(icon_id, datum/role/job/J, datum/preferences/prefs, dummy_key, showDirs = GLOB.cardinals, outfit_override = null) var/static/list/humanoid_icon_cache = list() if(!icon_id || !humanoid_icon_cache[icon_id]) var/mob/living/carbon/human/dummy/body = generate_or_wait_for_human_dummy(dummy_key) diff --git a/code/__HELPERS/sorts/comparators.dm b/code/__HELPERS/sorts/comparators.dm index e5b3d726d14..aceff459102 100644 --- a/code/__HELPERS/sorts/comparators.dm +++ b/code/__HELPERS/sorts/comparators.dm @@ -122,7 +122,7 @@ GLOBAL_VAR_INIT(cmp_field, "name") /** * Sorts jobs by department, and then by flag within department. */ -/proc/cmp_job_datums(datum/job/a, datum/job/b) +/proc/cmp_job_datums(datum/role/job/a, datum/role/job/b) . = 0 if( LAZYLEN(a.departments) && LAZYLEN(b.departments) ) // Makes a list that contains only departments that were in both. diff --git a/code/controllers/configuration/entries/skills.dm b/code/controllers/configuration/entries/skills.dm new file mode 100644 index 00000000000..4f105deddc0 --- /dev/null +++ b/code/controllers/configuration/entries/skills.dm @@ -0,0 +1,5 @@ +/datum/config_entry/flag/characteristics_enabled + config_entry_value = TRUE + +/datum/config_entry/flag/characteristics_active + config_entry_value = FALSE diff --git a/code/controllers/configuration_old/configuration.dm b/code/controllers/configuration_old/configuration.dm index 12dd8415f6f..4eafe402287 100644 --- a/code/controllers/configuration_old/configuration.dm +++ b/code/controllers/configuration_old/configuration.dm @@ -48,7 +48,6 @@ var/objectives_disabled = 0 //if objectives are disabled or not var/protect_roles_from_antagonist = 0// If security and such can be traitor/cult/other var/continous_rounds = 0 // Gamemodes which end instantly will instead keep on going until the round ends by escape shuttle or nuke. - var/allow_Metadata = 0 // Metadata is supported. var/popup_admin_pm = 0 //adminPMs to non-admins show in a pop-up 'reply' window when set to 1. var/fps = 20 var/tick_limit_mc_init = TICK_LIMIT_MC_INIT_DEFAULT //SSinitialization throttling @@ -516,9 +515,6 @@ if ("feature_object_spell_system") config_legacy.feature_object_spell_system = 1 - if ("allow_metadata") - config_legacy.allow_Metadata = 1 - if ("traitor_scaling") config_legacy.traitor_scaling = 1 diff --git a/code/controllers/configuration_old/configuration_vr.dm b/code/controllers/configuration_old/configuration_vr.dm index e9f776b45bd..8fae7b7d57d 100644 --- a/code/controllers/configuration_old/configuration_vr.dm +++ b/code/controllers/configuration_old/configuration_vr.dm @@ -6,7 +6,6 @@ var/time_off = FALSE var/pto_job_change = FALSE var/pto_cap = 100 //Hours - var/require_flavor = FALSE /hook/startup/proc/read_vs_config() var/list/Lines = world.file2list("config/legacy/config.txt") @@ -45,6 +44,4 @@ config_legacy.time_off = TRUE if ("pto_job_change") config_legacy.pto_job_change = TRUE - if ("require_flavor") - config_legacy.require_flavor = TRUE return 1 diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm index d5c34875173..092b3761bf6 100644 --- a/code/controllers/subsystem.dm +++ b/code/controllers/subsystem.dm @@ -284,7 +284,7 @@ //usually called via datum/controller/subsystem/New() when replacing a subsystem (i.e. due to a recurring crash) //should attempt to salvage what it can from the old instance of subsystem /datum/controller/subsystem/Recover() - return + return TRUE /datum/controller/subsystem/vv_edit_var(var_name, var_value) switch (var_name) diff --git a/code/controllers/subsystem/asset_loading.dm b/code/controllers/subsystem/asset_loading.dm index 5010d7e13af..f51ac236352 100644 --- a/code/controllers/subsystem/asset_loading.dm +++ b/code/controllers/subsystem/asset_loading.dm @@ -5,7 +5,7 @@ */ SUBSYSTEM_DEF(asset_loading) name = "Asset Loading" - priority = FIRE_PRIORITY_ASSETS + priority = FIRE_PRIORITY_ASSET_LOADING subsystem_flags = SS_NO_INIT runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT var/list/datum/asset/generate_queue = list() diff --git a/code/controllers/subsystem/assets.dm b/code/controllers/subsystem/assets.dm index cf8c2780a98..e18fc1943a4 100644 --- a/code/controllers/subsystem/assets.dm +++ b/code/controllers/subsystem/assets.dm @@ -20,8 +20,6 @@ SUBSYSTEM_DEF(assets) transport = newtransport transport.Load() - - /datum/controller/subsystem/assets/Initialize(timeofday) for(var/type in typesof(/datum/asset)) var/datum/asset/A = type diff --git a/code/controllers/subsystem/characters/_characters.dm b/code/controllers/subsystem/characters/_characters.dm index 23009184f9e..6bd991b16e2 100644 --- a/code/controllers/subsystem/characters/_characters.dm +++ b/code/controllers/subsystem/characters/_characters.dm @@ -7,7 +7,7 @@ SUBSYSTEM_DEF(characters) name = "Characters" init_order = INIT_ORDER_CHARACTERS - priority = FIRE_PRIORITY_CHARSETUP + priority = FIRE_PRIORITY_CHARACTERS subsystem_flags = SS_BACKGROUND wait = 1 SECOND runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT diff --git a/code/controllers/subsystem/characters/backgrounds.dm b/code/controllers/subsystem/characters/backgrounds.dm index 8a2f54a410b..c18e9e46214 100644 --- a/code/controllers/subsystem/characters/backgrounds.dm +++ b/code/controllers/subsystem/characters/backgrounds.dm @@ -45,21 +45,25 @@ tim_sort(character_religions, /proc/cmp_auto_compare, TRUE) tim_sort(character_factions, /proc/cmp_auto_compare, TRUE) -/datum/controller/subsystem/characters/proc/available_citizenships(species_id) +/datum/controller/subsystem/characters/proc/available_citizenships(species_id, category) . = list() for(var/id in character_citizenships) var/datum/lore/character_background/citizenship/L = character_citizenships[id] + if(category && (L.category != category)) + continue if(L.check_species_id(species_id)) . += L -/datum/controller/subsystem/characters/proc/available_religions(species_id) +/datum/controller/subsystem/characters/proc/available_religions(species_id, category) . = list() for(var/id in character_religions) var/datum/lore/character_background/religion/L = character_religions[id] + if(category && (L.category != category)) + continue if(L.check_species_id(species_id)) . += L -/datum/controller/subsystem/characters/proc/available_factions(species_id, origin_id, citizenship_id) +/datum/controller/subsystem/characters/proc/available_factions(species_id, origin_id, citizenship_id, category) . = list() for(var/id in character_factions) var/datum/lore/character_background/faction/L = character_factions[id] @@ -67,6 +71,8 @@ continue if(L.citizenship_whitelist && !(citizenship_id in L.citizenship_whitelist)) continue + if(category && (L.category != category)) + continue if(L.check_species_id(species_id)) . += L @@ -79,30 +85,30 @@ if(L.check_species_id(species_id)) . += L -/datum/controller/subsystem/characters/proc/resolve_citizenship(id) +/datum/controller/subsystem/characters/proc/resolve_citizenship(id_or_typepath) RETURN_TYPE(/datum/lore/character_background/citizenship) - if(ispath(id)) - var/datum/lore/character_background/bg = id - id = initial(bg.id) - return character_citizenships[id] + if(ispath(id_or_typepath)) + var/datum/lore/character_background/bg = id_or_typepath + id_or_typepath = initial(bg.id) + return character_citizenships[id_or_typepath] -/datum/controller/subsystem/characters/proc/resolve_faction(id) +/datum/controller/subsystem/characters/proc/resolve_faction(id_or_typepath) RETURN_TYPE(/datum/lore/character_background/faction) - if(ispath(id)) - var/datum/lore/character_background/bg = id - id = initial(bg.id) - return character_factions[id] + if(ispath(id_or_typepath)) + var/datum/lore/character_background/bg = id_or_typepath + id_or_typepath = initial(bg.id) + return character_factions[id_or_typepath] -/datum/controller/subsystem/characters/proc/resolve_religion(id) +/datum/controller/subsystem/characters/proc/resolve_religion(id_or_typepath) RETURN_TYPE(/datum/lore/character_background/religion) - if(ispath(id)) - var/datum/lore/character_background/bg = id - id = initial(bg.id) - return character_religions[id] + if(ispath(id_or_typepath)) + var/datum/lore/character_background/bg = id_or_typepath + id_or_typepath = initial(bg.id) + return character_religions[id_or_typepath] -/datum/controller/subsystem/characters/proc/resolve_origin(id) +/datum/controller/subsystem/characters/proc/resolve_origin(id_or_typepath) RETURN_TYPE(/datum/lore/character_background/origin) - if(ispath(id)) - var/datum/lore/character_background/bg = id - id = initial(bg.id) - return character_origins[id] + if(ispath(id_or_typepath)) + var/datum/lore/character_background/bg = id_or_typepath + id_or_typepath = initial(bg.id) + return character_origins[id_or_typepath] diff --git a/code/controllers/subsystem/job/_job.dm b/code/controllers/subsystem/job/_job.dm index 3f62678d064..185916fa6fe 100644 --- a/code/controllers/subsystem/job/_job.dm +++ b/code/controllers/subsystem/job/_job.dm @@ -6,7 +6,7 @@ SUBSYSTEM_DEF(job) /// List of all jobs var/list/occupations /// Dict of all jobs, keys are titles - var/list/datum/job/name_occupations + var/list/datum/role/job/name_occupations /// Dict of all jobs, keys are types var/list/type_occupations /// jobs by id @@ -43,7 +43,7 @@ SUBSYSTEM_DEF(job) // todo: this is shit but it works job_pref_ui_cache = list() for(var/id in job_lookup) - var/datum/job/J = job_lookup[id] + var/datum/role/job/J = job_lookup[id] if(!(J.join_types & JOB_ROUNDSTART)) continue var/faction = J.faction @@ -67,13 +67,13 @@ SUBSYSTEM_DEF(job) job_lookup = list() name_occupations = list() type_occupations = list() - var/list/all_jobs = subtypesof(/datum/job) + var/list/all_jobs = subtypesof(/datum/role/job) if(!all_jobs.len) to_chat(world, SPAN_WARNING( "Error setting up jobs, no job datums found")) return FALSE for(var/J in all_jobs) - var/datum/job/job = J + var/datum/role/job/job = J if(initial(job.abstract_type) == J) continue job = new J @@ -104,7 +104,7 @@ SUBSYSTEM_DEF(job) return TRUE -/datum/controller/subsystem/job/proc/add_to_departments(datum/job/J) +/datum/controller/subsystem/job/proc/add_to_departments(datum/role/job/J) // Adds to the regular job lists in the departments, which allow multiple departments for a job. for(var/D in J.departments) var/datum/department/dept = LAZYACCESS(department_datums, D) @@ -163,8 +163,8 @@ SUBSYSTEM_DEF(job) // Returns a reference to the primary department datum that a job is in. // Can receive job datum refs, typepaths, or job title strings. -/datum/controller/subsystem/job/proc/get_primary_department_of_job(datum/job/J) - if(!istype(J, /datum/job)) +/datum/controller/subsystem/job/proc/get_primary_department_of_job(datum/role/job/J) + if(!istype(J, /datum/role/job)) if(ispath(J)) J = job_by_type(J) else if(istext(J)) diff --git a/code/controllers/subsystem/job/_legacy_job_stuff.dm b/code/controllers/subsystem/job/_legacy_job_stuff.dm index 25e983c2e35..3e5d0665cdf 100644 --- a/code/controllers/subsystem/job/_legacy_job_stuff.dm +++ b/code/controllers/subsystem/job/_legacy_job_stuff.dm @@ -16,7 +16,7 @@ /datum/controller/subsystem/job/proc/AssignRole(mob/new_player/player, rank, latejoin = 0) job_debug("Running AR, Player: [player], Rank: [rank], LJ: [latejoin]") if(player && player.mind && rank) - var/datum/job/job = get_job(rank) + var/datum/role/job/job = get_job(rank) var/reasons = job.check_client_availability_one(player.client) if(reasons != ROLE_AVAILABLE) job_debug("AR failed: player [player], rank [rank], latejoin [latejoin], failed for [reasons]") @@ -34,13 +34,13 @@ /// Making additional slot on the fly. /datum/controller/subsystem/job/proc/FreeRole(rank) - var/datum/job/job = get_job(rank) + var/datum/role/job/job = get_job(rank) if(job && job.total_positions != -1) job.total_positions++ return 1 return 0 -/datum/controller/subsystem/job/proc/FindOccupationCandidates(datum/job/job, level) +/datum/controller/subsystem/job/proc/FindOccupationCandidates(datum/role/job/job, level) job_debug("Running FOC, Job: [job], Level: [level]") var/list/candidates = list() for(var/mob/new_player/player in divide_unassigned) @@ -56,7 +56,7 @@ /datum/controller/subsystem/job/proc/GiveRandomJob(mob/new_player/player) job_debug("GRJ Giving random job, Player: [player]") - for(var/datum/job/job in shuffle(occupations)) + for(var/datum/role/job/job in shuffle(occupations)) var/reasons = job.check_client_availability_one(player.client) if(reasons != ROLE_AVAILABLE) job_debug("GRJ failed for [reasons] on [job.id]") @@ -75,7 +75,7 @@ /datum/controller/subsystem/job/proc/FillHeadPosition() for(var/level in JOB_PRIORITY_HIGH to JOB_PRIORITY_LOW step -1) for(var/command_position in SSjob.get_job_titles_in_department(DEPARTMENT_COMMAND)) - var/datum/job/job = get_job(command_position) + var/datum/role/job/job = get_job(command_position) if(!job) continue var/list/candidates = FindOccupationCandidates(job, level) @@ -121,7 +121,7 @@ */ /datum/controller/subsystem/job/proc/CheckHeadPositions(level) for(var/command_position in SSjob.get_job_titles_in_department(DEPARTMENT_COMMAND)) - var/datum/job/job = get_job(command_position) + var/datum/role/job/job = get_job(command_position) if(!job) continue var/list/candidates = FindOccupationCandidates(job, level) @@ -145,7 +145,7 @@ //Holder for Triumvirate is stored in the SSticker, this just processes it if(SSticker && SSticker.triai) - for(var/datum/job/A in occupations) + for(var/datum/role/job/A in occupations) if(A.title == "AI") A.spawn_positions = 3 break @@ -162,7 +162,7 @@ //People who wants to be assistants, sure, go on. job_debug("DO, Running Assistant Check 1") - var/datum/job/assist = new DEFAULT_JOB_TYPE () + var/datum/role/job/assist = new DEFAULT_JOB_TYPE () var/list/assistant_candidates = FindOccupationCandidates(assist, JOB_PRIORITY_HIGH) job_debug("AC1, Candidates: [assistant_candidates.len]") for(var/mob/new_player/player in assistant_candidates) @@ -195,7 +195,7 @@ for(var/mob/new_player/player in divide_unassigned) // Loop through all jobs - for(var/datum/job/job in shuffledoccupations) // SHUFFLE ME BABY + for(var/datum/role/job/job in shuffledoccupations) // SHUFFLE ME BABY if(job.title in SSticker.mode.disabled_jobs) continue var/reasons = job.check_client_availability_one(player.client) @@ -241,7 +241,7 @@ if(!H) return null - var/datum/job/job = get_job(rank) + var/datum/role/job/job = get_job(rank) var/list/spawn_in_storage = list() var/real_species_name = H.species.name @@ -486,7 +486,7 @@ continue if(name && value) - var/datum/job/J = get_job(name) + var/datum/role/job/J = get_job(name) if(!J) continue J.total_positions = text2num(value) J.spawn_positions = text2num(value) @@ -497,7 +497,7 @@ /datum/controller/subsystem/job/proc/HandleFeedbackGathering() - for(var/datum/job/job in occupations) + for(var/datum/role/job/job in occupations) var/tmp_str = "|[job.title]|" var/level1 = 0 //high @@ -532,7 +532,7 @@ var/fail_deadly = FALSE - var/datum/job/J = SSjob.get_job(rank) + var/datum/role/job/J = SSjob.get_job(rank) fail_deadly = J?.offmap_spawn var/preferred_method var/datum/spawnpoint/spawnpos diff --git a/code/controllers/subsystem/job/jexp.dm b/code/controllers/subsystem/job/jexp.dm index 141086fa28f..a0f497d491e 100644 --- a/code/controllers/subsystem/job/jexp.dm +++ b/code/controllers/subsystem/job/jexp.dm @@ -11,9 +11,9 @@ */ /client/proc/has_jexp_bypass() SHOULD_NOT_SLEEP(TRUE) - return !!(admin_datums[ckey] || (database.player_flags & PLAYER_FLAG_JEXP_EXEMPT)) + return !!(admin_datums[ckey] || (player.player_flags & PLAYER_FLAG_JEXP_EXEMPT)) /client/proc/has_jexp_bypass_blocking() - database.block_on_available() - return !!(admin_datums[ckey] || (database.player_flags & PLAYER_FLAG_JEXP_EXEMPT)) + player.block_on_available() + return !!(admin_datums[ckey] || (player.player_flags & PLAYER_FLAG_JEXP_EXEMPT)) diff --git a/code/controllers/subsystem/job/job_manager.dm b/code/controllers/subsystem/job/job_manager.dm index d6f34440d02..bbea024f340 100644 --- a/code/controllers/subsystem/job/job_manager.dm +++ b/code/controllers/subsystem/job/job_manager.dm @@ -2,23 +2,23 @@ /datum/controller/subsystem/job /datum/controller/subsystem/job/proc/job_by_id(id) - RETURN_TYPE(/datum/job) + RETURN_TYPE(/datum/role/job) return job_lookup[id] /datum/controller/subsystem/job/proc/job_by_type(path) - RETURN_TYPE(/datum/job) + RETURN_TYPE(/datum/role/job) return type_occupations[path] // todo: this should not be used most of the time, id/type is better /datum/controller/subsystem/job/proc/job_by_title(title) - RETURN_TYPE(/datum/job) + RETURN_TYPE(/datum/role/job) return name_occupations[title] /datum/controller/subsystem/job/proc/all_job_ids(faction) RETURN_TYPE(/list) . = list() if(faction) - for(var/datum/job/J as anything in occupations) + for(var/datum/role/job/J as anything in occupations) if(J.faction != faction) continue . += J.id @@ -30,7 +30,7 @@ RETURN_TYPE(/list) . = list() if(faction) - for(var/datum/job/J as anything in occupations) + for(var/datum/role/job/J as anything in occupations) if(J.faction != faction) continue . += J.type @@ -43,7 +43,7 @@ RETURN_TYPE(/list) . = list() if(faction) - for(var/datum/job/J as anything in occupations) + for(var/datum/role/job/J as anything in occupations) if(J.faction != faction) continue . += J.title @@ -55,10 +55,10 @@ RETURN_TYPE(/list) . = list() if(faction) - for(var/datum/job/J as anything in occupations) + for(var/datum/role/job/J as anything in occupations) if(J.faction != faction) continue . += J else - for(var/datum/job/J as anything in occupations) + for(var/datum/role/job/J as anything in occupations) . += J diff --git a/code/controllers/subsystem/job/joining.dm b/code/controllers/subsystem/job/joining.dm index 009201c7544..9cf7c50a7cf 100644 --- a/code/controllers/subsystem/job/joining.dm +++ b/code/controllers/subsystem/job/joining.dm @@ -1,5 +1,5 @@ /* -/datum/controller/subsystem/job/proc/ProcessRoundstartPlayer(mob/M, datum/job/J, loadout = TRUE, client/C) +/datum/controller/subsystem/job/proc/ProcessRoundstartPlayer(mob/M, datum/role/job/J, loadout = TRUE, client/C) // autodetect if(!C) C = M.client @@ -16,7 +16,7 @@ SendToRoundstart(M, C, J) PostJoin(M, J, C, FALSE) -/datum/controller/subsystem/job/proc/ProcessLatejoinPlayer(mob/M, datum/job/J, loadout = TRUE, client/C) +/datum/controller/subsystem/job/proc/ProcessLatejoinPlayer(mob/M, datum/role/job/J, loadout = TRUE, client/C) // autodetect if(!C) C = M.client @@ -33,7 +33,7 @@ SendToLatejoin(M, C, job = J) PostJoin(M, J, C, TRUE) -/datum/controller/subsystem/job/proc/GreetPlayer(mob/M, datum/job/J, latejoin, client/C) +/datum/controller/subsystem/job/proc/GreetPlayer(mob/M, datum/role/job/J, latejoin, client/C) var/client/output = C || M.client if(!J) return @@ -52,7 +52,7 @@ to_chat(output, "Your account ID is [wageslave.account_id].") M.add_memory("Your account ID is [wageslave.account_id].") -/datum/controller/subsystem/job/proc/EquipPlayer(mob/M, datum/job/J, loadout = TRUE, datum/preferences/prefs, announce, latejoin, client/C) +/datum/controller/subsystem/job/proc/EquipPlayer(mob/M, datum/role/job/J, loadout = TRUE, datum/preferences/prefs, announce, latejoin, client/C) if(!istype(J)) J = GetJobAuto(J) ASSERT(istype(J)) @@ -73,7 +73,7 @@ HandleLoadoutLeftovers(M, leftovers, null, C) -/datum/controller/subsystem/job/proc/PostJoin(mob/M, datum/job/J, client/C, latejoin) +/datum/controller/subsystem/job/proc/PostJoin(mob/M, datum/role/job/J, client/C, latejoin) // job handling if(J) SSpersistence.antag_rep_change[M.client.ckey] += J.GetAntagRep() @@ -110,7 +110,7 @@ if(latejoin) AnnounceJoin(M, J, C) -/datum/controller/subsystem/job/proc/AnnounceJoin(mob/M, datum/job/J, client/C) +/datum/controller/subsystem/job/proc/AnnounceJoin(mob/M, datum/role/job/J, client/C) if(istype(get_area(M), /area/shuttle/arrival) && SSshuttle.arrivals) SSshuttle.arrivals.QueueAnnounce(M, J.title) else @@ -123,7 +123,7 @@ * - latejoin - latejoining mob? * - force - bypass checks */ -/datum/controller/subsystem/job/proc/Assign(datum/mind/M, datum/job/J, latejoin = FALSE, force = FALSE) +/datum/controller/subsystem/job/proc/Assign(datum/mind/M, datum/role/job/J, latejoin = FALSE, force = FALSE) if(ismob(M)) var/mob/_M = M M = _M.mind @@ -145,7 +145,7 @@ J.current_positions++ return TRUE -/datum/controller/subsystem/job/proc/CanAssign(M, datum/job/J, latejoin) +/datum/controller/subsystem/job/proc/CanAssign(M, datum/role/job/J, latejoin) var/mob/checking = ismob(M) && M if(!checking) if(istype(M, /datum/mind)) @@ -175,7 +175,7 @@ */ /datum/controller/subsystem/job/proc/SendToLatejoin(mob/M, client/C = M.client, faction, job, method, override) if(!override && M.mind?.assigned_role) - var/datum/job/J = SSjob.GetJobName(M.mind.assigned_role) + var/datum/role/job/J = SSjob.GetJobName(M.mind.assigned_role) if(J) faction = J.faction job = J.GetID() @@ -193,7 +193,7 @@ subsystem_log(error_message) CRASH(error_message) // this is serious. -/datum/controller/subsystem/job/proc/SendToRoundstart(mob/M, client/C, datum/job/J) +/datum/controller/subsystem/job/proc/SendToRoundstart(mob/M, client/C, datum/role/job/J) var/atom/movable/landmark/spawnpoint/S = GetRoundstartSpawnpoint(M, C, J.GetID(), J.faction) if(!S) stack_trace("Couldn't find a roundstart spawnpoint for [M] ([C]) - [J.type] ([J.faction]).") @@ -206,7 +206,7 @@ /datum/controller/subsystem/job/proc/handle_auto_deadmin_roles(client/C, rank) if(!C?.holder) return TRUE - var/datum/job/job = GetJobAuto(rank) + var/datum/role/job/job = GetJobAuto(rank) if(!job) return if((job.auto_deadmin_role_flags & DEADMIN_POSITION_HEAD) && (CONFIG_GET(flag/auto_deadmin_heads) || (C.prefs?.deadmin & DEADMIN_POSITION_HEAD))) diff --git a/code/controllers/subsystem/job/roundstart.dm b/code/controllers/subsystem/job/roundstart.dm index 7c2651ba752..327d5a29474 100644 --- a/code/controllers/subsystem/job/roundstart.dm +++ b/code/controllers/subsystem/job/roundstart.dm @@ -41,7 +41,7 @@ // i'm going to figure out if i can speed it up BEFORE rewriting everything. /* -/datum/controller/subsystem/job/proc/FindOccupationCandidates(datum/job/job, level, flag) +/datum/controller/subsystem/job/proc/FindOccupationCandidates(datum/role/job/job, level, flag) JobDebug("Running FOC, Job: [job], Level: [level], Flag: [flag]") var/list/candidates = list() for(var/mob/new_player/player in unassigned) @@ -71,7 +71,7 @@ /datum/controller/subsystem/job/proc/GiveRandomJob(mob/new_player/player) JobDebug("GRJ Giving random job, Player: [player]") . = FALSE - for(var/datum/job/job in shuffle(GetAllJobs())) + for(var/datum/role/job/job in shuffle(GetAllJobs())) if(!job) continue @@ -124,7 +124,7 @@ //This is basically to ensure that there's atleast a few heads in the round /datum/controller/subsystem/job/proc/FillHeadPosition() for(var/level in level_order) - for(var/datum/job/job as anything in GetDepartmentJobDatums(/datum/department/command)) + for(var/datum/role/job/job as anything in GetDepartmentJobDatums(/datum/department/command)) if(!job) continue if((job.current_positions >= job.total_positions) && job.total_positions != -1) @@ -140,7 +140,7 @@ //This proc is called at the start of the level loop of DivideOccupations() and will cause head jobs to be checked before any other jobs of the same level //This is also to ensure we get as many heads as possible /datum/controller/subsystem/job/proc/CheckHeadPositions(level) - for(var/datum/job/job as anything in GetDepartmentJobDatums(/datum/department/command)) + for(var/datum/role/job/job as anything in GetDepartmentJobDatums(/datum/department/command)) if(!job) continue if((job.current_positions >= job.total_positions) && job.total_positions != -1) @@ -153,7 +153,7 @@ /datum/controller/subsystem/job/proc/FillAIPosition() var/ai_selected = 0 - var/datum/job/job = GetJobType(/datum/job/ai) + var/datum/role/job/job = GetJobType(/datum/role/job/ai) if(!job) return 0 for(var/i = job.total_positions, i > 0, i--) @@ -179,7 +179,7 @@ //Holder for Triumvirate is stored in the SSticker, this just processes it if(SSticker.triai) - for(var/datum/job/ai/A in GetAllJobs()) + for(var/datum/role/job/ai/A in GetAllJobs()) A.roundstart_positions = 3 var/left = 2 for(var/atom/movable/landmark/spawnpoint/job/ai/secondary/S in GetAllSpawnpoints()) @@ -217,7 +217,7 @@ //People who wants to be the overflow role, sure, go on. JobDebug("DO, Running Overflow Check 1") - var/datum/job/overflow = GetJobName(SSjob.overflow_role) + var/datum/role/job/overflow = GetJobName(SSjob.overflow_role) var/list/overflow_candidates = FindOccupationCandidates(overflow, JP_LOW) JobDebug("AC1, Candidates: [overflow_candidates?.len]") for(var/mob/new_player/player in overflow_candidates) @@ -256,7 +256,7 @@ RejectPlayer(player) // Loop through all jobs - for(var/datum/job/job in shuffledoccupations) // SHUFFLE ME BABY + for(var/datum/role/job/job in shuffledoccupations) // SHUFFLE ME BABY if(!job) continue @@ -315,7 +315,7 @@ for(var/required_group in required_jobs) var/group_ok = TRUE for(var/rank in required_group) - var/datum/job/J = GetJobName(rank) + var/datum/role/job/J = GetJobName(rank) if(!J) SSticker.mode.setup_error = "Invalid job [rank] in gamemode required jobs." return FALSE @@ -352,7 +352,7 @@ /datum/controller/subsystem/job/proc/setup_officer_positions() - var/datum/job/J = SSjob.GetJobType(/datum/job/officer) + var/datum/role/job/J = SSjob.GetJobType(/datum/role/job/officer) if(!J) CRASH("setup_officer_positions(): Security officer job is missing") diff --git a/code/controllers/subsystem/persist_vr.dm b/code/controllers/subsystem/persist_vr.dm index 36745c3b41e..dcb1b738d0b 100644 --- a/code/controllers/subsystem/persist_vr.dm +++ b/code/controllers/subsystem/persist_vr.dm @@ -34,7 +34,7 @@ SUBSYSTEM_DEF(persist) continue // Try and detect job and department of mob - var/datum/job/J = detect_job(M) + var/datum/role/job/J = detect_job(M) if(!istype(J) || !J.pto_type || !J.timeoff_factor) if (MC_TICK_CHECK) return diff --git a/code/controllers/subsystem/persistence/objects/characters.dm b/code/controllers/subsystem/persistence/objects/characters.dm new file mode 100644 index 00000000000..45980eafacd --- /dev/null +++ b/code/controllers/subsystem/persistence/objects/characters.dm @@ -0,0 +1,248 @@ +/** + * ? Character Persistence System + */ +/datum/controller/subsystem/persistence + /// loaded characters - "[id]" = /datum/character instance + var/list/character_cache = list() + +/** + * flushes a character to db + * a new character is valid to save this way. + * + * @params + * * char - character datum + * * persisting - update persistence info if mob is given + */ +/datum/controller/subsystem/persistence/proc/save_character(datum/character/char, mob/persisting) + // pause admin proccall guard + var/__oldusr = usr + usr = null + // section below can never be allowed to runtime + + // if we have id, we're updating + if(char.character_id) + // last played is not updated by this proc + // everything else can though! + var/datum/db_query/update_query = SSdbcore.NewQuery( + "UPDATE [format_table_name("character")] \ + SET[persisting? " last_persisted = NOW()," : ""] canonical_name = :name, persist_data = :data, \ + playerid = :pid \ + WHERE id = :id", + list( + "id" = char.character_id, + "pid" = char.player_id, + "name" = ckey(char.canonical_name), + "data" = persisting? json_encode(char.make_persist_data(persisting)) : json_encode(list()), + ) + ) + update_query.Execute(async = FALSE) + qdel(update_query) + else + var/datum/db_query/insert_query = SSdbcore.NewQuery( + "INSERT INTO [format_table_name("character")] \ + (`created`, `last_played`, `last_persisted`, `playerid`, `canonical_name`, \ + `persist_data`, `character_type`) \ + VALUES (NOW(), NULL, [persisting? "NOW" : "NULL"], :pid, :name, :data, :type)", + list( + "pid" = char.player_id, + "name" = ckey(char.canonical_name), + "data" = persisting? json_encode(char.make_persist_data(persisting)) : json_encode(list()), + "type" = char.character_type, + ), + ) + insert_query.Execute(async = FALSE) + char.character_id = isnum(insert_query.last_insert_id)? insert_query.last_insert_id : text2num(insert_query.last_insert_id) + qdel(insert_query) + // fetch our ID immediately to repopulate + fetch_character(char.character_id, TRUE) + + // resume admin proccall guard + usr = __oldusr + +/** + * fetches a character datum + * you should not hold references to it yourself + * refetch when you need it! + * + * @params + * * id - character id + * * force - reload from sql if it's in cache + */ +/datum/controller/subsystem/persistence/proc/fetch_character(id, force = FALSE) + ASSERT(isnum(id)) + + // pause admin proccall guard + var/__oldusr = usr + usr = null + // section below can never be allowed to runtime + + var/datum/character/loaded = character_cache[num2text(id, 16)] + if(!force && loaded) + return loaded + + var/datum/db_query/load_query = SSdbcore.NewQuery( + "SELECT `created`, `last_played`, `last_persisted`, `playerid`, `canonical_name`, `persist_data`, `character_type` FROM \ + [format_table_name("character")] WHERE id = :id", + list( + "id" = id, + ) + ) + load_query.Execute(async = FALSE) + + if(!load_query.NextRow()) + character_cache -= num2text(id, 16) + qdel(load_query) + return null + + var/char_type = load_query.item[7] + var/datum_type = character_type_to_datum_path(char_type) + + if(!datum_type) + . = null + CRASH("unexpected char_type: [char_type]") + + // one's there, make one if it isn't already there + if(!istype(loaded, datum_type)) + character_cache[num2text(id, 16)] = (loaded = new datum_type) + + loaded.character_id = id + loaded.player_id = text2num(load_query.item[4]) + loaded.created_at = load_query.item[1] + loaded.played_at = load_query.item[2] + loaded.persisted_at = load_query.item[3] + loaded.canonical_name = load_query.item[5] + loaded.read_persist_data(load_query.item[6]? safe_json_decode(load_query.item[6], list()) : list()) + + . = loaded + + qdel(load_query) + + // resume admin proccall guard + usr = __oldusr + +/** + * returns a list of character ids for a player + * + * @params + * * playerid - player id + * * fetch - fetch the character datums in the process + * * force - forcefully fetch the character even if it's cached + */ +/datum/controller/subsystem/persistence/proc/query_characters(playerid, fetch = FALSE, force = FALSE) + ASSERT(isnum(playerid)) + + // pause admin proccall guard + var/__oldusr = usr + usr = null + // section below can never be allowed to runtime + + . = list() + var/datum/db_query/iteration_query = SSdbcore.ExecuteQuery( + "SELECT id FROM [format_table_name("character")] WHERE playerid = :id", + list( + "id" = playerid + ) + ) + while(iteration_query.NextRow()) + . += text2num(iteration_query.item[1]) + if(!length(.)) + return + + // resume admin proccall guard + usr = __oldusr + + // fetch if needed + if(fetch) + for(var/id in .) + fetch_character(id, force) + +/** + * mark a character as having played + * + * @params + * * id - character id + */ +/datum/controller/subsystem/persistence/proc/character_played(id) + ASSERT(isnum(id)) + + // pause admin proccall guard + var/__oldusr = usr + usr = null + // section below can never be allowed to runtime + + var/datum/db_query/mark_query = SSdbcore.ExecuteQuery( + "UPDATE [format_table_name("character")] SET last_played = NOW() WHERE id = :id", + list( + "id" = id + ) + ) + . = !!mark_query.affected + + // resume admin proccall guard + usr = __oldusr + +/** + * hardcoded switch: what character type string corrosponds to what /datum/character + */ +/datum/controller/subsystem/persistence/proc/character_type_to_datum_path(what) + switch(what) + if(OBJECT_PERSISTENCE_CHARACTER_TYPE_HUMAN) + return /datum/character/human + +/datum/character + abstract_type = /datum/character + /// our character id, if we're already in the sql database + var/character_id + /// character type - should never change + var/character_type + /// our player id + var/player_id + /// our ckey(name) - used to avoid spaces/whatever getting in the way + var/canonical_name + /// created - SQL datetime - not modifiable + var/created_at + /// last played SQL datetime - not modifiable directly, use proc + var/played_at + /// last persisted SQL datetime - not modifiable directly + var/persisted_at + +/** + * reads from a given mob + * + * this *is* allowed to touch the mob's /datum/mind! + */ +/datum/character/proc/read_from(mob/M) + return + +/** + * writes to a given mob + * + * this *is* allowed to touch the mob's /datum/mind! + */ +/datum/character/proc/write_to(mob/M) + return + +/** + * gets data to persist + * + * @return list of k-v entries + */ +/datum/character/proc/make_persist_data(mob/M) + return list() + +/** + * loads fields from persisting data + */ +/datum/character/proc/read_persist_data(list/data) + return + +/** + * changes the name of this character + * only ever change names this way, this'll handle the necessary updates, within the subsystem and on /datum/player's. + */ +/datum/character/proc/immediate_rename(new_name) + canonical_name = ckey(new_name) + SSpersistence.save_character(src) + +/datum/character/human + character_type = OBJECT_PERSISTENCE_CHARACTER_TYPE_HUMAN diff --git a/code/controllers/subsystem/persistence/objects/unique_string.dm b/code/controllers/subsystem/persistence/objects/unique_string.dm index e60dc326c71..bab43458ad3 100644 --- a/code/controllers/subsystem/persistence/objects/unique_string.dm +++ b/code/controllers/subsystem/persistence/objects/unique_string.dm @@ -59,7 +59,7 @@ //! Why the usr fuckery? Because we intentionally wish to obfuscate admin proccalls, since we properly sanitize **everything** in these procs. -/datum/controller/subsystem/persistence/proc/LoadString(group = OBJECT_PERSISTENCE_STRING_GROUP_NULL, key) +/datum/controller/subsystem/persistence/proc/LoadString(group = OBJECT_PERSISTENCE_GROUP_NONE, key) if(!SSdbcore.Connect()) return var/oldusr = usr @@ -78,7 +78,7 @@ . = query.item[1] qdel(query) -/datum/controller/subsystem/persistence/proc/SaveString(group = OBJECT_PERSISTENCE_STRING_GROUP_NULL, key, value) +/datum/controller/subsystem/persistence/proc/SaveString(group = OBJECT_PERSISTENCE_GROUP_NONE, key, value) if(!SSdbcore.Connect()) return var/oldusr = usr diff --git a/code/controllers/subsystem/prototypes/_prototypes.dm b/code/controllers/subsystem/prototypes/_prototypes.dm deleted file mode 100644 index db94bb81e9a..00000000000 --- a/code/controllers/subsystem/prototypes/_prototypes.dm +++ /dev/null @@ -1,50 +0,0 @@ -//! This file is WIP and currently unused. -/** - * yaml prototype loader, now with blackjack and hookers - * - * someone from ss14 come put me out of my misery please - */ -SUBSYSTEM_DEF(prototypes) - name = "Prototypes" - init_order = INIT_ORDER_PROTOTYPES - subsystem_flags = SS_NO_FIRE - - /// prototype cache - var/list/prototypes - -/datum/controller/subsystem/prototypes/Initialize() - Reload() - return ..() - -/datum/controller/subsystem/prototypes/Recover() - Reload() - return ..() - -/datum/controller/subsystem/prototypes/proc/Reload() - subsystem_log("reloading...") - prototypes = list() - var/list/walking = list("prototypes/") - for(var/dir in walking) - var/list/files = flist(dir) - for(var/path in files) - if(path[length(path)] == "/") - walking += dir + path - else - Load(dir + path) - -/datum/controller/subsystem/prototypes/proc/Load(fname) - if(!fexists(fname)) - CRASH("failed to load filename [fname]") - var/yaml = file2text(file(fname)) - var/list/L = yaml_decode(yaml) - subsystem_log("loading [fname]") - -/datum/controller/subsystem/prototypes/proc/Type(t) - switch(t) - if(YAML_PROTOTYPE_LORE) - return /datum/prototype/lore - if(YAML_PROTOTYPE_DUD) - return /datum/prototype/dud - -/datum/controller/subsystem/prototypes/proc/Resolve(domain, id) - return prototypes[domain]?[id] diff --git a/code/controllers/subsystem/prototypes/dud.dm b/code/controllers/subsystem/prototypes/dud.dm deleted file mode 100644 index b7fc1be0879..00000000000 --- a/code/controllers/subsystem/prototypes/dud.dm +++ /dev/null @@ -1,7 +0,0 @@ -/datum/prototype/dud - domain = YAML_PROTOTYPE_DUD - - var/list/read - -/datum/prototype/dud/Read(list/data) - read = data.Copy() diff --git a/code/controllers/subsystem/prototypes/lore.dm b/code/controllers/subsystem/prototypes/lore.dm deleted file mode 100644 index 4744149725d..00000000000 --- a/code/controllers/subsystem/prototypes/lore.dm +++ /dev/null @@ -1,16 +0,0 @@ -/datum/prototype/lore - domain = YAML_PROTOTYPE_LORE - -/datum/prototype/lore/Read(list/data) - - -/datum/lore_shard - -/** - * has a fleet - */ -/datum/lore_shard/fleet - -/** - * - */ diff --git a/code/controllers/subsystem/prototypes/prototype.dm b/code/controllers/subsystem/prototypes/prototype.dm deleted file mode 100644 index 3838d5ddee8..00000000000 --- a/code/controllers/subsystem/prototypes/prototype.dm +++ /dev/null @@ -1,19 +0,0 @@ -/** - * lightweight datums that load - * prototype data based on type - * and do some processing on them to get - * important tidbits out, as well as - * doing semantic linking when needed. - */ -/datum/prototype - /// type but we can't call it type :( - var/domain - /// id - var/id - -/datum/prototype/New(id, list/data) - src.id = id - Initialize(data) - -/datum/prototype/proc/Initialize(list/data) - return diff --git a/code/controllers/subsystem/radiation.dm b/code/controllers/subsystem/radiation.dm index 03b9de1d8ea..5b36c2af659 100644 --- a/code/controllers/subsystem/radiation.dm +++ b/code/controllers/subsystem/radiation.dm @@ -5,6 +5,7 @@ SUBSYSTEM_DEF(radiation) name = "Radiation" + priority = FIRE_PRIORITY_RADIATION subsystem_flags = SS_NO_INIT | SS_BACKGROUND wait = 1 SECONDS diff --git a/code/controllers/subsystem/repository.dm b/code/controllers/subsystem/repository.dm new file mode 100644 index 00000000000..26e3a6b0a30 --- /dev/null +++ b/code/controllers/subsystem/repository.dm @@ -0,0 +1,102 @@ +// TODO: file unticked +// see [code/datums/prototype.dm] for why. + +/** + * global singleton storage and fetcher + */ +SUBSYSTEM_DEF(repository) + name = "Repository" + subsystem_flags = SS_NO_FIRE + init_order = INIT_ORDER_REPOSITORY + + /// by-type lookup + var/list/type_lookup + /// by-id lookup + var/list/uid_lookup + /// fetched subtype lists + var/list/subtype_lists + +/datum/controller/subsystem/repository/Initialize() + uid_lookup = list() + type_lookup = list() + subtype_lists = list() + generate() + return ..() + +/datum/controller/subsystem/repository/Recover() + . = ..() + src.type_lookup = SSrepository.type_lookup + if(!islist(src.type_lookup)) + src.type_lookup = list() + . = FALSE + src.uid_lookup = SSrepository.uid_lookup + if(!islist(src.uid_lookup)) + src.uid_lookup = list() + . = FALSE + +/** + * prototypes returned should generally not be modified. + * prototypes returned from a typepath input should never, ever be modified. + */ +/datum/controller/subsystem/repository/proc/fetch(datum/prototype/type_or_id) + if(isnull(type_or_id)) + return + if(istext(type_or_id)) + return uid_lookup[type_or_id] + . = type_lookup[type_or_id] + if(.) + return + // types are complicated, is it lazy? + if(initial(type_or_id.lazy)) + // if so, init it + register_internal((. = new type_or_id), TRUE, TRUE) + else + CRASH("failed to fetch a hardcoded prototype") + +/** + * lists returned should never, ever be modified. + * this fetches subtypes, not the first type on purpose. + */ +/datum/controller/subsystem/repository/proc/fetch_subtypes(path) + RETURN_TYPE(/list) + ASSERT(ispath(path, /datum/prototype)) + if(subtype_lists[path]) + return subtype_lists[path] + var/list/generating = list() + subtype_lists[path] = generating + for(var/fetching as anything in subtypesof(path)) + var/datum/prototype/instance = fetch(fetching) + generating += instance + return generating + +/datum/controller/subsystem/repository/proc/register(datum/prototype/instance, force) + return register_internal(instance, force, FALSE) + +/datum/controller/subsystem/repository/proc/register_internal(datum/prototype/instance, force, hardcoded) + PRIVATE_PROC(TRUE) + if(uid_lookup[instance] && !force) + return FALSE + uid_lookup[instance] = instance + if(hardcoded) + type_lookup[instance.type] = instance + return TRUE + +/datum/controller/subsystem/repository/proc/unregister(datum/prototype/instance) + if(type_lookup[instance.type] == instance) + CRASH("tried to unregister a hardcoded instance") + if(!instance.unregister()) + CRASH("instance refused to unregister. this is undefined behavior.") + uid_lookup -= instance.uid + return TRUE + +/** + * regenerates entries, kicking out anything that's in the way + */ +/datum/controller/subsystem/repository/proc/generate() + for(var/datum/prototype/instance as anything in subtypesof(/datum/prototype)) + if(initial(instance.abstract_type) == instance) + continue + if(initial(instance.lazy)) + continue + instance = new instance + register_internal(instance, TRUE, TRUE) diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm index 112e55a7587..300da509d8b 100644 --- a/code/controllers/subsystem/statpanel.dm +++ b/code/controllers/subsystem/statpanel.dm @@ -58,18 +58,16 @@ SUBSYSTEM_DEF(statpanels) var/list/additional = player._statpanel_data() // server data has priority // assert primary status tab - var/server_data + var/server_data = "%5b%5d" // "[]" if(player.statpanel_tab("Status", TRUE)) server_data = cache_server_data // assert admin tabs - these are special and do not check for additional info - else if(player.statpanel_tab("MC", is_admin)) + if(player.statpanel_tab("MC", is_admin)) server_data = fetch_mc_data() - else if(player.statpanel_tab("Tickets", is_admin)) + if(player.statpanel_tab("Tickets", is_admin)) server_data = fetch_ticket_data() - else if(player.statpanel_tab("SDQL2", is_admin && length(GLOB.sdql2_queries))) + if(player.statpanel_tab("SDQL2", is_admin && length(GLOB.sdql2_queries))) server_data = fetch_sdql2_data() - else - server_data = "%5b%5d" // "[]" // send additional player << output("[server_data];[url_encode(json_encode(additional))]", "statbrowser:byond_update") diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 7ee887a0bab..c49135d6690 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -605,10 +605,10 @@ SUBSYSTEM_DEF(ticker) 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])" + total_antagonists[temprole] += ", [Mind.name]([Mind.ckey])" 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])" + total_antagonists[temprole] += ": [Mind.name]([Mind.ckey])" //Now print them all into the log! log_game("Antagonists at round end were...") diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index b8ff8476447..89dda9afb6c 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -102,7 +102,7 @@ break isactive[name] = active ? "Active" : "Inactive" - var/datum/job/J = SSjob.get_job(real_rank) + var/datum/role/job/J = SSjob.get_job(real_rank) if(J?.offmap_spawn) off[name] = rank @@ -310,7 +310,7 @@ GLOBAL_LIST_EMPTY(PDA_Manifest) var/list/all_jobs = get_job_datums() - for(var/datum/job/J in all_jobs) + for(var/datum/role/job/J in all_jobs) if(J.title == rank) //If we have a rank, just default to using that. real_title = rank break @@ -331,7 +331,7 @@ GLOBAL_LIST_EMPTY(PDA_Manifest) if(H.mind && !player_is_antag(H.mind, only_offstation_roles = 1)) var/assignment = GetAssignment(H) var/hidden - var/datum/job/J = SSjob.get_job(H.mind.assigned_role) + var/datum/role/job/J = SSjob.get_job(H.mind.assigned_role) hidden = J?.offmap_spawn /* Note: Due to cached_character_icon, a number of emergent properties occur due to the initialization diff --git a/code/datums/datum.dm b/code/datums/datum.dm index 84352d94bb1..0c0761a700b 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -264,3 +264,45 @@ return SEND_SIGNAL(source, COMSIG_CD_RESET(index), S_TIMER_COOLDOWN_TIMELEFT(source, index)) TIMER_COOLDOWN_END(source, index) + +//? simple serialize/deserialize; it's expected to use this for simple datums only. +//? do not use this for /atoms, SSpersistence handles that! + +/** + * serializes us to a list + * note that *everything* will be trampled down to a number or text. + * do not store raw types. + * + * reserved: + * "type" - this is always the type at time of saving. this is for current limitations, DO NOT use this if at all possible. + */ +/datum/proc/serialize() + return list("type" = "[type]") + +/** + * deserializes from a list + * + * @params + * * data - json_decode()'d list. + */ +/datum/proc/deserialize(list/data) + return + +/** + * make a datum from a serialized list + * you are responsible for knowing what datums this is valid for. + * you are responsible for sanitizing the input. + */ +/proc/deserialize_datum(list/data) + if(istext(data)) + data = json_decode(data) + var/path = text2path(data["type"]) + ASSERT(ispath(path, /datum)) + return (new path):deserialize(data) + +/** + * serializes a datum into a json text string + */ +/proc/serialize_datum(datum/D) + ASSERT(isdatum(D)) + return json_encode(D.serialize()) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 7cdc9a7c4c6..90c948c522c 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -26,17 +26,23 @@ */ /datum/mind - var/key + /// ckey of mind + var/ckey /// Replaces mob/var/original_name var/name var/mob/living/current var/mob/living/original //TODO: remove.not used in any meaningful way ~Carn. First I'll need to tweak the way silicon-mobs handle minds. var/active = FALSE - //? Original Character Data + //? Characteristics + /// characteristics holder + var/datum/characteristics_holder/characteristics + + //? Preferences /** * original save data * ! TODO: REMOVE THIS; we shouldn't keep this potentially big list all round. ! + * todo: don't actually remove it, just only save relevant data (?) */ var/list/original_save_data /// original economic modifier from backgrounds @@ -52,7 +58,7 @@ var/role_alt_title - var/datum/job/assigned_job + var/datum/role/job/assigned_job var/list/datum/objective/objectives = list() var/list/datum/objective/special_verbs = list() @@ -86,10 +92,21 @@ /// Used to store what traits the player had picked out in their preferences before joining, in text form. var/list/traits = list() -/datum/mind/New(var/key) - src.key = key +/datum/mind/New(ckey) + src.ckey = ckey - ..() +/datum/mind/Destroy() + QDEL_NULL(characteristics) + return ..() + +/** + * make sure we have a characteristics holder + */ +/datum/mind/proc/characteristics_holder() + if(!characteristics) + characteristics = new + characteristics.associate_with_mind(src) + return characteristics /datum/mind/proc/transfer_to(mob/living/new_character) if(!istype(new_character)) @@ -99,6 +116,7 @@ current.remove_changeling_powers() remove_verb(current, /datum/changeling/proc/EvolutionMenu) current.mind = null + characteristics?.disassociate_from_mob(current) SSnanoui.user_transferred(current, new_character) // transfer active NanoUI instances to new user if(new_character.mind) //remove any mind currently in our new body's mind variable @@ -106,12 +124,13 @@ current = new_character //link ourself to our new body new_character.mind = src //and link our new body to ourself + characteristics?.associate_with_mob(current) if(changeling) new_character.make_changeling() if(active) - new_character.key = key //now transfer the key to link the client to our new body + new_character.ckey = ckey //now transfer the ckey to link the client to our new body // if(new_character.client) //TODO: Eye Contact // LAZYCLEARLIST(new_character.client.recent_examines) @@ -141,7 +160,7 @@ return var/out = "[name][(current&&(current.real_name!=name))?" (as [current.real_name])":""]
" - out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]
" + out += "Mind currently owned by ckey: [ckey] [active?"(synced)":"(not synced)"]
" out += "Assigned role: [assigned_role]. Edit
" out += "
" out += "Factions and special roles:
" @@ -419,7 +438,7 @@ // var/obj/item/uplink/hidden/suplink = find_syndicate_uplink() No longer needed, uses stored in mind var/crystals crystals = tcrystals - crystals = input("Amount of telecrystals for [key]", crystals) as null|num + crystals = input("Amount of telecrystals for [ckey]", crystals) as null|num if (!isnull(crystals)) tcrystals = crystals @@ -498,9 +517,9 @@ //Initialisation procs /mob/proc/mind_initialize() if(mind) - mind.key = key + mind.ckey = ckey else - mind = new /datum/mind(key) + mind = new /datum/mind(ckey) mind.original = src if(SSticker) SSticker.minds += mind @@ -571,3 +590,42 @@ . = ..() mind.assigned_role = "Juggernaut" mind.special_role = "Cultist" + +//? Preferences Checks + +/datum/mind/proc/original_background_religion() + RETURN_TYPE(/datum/lore/character_background/religion) + var/id = original_save_data?[CHARACTER_DATA_RELIGION] + if(isnull(id)) + return + return SScharacters.resolve_religion(id) + +/datum/mind/proc/original_background_citizenship() + RETURN_TYPE(/datum/lore/character_background/citizenship) + var/id = original_save_data?[CHARACTER_DATA_CITIZENSHIP] + if(isnull(id)) + return + return SScharacters.resolve_citizenship(id) + +/datum/mind/proc/original_background_origin() + RETURN_TYPE(/datum/lore/character_background/origin) + var/id = original_save_data?[CHARACTER_DATA_ORIGIN] + if(isnull(id)) + return + return SScharacters.resolve_origin(id) + +/datum/mind/proc/original_background_faction() + RETURN_TYPE(/datum/lore/character_background/faction) + var/id = original_save_data?[CHARACTER_DATA_FACTION] + if(isnull(id)) + return + return SScharacters.resolve_faction(id) + +/datum/mind/proc/original_background_datums() + . = list( + original_background_citizenship(), + original_background_faction(), + original_background_origin(), + original_background_religion(), + ) + listclearnulls(.) diff --git a/code/datums/prototype.dm b/code/datums/prototype.dm new file mode 100644 index 00000000000..22650764e69 --- /dev/null +++ b/code/datums/prototype.dm @@ -0,0 +1,83 @@ +/* +candidates for conversion: +- /datum/role +- /datum/material +- /datum/lore +- /datum/design +*/ + +/** + * global singletons fetched from SSrepository + * + * they can be registered, or non-registered. + * + * ids are optional, but no id means it can only be fetched by type. set anonymous to TRUE for that! + * + * all prototypes should eventually be serializable + */ +/datum/prototype + abstract_type = /datum/prototype + + //? Identity + /// namespace - should be unique to a given domain or kind of prototype, e.g. /datum/prototype/lore, /datum/prototype/outfit, etc + /// this should NEVER be changed at runtime! + /// changing this may cause persistent data to be thrown out. + /// you have been warned. + var/namespace + /// identifier - must be unique within a namespace + var/identifier + /// anonymous? if true, we should not have a coded identifier. + var/anonymous = FALSE + + /// our id - must be unique globally. DO NOT EDIT THIS, EDIT [identifier]. + var/uid + /// uid next global on /datum/prototype + var/static/uid_next = 0 + + /// should this be saved? + // todo: not yet implemented + var/savable = FALSE + /// lazyloaded + var/lazy = FALSE + +/datum/prototype/New() + if(anonymous) + generate_anonymous_uid() + else + uid = "[namespace]_[identifier]" + +/datum/prototype/proc/generate_anonymous_uid() + uid = "[namespace]_[num2text(world.realtime, 16)]_[++uid_next]" + +/** + * called on register + * always call return ..() *LAST* so side effects can be cleaned up on every level on failure. + * + * @return TRUE / FALSE to allow / deny register; PLEASE clean up side effects if you make this fail! + */ +/datum/prototype/proc/register() + return TRUE + +/** + * called on unregister + * this should never fail; returning FALSE causes a fatal runtime to be generated. + * + * @return TRUE / FALSE on success / failure + */ +/datum/prototype/proc/unregister() + return TRUE + +/datum/prototype/serialize() + . = ..() + .[NAMEOF(src, identifier)] = identifier + +/datum/prototype/deserialize(list/data) + . = ..() + identifier = data[NAMEOF(src, identifier)] + uid = "[namespace]_[identifier]" + +/** + * checks that our identifier is set properly + */ +/datum/prototype/proc/assert_identifier() + return !anonymous && uid == "[namespace]_[identifier]" && namespace == initial(namespace) diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index b42c9a82e72..0d7c82ed724 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -179,17 +179,17 @@ /datum/antagonist/proc/draft_antagonist(var/datum/mind/player) //Check if the player can join in this antag role, or if the player has already been given an antag role. if(!can_become_antag(player) || (player.assigned_role in roundstart_restricted)) - log_debug(SPAN_DEBUG("[player.key] was selected for [role_text] by lottery, but is not allowed to be that role.")) + log_debug(SPAN_DEBUG("[player.ckey] was selected for [role_text] by lottery, but is not allowed to be that role.")) return 0 if(player.special_role) - log_debug(SPAN_DEBUG("[player.key] was selected for [role_text] by lottery, but they already have a special role.")) + log_debug(SPAN_DEBUG("[player.ckey] was selected for [role_text] by lottery, but they already have a special role.")) return 0 if(!(flags & ANTAG_OVERRIDE_JOB) && (!player.current || istype(player.current, /mob/new_player))) - log_debug(SPAN_DEBUG("[player.key] was selected for [role_text] by lottery, but they have not joined the game.")) + log_debug(SPAN_DEBUG("[player.ckey] was selected for [role_text] by lottery, but they have not joined the game.")) return 0 pending_antagonists |= player - log_debug(SPAN_DEBUG("[player.key] has been selected for [role_text] by lottery.")) + log_debug(SPAN_DEBUG("[player.ckey] has been selected for [role_text] by lottery.")) //Ensure that antags with ANTAG_OVERRIDE_JOB do not occupy job slots. if(flags & ANTAG_OVERRIDE_JOB) diff --git a/code/game/antagonist/antagonist_panel.dm b/code/game/antagonist/antagonist_panel.dm index 079e1e09e40..3f397d29c38 100644 --- a/code/game/antagonist/antagonist_panel.dm +++ b/code/game/antagonist/antagonist_panel.dm @@ -27,13 +27,13 @@ var/mob/M = player.current dat += "" if(M) - dat += "" dat += "" else - dat += "" + dat += "" dat += "" dat += "
[M.real_name]/([player.key])" + dat += "[M.real_name]/([player.ckey])" if(!M.client) dat += " (logged out)" if(M.stat == DEAD) dat += " (DEAD)" dat += "\[PP]\[PM\]\[TP\][player.key] Mob not found![player.ckey] Mob not found!
" diff --git a/code/game/antagonist/antagonist_print.dm b/code/game/antagonist/antagonist_print.dm index 69d98eeff8f..64e54638dc4 100644 --- a/code/game/antagonist/antagonist_print.dm +++ b/code/game/antagonist/antagonist_print.dm @@ -49,7 +49,7 @@ /datum/antagonist/proc/print_player_lite(var/datum/mind/ply) var/role = ply.assigned_role ? "\improper[ply.assigned_role]" : "\improper[ply.special_role]" - var/text = "
[ply.name] ([ply.key]) as \a [role] (" + var/text = "
[ply.name] ([ply.ckey]) as \a [role] (" if(ply.current) if(ply.current.stat == DEAD) text += "died" diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 70d48a21751..f2ac9d2d843 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -498,17 +498,17 @@ var/global/list/additional_antag_types = list() if(D.mind && (D.mind.original == L || D.mind.current == L)) if(L.stat == DEAD) if(L.suiciding) //Suicider - msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Suicide)\n" + msg += "[L.name] ([ckey(D.mind.ckey)]), the [L.job] (Suicide)\n" continue //Disconnected client else - msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Dead)\n" + msg += "[L.name] ([ckey(D.mind.ckey)]), the [L.job] (Dead)\n" continue //Dead mob, ghost abandoned else if(D.can_reenter_corpse) - msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Adminghosted)\n" + msg += "[L.name] ([ckey(D.mind.ckey)]), the [L.job] (Adminghosted)\n" continue //Lolwhat else - msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Ghosted)\n" + msg += "[L.name] ([ckey(D.mind.ckey)]), the [L.job] (Ghosted)\n" continue //Ghosted while alive msg += "" // close the span from right at the top diff --git a/code/game/landmarks/spawnpoint/_spawnpoint.dm b/code/game/landmarks/spawnpoint/_spawnpoint.dm index 208363cfc0e..595a3a830d1 100644 --- a/code/game/landmarks/spawnpoint/_spawnpoint.dm +++ b/code/game/landmarks/spawnpoint/_spawnpoint.dm @@ -136,7 +136,7 @@ * name - spawnee's name * job_name - job's name - useful for alt titles */ -/obj/landmark/spawnpoint/proc/RenderAnnounceMessage(mob/M, client/C, datum/job/J, name, job_name) +/obj/landmark/spawnpoint/proc/RenderAnnounceMessage(mob/M, client/C, datum/role/job/J, name, job_name) return "[name || "Unknown"] will arrive shortly." /** diff --git a/code/game/landmarks/spawnpoint/station/jobs.dm b/code/game/landmarks/spawnpoint/station/jobs.dm index d7f14cdac44..d14872b2298 100644 --- a/code/game/landmarks/spawnpoint/station/jobs.dm +++ b/code/game/landmarks/spawnpoint/station/jobs.dm @@ -1,7 +1,7 @@ /obj/landmark/spawnpoint/job/assistant name = "Assistant" icon_state = "Assistant" - job_path = /datum/job/station/assistant + job_path = /datum/role/job/station/assistant /obj/landmark/spawnpoint/job/assistant/override spawns_left = INFINITY @@ -11,199 +11,199 @@ /obj/landmark/spawnpoint/job/janitor name = "Janitor" icon_state = "Janitor" - job_path = /datum/job/station/janitor + job_path = /datum/role/job/station/janitor /obj/landmark/spawnpoint/job/cargo_technician name = "Cargo Technician" icon_state = "Cargo Technician" - job_path = /datum/job/station/cargo_tech + job_path = /datum/role/job/station/cargo_tech /obj/landmark/spawnpoint/job/bartender name = "Bartender" icon_state = "Bartender" - job_path = /datum/job/station/bartender + job_path = /datum/role/job/station/bartender /obj/landmark/spawnpoint/job/clown name = "Clown" icon_state = "Clown" - job_path = /datum/job/station/clown + job_path = /datum/role/job/station/clown /obj/landmark/spawnpoint/job/mime name = "Mime" icon_state = "Mime" - job_path = /datum/job/station/mime + job_path = /datum/role/job/station/mime /obj/landmark/spawnpoint/job/quartermaster name = "Quartermaster" icon_state = "Quartermaster" - job_path = /datum/job/station/quartermaster + job_path = /datum/role/job/station/quartermaster /obj/landmark/spawnpoint/job/atmospheric_technician name = "Atmospheric Technician" icon_state = "Atmospheric Technician" - job_path = /datum/job/station/atmos + job_path = /datum/role/job/station/atmos /obj/landmark/spawnpoint/job/chef name = "Cook" icon_state = "Cook" - job_path = /datum/job/station/chef + job_path = /datum/role/job/station/chef /obj/landmark/spawnpoint/job/shaft_miner name = "Shaft Miner" icon_state = "Shaft Miner" - job_path = /datum/job/station/mining + job_path = /datum/role/job/station/mining /obj/landmark/spawnpoint/job/security_officer name = "Security Officer" icon_state = "Security Officer" - job_path = /datum/job/station/officer + job_path = /datum/role/job/station/officer /obj/landmark/spawnpoint/job/botanist name = "Botanist" icon_state = "Botanist" - job_path = /datum/job/station/hydro + job_path = /datum/role/job/station/hydro /obj/landmark/spawnpoint/job/head_of_security name = "Head of Security" icon_state = "Head of Security" - job_path = /datum/job/station/head_of_security + job_path = /datum/role/job/station/head_of_security /obj/landmark/spawnpoint/job/captain name = "Captain" icon_state = "Captain" - job_path = /datum/job/station/captain + job_path = /datum/role/job/station/captain /obj/landmark/spawnpoint/job/detective name = "Detective" icon_state = "Detective" - job_path = /datum/job/station/detective + job_path = /datum/role/job/station/detective /obj/landmark/spawnpoint/job/warden name = "Warden" icon_state = "Warden" - job_path = /datum/job/station/warden + job_path = /datum/role/job/station/warden /obj/landmark/spawnpoint/job/chief_engineer name = "Chief Engineer" icon_state = "Chief Engineer" - job_path = /datum/job/station/chief_engineer + job_path = /datum/role/job/station/chief_engineer /obj/landmark/spawnpoint/job/senior_engineer name = "Senior Engineer" icon_state = "Chief Engineer" - job_path = /datum/job/station/senior_engineer + job_path = /datum/role/job/station/senior_engineer /obj/landmark/spawnpoint/job/head_of_personnel name = "Head of Personnel" icon_state = "Head of Personnel" - job_path = /datum/job/station/head_of_personnel + job_path = /datum/role/job/station/head_of_personnel /obj/landmark/spawnpoint/job/librarian name = "Curator" icon_state = "Curator" - job_path = /datum/job/station/librarian + job_path = /datum/role/job/station/librarian /obj/landmark/spawnpoint/job/lawyer name = "Lawyer" icon_state = "Lawyer" - job_path = /datum/job/station/lawyer + job_path = /datum/role/job/station/lawyer /obj/landmark/spawnpoint/job/station_engineer name = "Station Engineer" icon_state = "Station Engineer" - job_path = /datum/job/station/engineer + job_path = /datum/role/job/station/engineer /obj/landmark/spawnpoint/job/medical_doctor name = "Medical Doctor" icon_state = "Medical Doctor" - job_path = /datum/job/station/doctor + job_path = /datum/role/job/station/doctor /obj/landmark/spawnpoint/job/head_nurse name = "Head Nurse" // icon_state = "Medical Doctor" - job_path = /datum/job/station/head_nurse + job_path = /datum/role/job/station/head_nurse /obj/landmark/spawnpoint/job/paramedic name = "Paramedic" icon_state = "Paramedic" - job_path = /datum/job/station/paramedic + job_path = /datum/role/job/station/paramedic /obj/landmark/spawnpoint/job/scientist name = "Scientist" icon_state = "Scientist" - job_path = /datum/job/station/scientist + job_path = /datum/role/job/station/scientist /obj/landmark/spawnpoint/job/senior_researcher name = "Senior Researcher" // icon_state = "Scientist" - job_path = /datum/job/station/senior_researcher + job_path = /datum/role/job/station/senior_researcher /obj/landmark/spawnpoint/job/chemist name = "Chemist" icon_state = "Chemist" - job_path = /datum/job/station/chemist + job_path = /datum/role/job/station/chemist /obj/landmark/spawnpoint/job/roboticist name = "Roboticist" icon_state = "Roboticist" - job_path = /datum/job/station/roboticist + job_path = /datum/role/job/station/roboticist /obj/landmark/spawnpoint/job/research_director name = "Research Director" icon_state = "Research Director" - job_path = /datum/job/station/research_director + job_path = /datum/role/job/station/research_director // /obj/landmark/spawnpoint/job/geneticist // name = "Geneticist" // icon_state = "Geneticist" -// job_path = /datum/job/station/geneticist +// job_path = /datum/role/job/station/geneticist /obj/landmark/spawnpoint/job/chief_medical_officer name = "Chief Medical Officer" icon_state = "Chief Medical Officer" - job_path = /datum/job/station/chief_medical_officer + job_path = /datum/role/job/station/chief_medical_officer // /obj/landmark/spawnpoint/job/virologist // name = "Virologist" // icon_state = "Virologist" -// job_path = /datum/job/station/virologist +// job_path = /datum/role/job/station/virologist /obj/landmark/spawnpoint/job/chaplain name = "Chaplain" icon_state = "Chaplain" - job_path = /datum/job/station/chaplain + job_path = /datum/role/job/station/chaplain /obj/landmark/spawnpoint/job/cyborg name = "Cyborg" icon_state = "Cyborg" - job_path = /datum/job/station/cyborg + job_path = /datum/role/job/station/cyborg /obj/landmark/spawnpoint/job/entertainer name = "Entertainer" - job_path = /datum/job/station/entertainer + job_path = /datum/role/job/station/entertainer /obj/landmark/spawnpoint/job/pilot name = "Pilot" - job_path = /datum/job/station/pilot + job_path = /datum/role/job/station/pilot /obj/landmark/spawnpoint/job/command_secretary name = "Command Secretary" - job_path = /datum/job/station/command_secretary + job_path = /datum/role/job/station/command_secretary /obj/landmark/spawnpoint/job/explorer name = "Explorer" - job_path = /datum/job/station/explorer + job_path = /datum/role/job/station/explorer /obj/landmark/spawnpoint/job/field_medic name = "Field Medic" - job_path = /datum/job/station/field_medic + job_path = /datum/role/job/station/field_medic /obj/landmark/spawnpoint/job/pathfinder name = "Pathfinder" - job_path = /datum/job/station/pathfinder + job_path = /datum/role/job/station/pathfinder /obj/landmark/spawnpoint/job/psychiatrist name = "Psychiatrist" - job_path = /datum/job/station/psychiatrist + job_path = /datum/role/job/station/psychiatrist /obj/landmark/spawnpoint/job/xenobotanist name = "Xenobotanist" @@ -216,7 +216,7 @@ icon_state = "AI" latejoin = TRUE // AIize in transform_procs.dm uses get_latejoin_spawnpoint() for spawning in a AI -- including at roundstart. delete_on_roundstart = TRUE - job_path = /datum/job/station/ai + job_path = /datum/role/job/station/ai prevent_mob_stack = FALSE spawns_left = 1 var/primary_ai = TRUE diff --git a/code/game/landmarks/spawnpoint/tradeport.dm b/code/game/landmarks/spawnpoint/tradeport.dm index 4112d043e5f..24adc1185e2 100644 --- a/code/game/landmarks/spawnpoint/tradeport.dm +++ b/code/game/landmarks/spawnpoint/tradeport.dm @@ -1,6 +1,6 @@ /obj/landmark/spawnpoint/job/trader name = "Trader" - job_path = /datum/job/trader + job_path = /datum/role/job/trader latejoin = TRUE latejoin_override = TRUE diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 92b95298c30..f164a14d74b 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -80,7 +80,7 @@ if(clonemind.current && clonemind.current.stat != DEAD) // Mind is associated with a non-dead body. return FALSE if(clonemind.active) // Somebody is using that mind. - if(ckey(clonemind.key) != R.ckey) + if(clonemind.ckey != R.ckey) return FALSE else for(var/mob/observer/dead/G in GLOB.player_list) diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index 56e21f307a7..80253bb8c12 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -219,7 +219,7 @@ if(is_centcom()) access = get_centcom_access(t1) else - var/datum/job/jobdatum = SSjob.get_job(t1) + var/datum/role/job/jobdatum = SSjob.get_job(t1) if(!jobdatum) to_chat(usr, "No log exists for this job: [t1]") return diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 8cc62969653..4870e1de2b9 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -322,9 +322,9 @@ return if ((!subject.ckey) || (!subject.client)) scantemp = "Error: Mental interface failure." - if(subject.stat == DEAD && subject.mind && subject.mind.key) // If they're dead and not in their body, tell them to get in it. + if(subject.stat == DEAD && subject.mind && subject.mind.ckey) // If they're dead and not in their body, tell them to get in it. for(var/mob/observer/dead/ghost in GLOB.player_list) - if(ghost.ckey == ckey(subject.mind.key)) + if(ghost.ckey == ckey(subject.mind.ckey)) ghost.notify_revive("Someone is trying to scan your body in the cloner. Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg') break return diff --git a/code/game/machinery/computer/timeclock_vr.dm b/code/game/machinery/computer/timeclock_vr.dm index a7fce3060c4..6f20c867eff 100644 --- a/code/game/machinery/computer/timeclock_vr.dm +++ b/code/game/machinery/computer/timeclock_vr.dm @@ -92,7 +92,7 @@ if(card) data["card"] = "[card]" data["assignment"] = card.assignment - var/datum/job/job = SSjob.get_job(card.rank) + var/datum/role/job/job = SSjob.get_job(card.rank) if(job) data["job_datum"] = list( "title" = job.title, @@ -145,19 +145,21 @@ update_icon() return TRUE - /obj/machinery/computer/timeclock/proc/getOpenOnDutyJobs(var/mob/user, var/department) var/list/available_jobs = list() - for(var/datum/job/job in SSjob.occupations) + for(var/datum/role/job/job in SSjob.occupations) if(isOpenOnDutyJob(user, department, job)) - available_jobs[job.title] = list(job.title) - if(job.alt_titles) - for(var/alt_job in job.alt_titles) - if(alt_job != job.title) - available_jobs[job.title] += alt_job + var/list/titles = available_titles(user, job) + if(!length(titles)) + continue + available_jobs[job.title] = titles return available_jobs -/obj/machinery/computer/timeclock/proc/isOpenOnDutyJob(var/mob/user, var/department, var/datum/job/job) +/obj/machinery/computer/timeclock/proc/available_titles(mob/user, var/datum/role/job/job) + var/list/datum/lore/character_background/backgrounds = user.mind?.original_background_datums() + return job.alt_title_query(backgrounds) + +/obj/machinery/computer/timeclock/proc/isOpenOnDutyJob(var/mob/user, var/department, var/datum/role/job/job) return job \ && job.is_position_available() \ && !job.whitelist_only \ @@ -165,15 +167,18 @@ && job.player_old_enough(user.client) \ && job.pto_type == department \ && !job.disallow_jobhop \ - && job.timeoff_factor > 0 + && job.timeoff_factor > 0 \ + && (job.check_mob_availability_one(user) == ROLE_AVAILABLE) /obj/machinery/computer/timeclock/proc/makeOnDuty(var/newrank, var/newassignment) - var/datum/job/oldjob = SSjob.get_job(card.rank) - var/datum/job/newjob = SSjob.get_job(newrank) + var/datum/role/job/oldjob = SSjob.get_job(card.rank) + var/datum/role/job/newjob = SSjob.get_job(newrank) if(!oldjob || !isOpenOnDutyJob(usr, oldjob.pto_type, newjob)) return if(newassignment != newjob.title && !(newassignment in newjob.alt_titles)) return + if(!newjob.alt_title_check(newassignment, usr.mind?.original_background_datums())) + return if(newjob) card.access = newjob.get_access() card.rank = newjob.title @@ -190,12 +195,12 @@ return /obj/machinery/computer/timeclock/proc/makeOffDuty() - var/datum/job/foundjob = SSjob.get_job(card.rank) + var/datum/role/job/foundjob = SSjob.get_job(card.rank) if(!foundjob) return var/new_dept = foundjob.pto_type || PTO_CIVILIAN - var/datum/job/ptojob = null - for(var/datum/job/job in SSjob.occupations) + var/datum/role/job/ptojob = null + for(var/datum/role/job/job in SSjob.occupations) if(job.pto_type == new_dept && job.timeoff_factor < 0) ptojob = job break diff --git a/code/game/objects/items/devices/scanners_vr.dm b/code/game/objects/items/devices/scanners_vr.dm index 40d104fbf21..6ceb8bd08d9 100644 --- a/code/game/objects/items/devices/scanners_vr.dm +++ b/code/game/objects/items/devices/scanners_vr.dm @@ -77,9 +77,9 @@ var/global/mob/living/carbon/human/dummy/mannequin/sleevemate_mob output += "Sleeve Pair: " if(!H.ckey) output += "No mind in that body [stored_mind != null ? "\[Upload\]" : null]
" - else if(H.mind && ckey(H.mind.key) != H.ckey) + else if(H.mind && H.mind.ckey != H.ckey) output += "May not be correct body
" - else if(H.mind && ckey(H.mind.key) == H.ckey) + else if(H.mind && H.mind.ckey == H.ckey) output += "Appears to be correct mind in body
" else output += "Unable to perform comparison
" diff --git a/code/game/objects/items/id_cards/station_ids.dm b/code/game/objects/items/id_cards/station_ids.dm index 0d2c3cbc09a..2de8877df28 100644 --- a/code/game/objects/items/id_cards/station_ids.dm +++ b/code/game/objects/items/id_cards/station_ids.dm @@ -24,7 +24,7 @@ var/primary_color = rgb(0,0,0) // Obtained by eyedroppering the stripe in the middle of the card var/secondary_color = rgb(0,0,0) // Likewise for the oval in the top-left corner - var/datum/job/job_access_type = /datum/job/station/assistant // Job type to acquire access rights from, if any + var/datum/role/job/job_access_type = /datum/role/job/station/assistant // Job type to acquire access rights from, if any //alt titles are handled a bit weirdly in order to unobtrusively integrate into existing ID system var/assignment = null //can be alt title or the actual job @@ -124,7 +124,7 @@ /obj/item/card/id/Initialize(mapload) . = ..() - var/datum/job/J = SSjob.get_job(rank) + var/datum/role/job/J = SSjob.get_job(rank) if(J) access = J.get_access() @@ -138,14 +138,14 @@ name = "secretary ID" assignment = "Command Secretary" rank = "Command Secretary" - job_access_type = /datum/job/station/command_secretary + job_access_type = /datum/role/job/station/command_secretary /obj/item/card/id/silver/hop name = "\improper HoP ID" assignment = "Head of Personnel" rank = "Head of Personnel" desc = "A card which represents the balance between those that serve and those that are served." - job_access_type = /datum/job/station/head_of_personnel + job_access_type = /datum/role/job/station/head_of_personnel /obj/item/card/id/gold name = "gold identification card" @@ -158,14 +158,14 @@ name = "\improper Facility Director's ID" assignment = "Facility Director" rank = "Facility Director" - job_access_type = /datum/job/station/captain + job_access_type = /datum/role/job/station/captain /obj/item/card/id/gold/captain/spare name = "\improper Facility Director's spare ID" desc = "The spare ID of the High Lord himself." registered_name = "Facility Director" icon_state = "gold-id-alternate" - job_access_type = /datum/job/station/captain + job_access_type = /datum/role/job/station/captain /obj/item/card/id/synthetic name = "\improper Synthetic ID" @@ -229,31 +229,31 @@ name = "doctor ID" assignment = "Medical Doctor" rank = "Medical Doctor" - job_access_type = /datum/job/station/doctor + job_access_type = /datum/role/job/station/doctor /obj/item/card/id/medical/chemist name = "chemist ID" assignment = "Chemist" rank = "Chemist" - job_access_type = /datum/job/station/chemist + job_access_type = /datum/role/job/station/chemist /obj/item/card/id/medical/geneticist name = "geneticist ID" assignment = "Geneticist" rank = "Geneticist" - job_access_type = /datum/job/station/doctor //geneticist + job_access_type = /datum/role/job/station/doctor //geneticist /obj/item/card/id/medical/psychiatrist name = "psychiatrist ID" assignment = "Psychiatrist" rank = "Psychiatrist" - job_access_type = /datum/job/station/psychiatrist + job_access_type = /datum/role/job/station/psychiatrist /obj/item/card/id/medical/paramedic name = "paramedic ID" assignment = "Paramedic" rank = "Paramedic" - job_access_type = /datum/job/station/paramedic + job_access_type = /datum/role/job/station/paramedic /obj/item/card/id/medical/head name = "\improper CMO ID" @@ -262,7 +262,7 @@ secondary_color = rgb(255,223,127) assignment = "Chief Medical Officer" rank = "Chief Medical Officer" - job_access_type = /datum/job/station/chief_medical_officer + job_access_type = /datum/role/job/station/chief_medical_officer /obj/item/card/id/security name = "security identification card" @@ -275,19 +275,19 @@ name = "officer ID" assignment = "Security Officer" rank = "Security Officer" - job_access_type = /datum/job/station/officer + job_access_type = /datum/role/job/station/officer /obj/item/card/id/security/detective name = "detective ID" assignment = "Detective" rank = "Detective" - job_access_type = /datum/job/station/detective + job_access_type = /datum/role/job/station/detective /obj/item/card/id/security/warden name = "warden ID" assignment = "Warden" rank = "Warden" - job_access_type = /datum/job/station/warden + job_access_type = /datum/role/job/station/warden /obj/item/card/id/security/head name = "\improper HoS ID" @@ -296,7 +296,7 @@ secondary_color = rgb(255,223,127) assignment = "Head of Security" rank = "Head of Security" - job_access_type = /datum/job/station/head_of_security + job_access_type = /datum/role/job/station/head_of_security /obj/item/card/id/engineering name = "engineering identification card" @@ -309,13 +309,13 @@ name = "engineer ID" assignment = "Station Engineer" rank = "Station Engineer" - job_access_type = /datum/job/station/engineer + job_access_type = /datum/role/job/station/engineer /obj/item/card/id/engineering/atmos name = "atmospherics ID" assignment = "Atmospheric Technician" rank = "Atmospheric Technician" - job_access_type = /datum/job/station/atmos + job_access_type = /datum/role/job/station/atmos /obj/item/card/id/engineering/head name = "\improper CE ID" @@ -324,7 +324,7 @@ secondary_color = rgb(255,223,127) assignment = "Chief Engineer" rank = "Chief Engineer" - job_access_type = /datum/job/station/chief_engineer + job_access_type = /datum/role/job/station/chief_engineer /obj/item/card/id/science name = "science identification card" @@ -337,19 +337,19 @@ name = "scientist ID" assignment = "Scientist" rank = "Scientist" - job_access_type = /datum/job/station/scientist + job_access_type = /datum/role/job/station/scientist /obj/item/card/id/science/xenobiologist name = "xenobiologist ID" assignment = "Xenobiologist" rank = "Xenobiologist" - job_access_type = /datum/job/station/scientist // /datum/job/station/xenobiologist + job_access_type = /datum/role/job/station/scientist // /datum/role/job/station/xenobiologist /obj/item/card/id/science/roboticist name = "roboticist ID" assignment = "Roboticist" rank = "Roboticist" - job_access_type = /datum/job/station/roboticist + job_access_type = /datum/role/job/station/roboticist /obj/item/card/id/science/head name = "\improper RD ID" @@ -358,7 +358,7 @@ secondary_color = rgb(255,223,127) assignment = "Research Director" rank = "Research Director" - job_access_type = /datum/job/station/research_director + job_access_type = /datum/role/job/station/research_director /obj/item/card/id/cargo name = "cargo identification card" @@ -371,13 +371,13 @@ name = "cargo ID" assignment = "Cargo Technician" rank = "Cargo Technician" - job_access_type = /datum/job/station/cargo_tech + job_access_type = /datum/role/job/station/cargo_tech /obj/item/card/id/cargo/mining name = "mining ID" assignment = "Shaft Miner" rank = "Shaft Miner" - job_access_type = /datum/job/station/mining + job_access_type = /datum/role/job/station/mining /obj/item/card/id/cargo/head name = "\improper Quartermaster's ID" @@ -386,12 +386,12 @@ secondary_color = rgb(255,223,127) assignment = "Quartermaster" rank = "Quartermaster" - job_access_type = /datum/job/station/quartermaster + job_access_type = /datum/role/job/station/quartermaster /obj/item/card/id/assistant assignment = USELESS_JOB rank = USELESS_JOB - job_access_type = /datum/job/station/assistant + job_access_type = /datum/role/job/station/assistant /obj/item/card/id/civilian name = "civilian identification card" @@ -401,61 +401,61 @@ secondary_color = rgb(95,159,191) assignment = "Civilian" rank = "Assistant" - job_access_type = /datum/job/station/assistant + job_access_type = /datum/role/job/station/assistant /obj/item/card/id/civilian/bartender name = "bartender ID" assignment = "Bartender" rank = "Bartender" - job_access_type = /datum/job/station/bartender + job_access_type = /datum/role/job/station/bartender /obj/item/card/id/civilian/botanist name = "botanist ID" assignment = "Botanist" rank = "Botanist" - job_access_type = /datum/job/station/hydro + job_access_type = /datum/role/job/station/hydro /obj/item/card/id/civilian/chaplain name = "chaplain ID" assignment = "Chaplain" rank = "Chaplain" - job_access_type = /datum/job/station/chaplain + job_access_type = /datum/role/job/station/chaplain /obj/item/card/id/civilian/chef name = "chef ID" assignment = "Chef" rank = "Chef" - job_access_type = /datum/job/station/chef + job_access_type = /datum/role/job/station/chef /obj/item/card/id/civilian/internal_affairs_agent name = "internal affairs ID" assignment = "Internal Affairs Agent" rank = "Internal Affairs Agent" - job_access_type = /datum/job/station/lawyer + job_access_type = /datum/role/job/station/lawyer /obj/item/card/id/civilian/janitor name = "janitor ID" assignment = "Janitor" rank = "Janitor" - job_access_type = /datum/job/station/janitor + job_access_type = /datum/role/job/station/janitor /obj/item/card/id/civilian/librarian name = "librarian ID" assignment = "Librarian" rank = "Librarian" - job_access_type = /datum/job/station/librarian + job_access_type = /datum/role/job/station/librarian /obj/item/card/id/civilian/clown name = "clown ID" assignment = "Clown" rank = "Clown" - job_access_type = /datum/job/station/clown + job_access_type = /datum/role/job/station/clown /obj/item/card/id/civilian/mime name = "mime ID" assignment = "Mime" rank = "Mime" - job_access_type = /datum/job/station/mime + job_access_type = /datum/role/job/station/mime /obj/item/card/id/civilian/head //This is not the HoP. There's no position that uses this right now. name = "\improper Services Officer ID" @@ -511,7 +511,7 @@ rank = "Field Medic" primary_color = rgb(47,189,189) secondary_color = rgb(127,223,223) - job_access_type = /datum/job/station/field_medic + job_access_type = /datum/role/job/station/field_medic /obj/item/card/id/explorer name = "identification card" @@ -522,12 +522,12 @@ /obj/item/card/id/explorer/pilot assignment = "Pilot" rank = "Pilot" - job_access_type = /datum/job/station/pilot + job_access_type = /datum/role/job/station/pilot /obj/item/card/id/explorer/explorer assignment = "Explorer" rank = "Explorer" - job_access_type = /datum/job/station/explorer + job_access_type = /datum/role/job/station/explorer /obj/item/card/id/explorer/head name = "identification card" @@ -539,4 +539,4 @@ /obj/item/card/id/explorer/head/pathfinder assignment = "Pathfinder" rank = "Pathfinder" - job_access_type = /datum/job/station/pathfinder + job_access_type = /datum/role/job/station/pathfinder diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index 8ae9e760259..9122cef6648 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -208,10 +208,7 @@ if(..()) return FALSE - if(istype(R.translation_context, /datum/translation_context/simple/silicons)) - qdel(R.translation_context) - R.translation_context = new /datum/translation_context/variable/learning/silicons - R.sync_translation_context() + R.create_translation_context(/datum/translation_context/variable/learning/silicons) return TRUE diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 96862c1a4c9..baa75a97412 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -1021,7 +1021,7 @@ var/list/admin_verbs_event_manager = list( set category = "Admin" if(holder) var/list/jobs = list() - for (var/datum/job/J in SSjob.occupations) + for (var/datum/role/job/J in SSjob.occupations) if (J.current_positions >= J.total_positions && J.total_positions != -1) jobs += J.title if (!jobs.len) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 5736759ab2a..c12495f5c76 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -397,7 +397,7 @@ jobs += "Command Positions" for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_COMMAND)) if(!jobPos) continue - var/datum/job/job = SSjob.get_job(jobPos) + var/datum/role/job/job = SSjob.get_job(jobPos) if(!job) continue if(jobban_isbanned(M, job.title)) @@ -418,7 +418,7 @@ jobs += "Security Positions" for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_SECURITY)) if(!jobPos) continue - var/datum/job/job = SSjob.get_job(jobPos) + var/datum/role/job/job = SSjob.get_job(jobPos) if(!job) continue if(jobban_isbanned(M, job.title)) @@ -439,7 +439,7 @@ jobs += "Engineering Positions" for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_ENGINEERING)) if(!jobPos) continue - var/datum/job/job = SSjob.get_job(jobPos) + var/datum/role/job/job = SSjob.get_job(jobPos) if(!job) continue if(jobban_isbanned(M, job.title)) @@ -460,7 +460,7 @@ jobs += "Cargo Positions" for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_CARGO)) if(!jobPos) continue - var/datum/job/job = SSjob.get_job(jobPos) + var/datum/role/job/job = SSjob.get_job(jobPos) if(!job) continue if(jobban_isbanned(M, job.title)) @@ -481,7 +481,7 @@ jobs += "Medical Positions" for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_MEDICAL)) if(!jobPos) continue - var/datum/job/job = SSjob.get_job(jobPos) + var/datum/role/job/job = SSjob.get_job(jobPos) if(!job) continue if(jobban_isbanned(M, job.title)) @@ -502,7 +502,7 @@ jobs += "Science Positions" for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_RESEARCH)) if(!jobPos) continue - var/datum/job/job = SSjob.get_job(jobPos) + var/datum/role/job/job = SSjob.get_job(jobPos) if(!job) continue if(jobban_isbanned(M, job.title)) @@ -522,7 +522,7 @@ jobs += "Science Positions" for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_PLANET)) if(!jobPos) continue - var/datum/job/job = SSjob.get_job(jobPos) + var/datum/role/job/job = SSjob.get_job(jobPos) if(!job) continue if(jobban_isbanned(M, job.title)) @@ -542,7 +542,7 @@ jobs += "Civilian Positions" for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_CIVILIAN)) if(!jobPos) continue - var/datum/job/job = SSjob.get_job(jobPos) + var/datum/role/job/job = SSjob.get_job(jobPos) if(!job) continue if(jobban_isbanned(M, job.title)) @@ -569,7 +569,7 @@ jobs += "Non-human Positions" for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_SYNTHETIC)) if(!jobPos) continue - var/datum/job/job = SSjob.get_job(jobPos) + var/datum/role/job/job = SSjob.get_job(jobPos) if(!job) continue if(jobban_isbanned(M, job.title)) @@ -656,56 +656,56 @@ if("commanddept") for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_COMMAND)) if(!jobPos) continue - var/datum/job/temp = SSjob.get_job(jobPos) + var/datum/role/job/temp = SSjob.get_job(jobPos) if(!temp) continue joblist += temp.title if("securitydept") for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_SECURITY)) if(!jobPos) continue - var/datum/job/temp = SSjob.get_job(jobPos) + var/datum/role/job/temp = SSjob.get_job(jobPos) if(!temp) continue joblist += temp.title if("engineeringdept") for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_ENGINEERING)) if(!jobPos) continue - var/datum/job/temp = SSjob.get_job(jobPos) + var/datum/role/job/temp = SSjob.get_job(jobPos) if(!temp) continue joblist += temp.title if("cargodept") for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_CARGO)) if(!jobPos) continue - var/datum/job/temp = SSjob.get_job(jobPos) + var/datum/role/job/temp = SSjob.get_job(jobPos) if(!temp) continue joblist += temp.title if("medicaldept") for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_MEDICAL)) if(!jobPos) continue - var/datum/job/temp = SSjob.get_job(jobPos) + var/datum/role/job/temp = SSjob.get_job(jobPos) if(!temp) continue joblist += temp.title if("sciencedept") for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_RESEARCH)) if(!jobPos) continue - var/datum/job/temp = SSjob.get_job(jobPos) + var/datum/role/job/temp = SSjob.get_job(jobPos) if(!temp) continue joblist += temp.title if("explorationdept") for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_PLANET)) if(!jobPos) continue - var/datum/job/temp = SSjob.get_job(jobPos) + var/datum/role/job/temp = SSjob.get_job(jobPos) if(!temp) continue joblist += temp.title if("civiliandept") for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_CIVILIAN)) if(!jobPos) continue - var/datum/job/temp = SSjob.get_job(jobPos) + var/datum/role/job/temp = SSjob.get_job(jobPos) if(!temp) continue joblist += temp.title if("nonhumandept") joblist += "pAI" for(var/jobPos in SSjob.get_job_titles_in_department(DEPARTMENT_SYNTHETIC)) if(!jobPos) continue - var/datum/job/temp = SSjob.get_job(jobPos) + var/datum/role/job/temp = SSjob.get_job(jobPos) if(!temp) continue joblist += temp.title else diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm index 8846f40967d..870585ef2d4 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm @@ -164,6 +164,7 @@ */ +// todo: set_state(state) proc so this is less of a snowflake mess #define SDQL2_STATE_ERROR 0 #define SDQL2_STATE_IDLE 1 @@ -184,16 +185,18 @@ #define SDQL2_OPTIONS_DEFAULT (SDQL2_OPTION_SELECT_OUTPUT_SKIP_NULLS) -#define SDQL2_IS_RUNNING (state == SDQL2_STATE_EXECUTING || state == SDQL2_STATE_SEARCHING || state == SDQL2_STATE_SWITCHING || state == SDQL2_STATE_PRESEARCH) -#define SDQL2_HALT_CHECK if(!SDQL2_IS_RUNNING) {state = SDQL2_STATE_HALTING; return FALSE;}; +#define SDQL2_IS_RUNNING (running == TRUE) +#define SDQL2_HALT_CHECK if(running == FALSE) {state = SDQL2_STATE_HALTING; running = FALSE; return FALSE;}; -#define SDQL2_TICK_CHECK ((options & SDQL2_OPTION_HIGH_PRIORITY)? CHECK_TICK_HIGH_PRIORITY : CHECK_TICK) +#define SDQL2_TICK_CHECK ((high_priority == TRUE)? CHECK_TICK_HIGH_PRIORITY : CHECK_TICK) #define SDQL2_STAGE_SWITCH_CHECK if(state != SDQL2_STATE_SWITCHING){\ if(state == SDQL2_STATE_HALTING){\ state = SDQL2_STATE_IDLE;\ + running = FALSE;\ return FALSE}\ state = SDQL2_STATE_ERROR;\ + running = FALSE;\ CRASH("SDQL2 fatal error");}; /client/proc/SDQL2_query(query_text as message) @@ -282,8 +285,12 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null /datum/SDQL2_query var/list/query_tree + /// is running? separate for fast-ness + var/running = FALSE var/state = SDQL2_STATE_IDLE var/options = SDQL2_OPTIONS_DEFAULT + /// high priority? separate for fast-ness + var/high_priority = FALSE var/superuser = FALSE //Run things like proccalls without using admin protections var/allow_admin_interact = TRUE //Allow admins to do things to this excluding varedit these two vars var/static/id_assign = 1 @@ -325,6 +332,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null /datum/SDQL2_query/Destroy() state = SDQL2_STATE_HALTING + running = FALSE query_tree = null obj_count_all = null obj_count_eligible = null @@ -419,6 +427,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null message_admins(msg) log_admin(msg) state = SDQL2_STATE_HALTING + running = FALSE /datum/SDQL2_query/proc/admin_run(mob/user = usr) if(SDQL2_IS_RUNNING) @@ -449,6 +458,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null switch(value) if("high") options |= SDQL2_OPTION_HIGH_PRIORITY + high_priority = TRUE if("autogc") switch(value) if("keep_alive") @@ -470,6 +480,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null obj_count_eligible = 0 obj_count_finished = 0 start_time = REALTIMEOFDAY + running = TRUE state = SDQL2_STATE_PRESEARCH var/list/search_tree = PreSearch() @@ -485,6 +496,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null end_time = REALTIMEOFDAY state = SDQL2_STATE_IDLE + running = FALSE finished = TRUE . = TRUE if(show_next_to_key) @@ -509,6 +521,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null if("explain") SDQL_testout(query_tree["explain"]) state = SDQL2_STATE_HALTING + running = FALSE return if("call") . = query_tree["on"] diff --git a/code/modules/admin/verbs/debug/reestablish_db_connection.dm b/code/modules/admin/verbs/debug/reestablish_db_connection.dm index f40e05f1cfc..33f0e9d8524 100644 --- a/code/modules/admin/verbs/debug/reestablish_db_connection.dm +++ b/code/modules/admin/verbs/debug/reestablish_db_connection.dm @@ -30,4 +30,4 @@ message_admins("Database connection re-established") message_admins("Reloading client database data...") for(var/client/C in GLOB.clients) - C.database?.load() + C.player?.load() diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 68aa57e2ab9..2c9616ff3d2 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -630,7 +630,7 @@ Traitors and the like can also be revived with the previous role mostly intact. to_chat(src, "Only administrators may use this command.") return if(SSjob) - for(var/datum/job/job in SSjob.occupations) + for(var/datum/role/job/job in SSjob.occupations) to_chat(src, "[job.title]: [job.total_positions]") feedback_add_details("admin_verb","LFS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/verbs/tripAI.dm b/code/modules/admin/verbs/tripAI.dm index ac3de9fee47..390429d41dc 100644 --- a/code/modules/admin/verbs/tripAI.dm +++ b/code/modules/admin/verbs/tripAI.dm @@ -7,7 +7,7 @@ return if(SSjob && SSticker) - var/datum/job/job = SSjob.get_job("AI") + var/datum/role/job/job = SSjob.get_job("AI") if(!job) to_chat(usr, "Unable to locate the AI job") return diff --git a/code/modules/admin/view_variables/debug_variables.dm b/code/modules/admin/view_variables/debug_variables.dm index 367e1dace0b..58a215d74cd 100644 --- a/code/modules/admin/view_variables/debug_variables.dm +++ b/code/modules/admin/view_variables/debug_variables.dm @@ -48,8 +48,12 @@ else if (islist(value)) var/list/L = value var/list/items = list() - - if (L.len > 0 && !(name == "underlays" || name == "overlays" || L.len > (IS_NORMAL_LIST(L) ? VV_NORMAL_LIST_NO_EXPAND_THRESHOLD : VV_SPECIAL_LIST_NO_EXPAND_THRESHOLD))) + // don't expand if it's: + // 1. overlays - this info is rarely needing to be accessed unless you're doing overlay debugging + // 2. underlays - ditto + // 3. GLOB - there's a metric ton of lists on global variables and we want to avoid admins needing to download MB's of data instantly + // 4. if the list is too long otherwise + if (L.len > 0 && !(name == "underlays" || name == "overlays" || D == GLOB || L.len > (IS_NORMAL_LIST(L) ? VV_NORMAL_LIST_NO_EXPAND_THRESHOLD : VV_SPECIAL_LIST_NO_EXPAND_THRESHOLD))) for (var/i in 1 to L.len) var/key = L[i] var/val diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index d8971d6d7c6..6de67a81b73 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -59,9 +59,9 @@ M.equip_to_slot_or_del(new src.corpseback(M), SLOT_ID_BACK) if(src.corpseid == 1) var/obj/item/card/id/W = new(M) - var/datum/job/jobdatum - for(var/jobtype in typesof(/datum/job)) - var/datum/job/J = new jobtype + var/datum/role/job/jobdatum + for(var/jobtype in typesof(/datum/role/job)) + var/datum/role/job/J = new jobtype if(J.title == corpseidaccess) jobdatum = J break diff --git a/code/modules/client/client.dm b/code/modules/client/client.dm index ceb710ef588..e51461aa8d6 100644 --- a/code/modules/client/client.dm +++ b/code/modules/client/client.dm @@ -42,7 +42,7 @@ /// Persistent round-by-round data holder var/datum/client_data/persistent /// Database data - var/datum/client_dbdata/database + var/datum/player_data/player //! Rendering /// Click catcher diff --git a/code/modules/client/data.dm b/code/modules/client/client_data.dm similarity index 100% rename from code/modules/client/data.dm rename to code/modules/client/client_data.dm diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 1fdb918a2ed..8748a10531d 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -280,13 +280,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( log_admin_private("Notice: [key_name(src)] has the same [matches] as [key_name(C)] (no longer logged in).") - if(GLOB.player_details[ckey]) - player_details = GLOB.player_details[ckey] - player_details.byond_version = full_version - else - player_details = new(ckey) - player_details.byond_version = full_version - GLOB.player_details[ckey] = player_details */ //! WARNING: mob.login is always called async, aka immediately returns on sleep. @@ -303,8 +296,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( // resolve database data // this is down here because player_lookup won't have an entry for us until log_client_to_db() runs!! - database = new(ckey) - database.log_connect() + player = new(ckey) + player.log_connect() if (byond_version >= 512) if (!byond_build || byond_build < 1386) @@ -450,7 +443,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( log_access("Logout: [key_name(src)]") GLOB.ahelp_tickets.ClientLogout(src) persistent = null - database = null + player = null if(prefs) prefs.client = null prefs = null diff --git a/code/modules/client/database.dm b/code/modules/client/player_data.dm similarity index 88% rename from code/modules/client/database.dm rename to code/modules/client/player_data.dm index f1dcd867fd1..d2ed3d8f9ee 100644 --- a/code/modules/client/database.dm +++ b/code/modules/client/player_data.dm @@ -2,7 +2,7 @@ * holds db-related data * loaded every connect */ -/datum/client_dbdata +/datum/player_data //! intrinsics /// our ckey var/ckey @@ -23,7 +23,7 @@ /// player age var/player_age -/datum/client_dbdata/New(ckey) +/datum/player_data/New(ckey) src.ckey = ckey if(!src.ckey) return @@ -32,7 +32,7 @@ /** * async */ -/datum/client_dbdata/proc/load() +/datum/player_data/proc/load() if(!SSdbcore.Connect()) if(isnull(available)) available = FALSE @@ -40,7 +40,7 @@ INVOKE_ASYNC(src, .proc/load_blocking) return TRUE -/datum/client_dbdata/proc/load_blocking() +/datum/player_data/proc/load_blocking() // allow admin proccalls - there's no args here. var/was_proccall = !!IsAdminAdvancedProcCall() var/old_usr = usr @@ -48,7 +48,7 @@ _load_lock(was_proccall) usr = old_usr -/datum/client_dbdata/proc/_load_lock(was_proccall) +/datum/player_data/proc/_load_lock(was_proccall) if(IsAdminAdvancedProcCall()) return if(loading) @@ -59,7 +59,7 @@ _load() loading = FALSE -/datum/client_dbdata/proc/_load() +/datum/player_data/proc/_load() if(IsAdminAdvancedProcCall()) return var/datum/db_query/lookup @@ -105,7 +105,7 @@ qdel(lookup) register_new_player(lookup_firstseen, lookup_id) -/datum/client_dbdata/proc/register_new_player(migrate_firstseen, lookup_id) +/datum/player_data/proc/register_new_player(migrate_firstseen, lookup_id) if(IsAdminAdvancedProcCall()) return // new person! @@ -149,7 +149,7 @@ /** * async */ -/datum/client_dbdata/proc/save() +/datum/player_data/proc/save() set waitfor = FALSE // why are we in here if we're write locked? if(saving) @@ -168,7 +168,7 @@ saving = FALSE usr = old_usr -/datum/client_dbdata/proc/_save() +/datum/player_data/proc/_save() qdel(SSdbcore.ExecuteQuery( "UPDATE [format_table_name("player")] SET flags = :flags WHERE id = :id", list( @@ -180,11 +180,11 @@ /** * async */ -/datum/client_dbdata/proc/log_connect() +/datum/player_data/proc/log_connect() set waitfor = FALSE update_last_seen() -/datum/client_dbdata/proc/update_last_seen() +/datum/player_data/proc/update_last_seen() // don't interrupt if(!block_on_available()) return FALSE @@ -199,7 +199,7 @@ /** * sync */ -/datum/client_dbdata/proc/player_age() +/datum/player_data/proc/player_age() UNTIL(!loading) return player_age @@ -207,7 +207,7 @@ * block until we know if we're available * then return if we are */ -/datum/client_dbdata/proc/block_on_available() +/datum/player_data/proc/block_on_available() UNTIL(!isnull(available)) return available @@ -215,5 +215,5 @@ * returns if we're available * if we don't know yet, return false */ -/datum/client_dbdata/proc/immediately_available() +/datum/player_data/proc/immediately_available() return !!available diff --git a/code/modules/client/player_details.dm b/code/modules/client/player_details.dm deleted file mode 100644 index 5e00e61c1df..00000000000 --- a/code/modules/client/player_details.dm +++ /dev/null @@ -1,28 +0,0 @@ - -///assoc list of ckey -> /datum/player_details -GLOBAL_LIST_EMPTY(player_details) - -// todo: roll into client_data datums -/datum/player_details - var/list/player_actions = list() - var/list/logging = list() - var/list/post_login_callbacks = list() - var/list/post_logout_callbacks = list() - var/list/played_names = list() //List of names this key played under this round - var/byond_version = "Unknown" -/* var/datum/achievement_data/achievements - -/datum/player_details/New(key) - achievements = new(key) -*/ -/proc/log_played_names(ckey, ...) - if(!ckey) - return - if(args.len < 2) - return - var/list/names = args.Copy(2) - var/datum/player_details/P = GLOB.player_details[ckey] - if(P) - for(var/name in names) - if(name) - P.played_names |= name diff --git a/code/modules/client/winset_wrappers.dm b/code/modules/client/wrappers.dm similarity index 100% rename from code/modules/client/winset_wrappers.dm rename to code/modules/client/wrappers.dm diff --git a/code/modules/events/meteors.dm b/code/modules/events/meteors.dm index fef2bb72452..ffffd337146 100644 --- a/code/modules/events/meteors.dm +++ b/code/modules/events/meteors.dm @@ -93,10 +93,8 @@ . = ..() if(!victim) return - var/skill = victim.get_helm_skill() + // todo: implement skill checks with math on this, do actual overmaps physics var/speed = victim.get_speed_legacy() - if(skill >= SKILL_PROF) - . = round(. * 0.5) if(!victim.is_moving()) // Standing still means less shit flies your way . = round(. * 0.1) if(speed < SHIP_SPEED_SLOW) // Slow and steady @@ -104,12 +102,3 @@ if(speed > SHIP_SPEED_FAST) // Sanic stahp . *= 2 - // Smol ship evasion - if(victim.vessel_size < SHIP_SIZE_LARGE && speed < SHIP_SPEED_FAST) - var/skill_needed = SKILL_PROF - if(speed < SHIP_SPEED_SLOW) - skill_needed = SKILL_ADEPT - if(victim.vessel_size < SHIP_SIZE_SMALL) - skill_needed = skill_needed - 1 - if(skill >= max(skill_needed, victim.skill_needed)) - . = round(. * 0.5) diff --git a/code/modules/ghostroles/instantiator.dm b/code/modules/ghostroles/instantiator.dm index 0f18a669f42..e7865ec97c3 100644 --- a/code/modules/ghostroles/instantiator.dm +++ b/code/modules/ghostroles/instantiator.dm @@ -159,9 +159,11 @@ /datum/ghostrole_instantiator/human/player_static/Create(client/C, atom/location, list/params) var/mob/living/carbon/human/H = ..() var/list/errors = list() + // todo: respect warnings; we ignore them right now so we don't block joins. if(!C.prefs.spawn_checks(PREF_COPY_TO_FOR_GHOSTROLE, errors)) to_chat(C, SPAN_WARNING("An error has occured while attempting to spawn you in:
[errors.Join("
")]")) return + LoadSavefile(C, H) return H diff --git a/code/modules/ghostroles/menu.dm b/code/modules/ghostroles/menu.dm index 1763e6d3603..07cdf83d827 100644 --- a/code/modules/ghostroles/menu.dm +++ b/code/modules/ghostroles/menu.dm @@ -16,7 +16,7 @@ GLOBAL_DATUM_INIT(ghostrole_menu, /datum/ghostrole_menu, new) var/list/spawners = list() .["spawners"] = spawners for(var/id in GLOB.ghostroles) - var/datum/ghostrole/role = GLOB.ghostroles[id] + var/datum/role/ghostrole/role = GLOB.ghostroles[id] if(!istype(role)) stack_trace("non ghostrole [role] ([id]) pruned from ghostroles list.") GLOB.ghostroles -= id @@ -37,7 +37,7 @@ GLOBAL_DATUM_INIT(ghostrole_menu, /datum/ghostrole_menu, new) if(!isobserver(usr)) return var/id = params["id"] - var/datum/ghostrole/role = get_ghostrole_datum(id) + var/datum/role/ghostrole/role = get_ghostrole_datum(id) if(!role) return switch(action) diff --git a/code/modules/ghostroles/role.dm b/code/modules/ghostroles/role.dm index a3aa1cf2333..08052c27cbd 100644 --- a/code/modules/ghostroles/role.dm +++ b/code/modules/ghostroles/role.dm @@ -2,8 +2,8 @@ GLOBAL_LIST_INIT(ghostroles, init_ghostroles()) /proc/init_ghostroles() . = list() - for(var/path in subtypesof(/datum/ghostrole)) - var/datum/ghostrole/G = path + for(var/path in subtypesof(/datum/role/ghostrole)) + var/datum/role/ghostrole/G = path if(initial(G.abstract_type) == path) continue if(initial(G.lazy_init)) @@ -17,16 +17,16 @@ GLOBAL_LIST_INIT(ghostroles, init_ghostroles()) if(GLOB.ghostroles[path]) return GLOB.ghostroles[path] var/is_this_a_path = ispath(path)? path : text2path(path) - if(ispath(is_this_a_path, /datum/ghostrole)) + if(ispath(is_this_a_path, /datum/role/ghostrole)) GLOB.ghostroles[is_this_a_path] = new is_this_a_path return GLOB.ghostroles[is_this_a_path] /** * Ghostrole datums */ -/datum/ghostrole +/datum/role/ghostrole /// Abstract type. - abstract_type = /datum/ghostrole + abstract_type = /datum/role/ghostrole /// name var/name = "Unnamed Role" @@ -61,12 +61,12 @@ GLOBAL_LIST_INIT(ghostroles, init_ghostroles()) /// inject params during spawning var/list/inject_params -/datum/ghostrole/New(_id) +/datum/role/ghostrole/New(_id) if(ispath(instantiator, /datum/ghostrole_instantiator)) instantiator = new instantiator id = _id || type -/datum/ghostrole/proc/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) +/datum/role/ghostrole/proc/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) if(show_standard_greeting) to_chat(created, "
You have spawned as a ghostrole. These roles should be taken seriously. Be sure to follow the directives in your spawntext (if any), as well as the server rules. Beyond that, roleplay your character however you see fit! Spawntext as follows;
") if(spawntext) @@ -74,7 +74,7 @@ GLOBAL_LIST_INIT(ghostroles, init_ghostroles()) if(spawnpoint.spawntext) to_chat(created, "
[spawntext]
") -/datum/ghostrole/proc/ImportantInfo(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) +/datum/role/ghostrole/proc/ImportantInfo(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) if(important_info) to_chat(created, "
[important_info]
") @@ -83,7 +83,7 @@ GLOBAL_LIST_INIT(ghostroles, init_ghostroles()) * * Return TRUe on success, or a string of why it failed. */ -/datum/ghostrole/proc/AttemptSpawn(client/C, datum/component/ghostrole_spawnpoint/chosen_spawnpoint) +/datum/role/ghostrole/proc/AttemptSpawn(client/C, datum/component/ghostrole_spawnpoint/chosen_spawnpoint) if(BanCheck(C)) return "You can't spawn as [src] due to an active job-ban." if(!AllowSpawn(C)) @@ -112,13 +112,13 @@ GLOBAL_LIST_INIT(ghostroles, init_ghostroles()) GLOB.ghostrole_menu.queue_update() return TRUE -/datum/ghostrole/proc/Instantiate(client/C, atom/loc, list/params) +/datum/role/ghostrole/proc/Instantiate(client/C, atom/loc, list/params) var/mob/living/L = instantiator.Run(C, loc, params) . = istype(L) && L if(.) L.mind?.assigned_role = assigned_role || name -/datum/ghostrole/proc/Transfer(client/C, mob/created) +/datum/role/ghostrole/proc/Transfer(client/C, mob/created) if(!isnewplayer(C.mob)) C.mob.ghostize(TRUE, TRUE) created.ckey = C.ckey @@ -127,25 +127,25 @@ GLOBAL_LIST_INIT(ghostroles, init_ghostroles()) /** * Ran before anything else is at AttemptSpawn() */ -/datum/ghostrole/proc/PreInstantiate(client/C) +/datum/role/ghostrole/proc/PreInstantiate(client/C) return TRUE /** * Checks if the client is a valid user mob and if we can allow a spawn from them */ -/datum/ghostrole/proc/AllowSpawn(client/C, list/params) +/datum/role/ghostrole/proc/AllowSpawn(client/C, list/params) if(!isobserver(C.mob) && !isnewplayer(C.mob)) return FALSE if(SpawnsLeft(C) <= 0) return FALSE return TRUE -/datum/ghostrole/proc/SpawnsLeft(client/C) +/datum/role/ghostrole/proc/SpawnsLeft(client/C) if(spawnerless) return max(0, slots - spawns) return min(max(0, slots - spawns), TallySpawnpointSlots(C)) -/datum/ghostrole/proc/TallySpawnpointSlots(client/C) +/datum/role/ghostrole/proc/TallySpawnpointSlots(client/C) var/list/datum/component/ghostrole_spawnpoint/spawnpoints = GLOB.ghostrole_spawnpoints[id] . = 0 for(var/datum/component/ghostrole_spawnpoint/S as anything in spawnpoints) @@ -156,7 +156,7 @@ GLOBAL_LIST_INIT(ghostroles, init_ghostroles()) * * For spawnerless ghostroles, return null. */ -/datum/ghostrole/proc/GetSpawnpoint(client/C) +/datum/role/ghostrole/proc/GetSpawnpoint(client/C) if(!allow_pick_spawner) return SAFEPICK(GLOB.ghostrole_spawnpoints[id]) var/list/datum/component/ghostrole_spawnpoint/spawnpoints = GLOB.ghostrole_spawnpoints[id] @@ -172,13 +172,13 @@ GLOBAL_LIST_INIT(ghostroles, init_ghostroles()) * * spawnpoint can be null for spawnerless ghostroles. */ -/datum/ghostrole/proc/GetSpawnLoc(client/C, datum/component/ghostrole_spawnpoint/spawnpoint) +/datum/role/ghostrole/proc/GetSpawnLoc(client/C, datum/component/ghostrole_spawnpoint/spawnpoint) return spawnpoint?.Turf() /** * Spawnpoint can be null here, if we're not using a spawnpoint */ -/datum/ghostrole/proc/PostInstantiate(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) +/datum/role/ghostrole/proc/PostInstantiate(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) Greet(created, spawnpoint, params) ImportantInfo(created, spawnpoint, params) if(automatic_objective) @@ -190,15 +190,15 @@ GLOBAL_LIST_INIT(ghostroles, init_ghostroles()) /** * Ban check. */ -/datum/ghostrole/proc/BanCheck(client/C) +/datum/role/ghostrole/proc/BanCheck(client/C) if(!jobban_role) return FALSE return jobban_isbanned(C.mob, jobban_role) -/datum/ghostrole/proc/GiveCustomObjective(mob/created, objective) +/datum/role/ghostrole/proc/GiveCustomObjective(mob/created, objective) created.GhostroleGiveCustomObjective(src, objective) -/mob/proc/GhostroleGiveCustomObjective(datum/ghostrole/R, objective) +/mob/proc/GhostroleGiveCustomObjective(datum/role/ghostrole/R, objective) if(!mind) mind_initialize() if(!mind) diff --git a/code/modules/ghostroles/roles/ashlander.dm b/code/modules/ghostroles/roles/ashlander.dm index f42c0cb70d5..070e7178321 100644 --- a/code/modules/ghostroles/roles/ashlander.dm +++ b/code/modules/ghostroles/roles/ashlander.dm @@ -1,4 +1,4 @@ -/datum/ghostrole/ashlander +/datum/role/ghostrole/ashlander name = "Ashlander" assigned_role = "Ashlander" desc = "You are an Ashlander! An old and storied race of subterranean xenos." @@ -6,7 +6,7 @@ important_info = "The nomadic Ashlanders are a neutral party. The Ashlander race (Scorian), is selected by default. If you accidentally swap, make sure to change it back. Ashlanders are all permadeath characters. They have gray skin of varying hues, red eyes, and - typically - white, black, or brown hair. These options are selectable through the appearance menu, directly below the race block, and above hairstyles. " instantiator = /datum/ghostrole_instantiator/human/random/species/ashlander -/datum/ghostrole/ashlander/Instantiate(client/C, atom/loc, list/params) +/datum/role/ghostrole/ashlander/Instantiate(client/C, atom/loc, list/params) var/rp = rand(1, 7) switch(rp) if(1) @@ -25,7 +25,7 @@ params["fluff"] = "priest" return ..() -/datum/ghostrole/ashlander/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) +/datum/role/ghostrole/ashlander/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) . = ..() var/flavour_text = "Fine particles of ash slip past the fluttering Goliath hide covering your doorway to settle on the floor of the yurt. \ The hide is patched, and worn from years of use - it was gifted to you many Storms ago. Outside, the baking heat of the planet's surface \ @@ -120,7 +120,7 @@ icon_state = "yurt" anchored = TRUE density = TRUE - role_type = /datum/ghostrole/ashlander + role_type = /datum/role/ghostrole/ashlander role_spawns = 1 //var/datum/team/ashlanders/team @@ -139,7 +139,7 @@ params["fluff"] = "sentry" return ..() -/datum/ghostrole/ashlander/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) +/datum/role/ghostrole/ashlander/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) . = ..() var/flavour_text = "Fine particles of ash slip past the fluttering Goliath hide covering your doorway to settle on the floor of the yurt. \ The hide is patched, and worn from years of use - it was gifted to you many Storms ago. Outside, the baking heat of the planet's surface \ @@ -213,7 +213,7 @@ else to_chat(created, "You have awoken outside of your natural home! Whether you decide to return below the surface, or make due with your current surroundings is your own decision.") -/datum/ghostrole/ashlander/AllowSpawn(client/C, list/params) +/datum/role/ghostrole/ashlander/AllowSpawn(client/C, list/params) if(params && params["team"]) var/datum/team/ashlanders/team = params["team"] if(C.ckey in team.players_spawned) @@ -221,7 +221,7 @@ return FALSE return ..() -/datum/ghostrole/ashlander/PostInstantiate(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) +/datum/role/ghostrole/ashlander/PostInstantiate(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) . = ..() if(params["team"]) var/datum/team/ashlanders/team = spawnpoint.params["team"] diff --git a/code/modules/ghostroles/roles/cybersun_cruiser.dm b/code/modules/ghostroles/roles/cybersun_cruiser.dm index b87e009ff3a..11388ef8631 100644 --- a/code/modules/ghostroles/roles/cybersun_cruiser.dm +++ b/code/modules/ghostroles/roles/cybersun_cruiser.dm @@ -1,8 +1,8 @@ -/datum/ghostrole/cybersun - abstract_type = /datum/ghostrole/cybersun +/datum/role/ghostrole/cybersun + abstract_type = /datum/role/ghostrole/cybersun assigned_role = "Space Syndicate" -/datum/ghostrole/cybersun/ship +/datum/role/ghostrole/cybersun/ship name = "Cybersun Ship Operative" name = "Syndicate Battlecruiser Ship Operative" desc = "You are a crewmember aboard the syndicate flagship: the SBC Starfury." @@ -10,14 +10,14 @@
Furthermore, the armory is not a candy store, and your role is not to assault the station directly, leave that work to the assault operatives." instantiator = /datum/ghostrole_instantiator/human/random/cybersun/ship -/datum/ghostrole/cybersun/assault +/datum/role/ghostrole/cybersun/assault name = "Cybersun Assault Operative" desc = "You are an assault operative aboard the syndicate flagship: the SBC Starfury." spawntext = "Your job is to follow your captain's orders, keep intruders out of the ship, and assault Space Station 13. There is an armory, multiple assault ships, and beam cannons to attack the station with. \
Work as a team with your fellow operatives and work out a plan of attack. If you are overwhelmed, escape back to your ship!" instantiator = /datum/ghostrole_instantiator/human/random/cybersun/assault -/datum/ghostrole/cybersun/captain +/datum/role/ghostrole/cybersun/captain name = "Cybersun Ship Captain" desc = "You are the captain aboard the syndicate flagship: the SBC Starfury." spawntext = "Your job is to oversee your crew, defend the ship, and destroy Space Station 13. The ship has an armory, multiple ships, beam cannons, and multiple crewmembers to accomplish this goal. \ @@ -50,13 +50,13 @@ role_type = null /obj/structure/ghost_role_spawner/syndicate/battlecruiser - role_type = /datum/ghostrole/cybersun/ship + role_type = /datum/role/ghostrole/cybersun/ship /obj/structure/ghost_role_spawner/syndicate/battlecruiser/assault - role_type = /datum/ghostrole/cybersun/assault + role_type = /datum/role/ghostrole/cybersun/assault /obj/structure/ghost_role_spawner/syndicate/battlecruiser/captain - role_type = /datum/ghostrole/cybersun/captain + role_type = /datum/role/ghostrole/cybersun/captain /datum/outfit/syndicate_empty name = "Syndicate Operative Empty" diff --git a/code/modules/ghostroles/roles/demonic_friend.dm b/code/modules/ghostroles/roles/demonic_friend.dm index 3f96e2e86c8..b170806734e 100644 --- a/code/modules/ghostroles/roles/demonic_friend.dm +++ b/code/modules/ghostroles/roles/demonic_friend.dm @@ -1,10 +1,10 @@ -/datum/ghostrole/demonic_friend +/datum/role/ghostrole/demonic_friend name = "Demonic Friend" desc = "You are someone's demonic friend from hell." instantiator = /datum/ghostrole_instantiator/human/random/demonic_friend assigned_role = "SuperFriend" -/datum/ghostrole/demonic_friend/PostInstantiate(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) +/datum/role/ghostrole/demonic_friend/PostInstantiate(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) . = ..() if(params["spell"]) var/obj/effect/proc_holder/spell/targeted/summon_friend/S = spawnpoint?.params["spell"] @@ -23,7 +23,7 @@ else addtimer(CALLBACK(created, /mob/proc/dust), 15 SECONDS) -/datum/ghostrole/demonic_friend/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) +/datum/role/ghostrole/demonic_friend/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) . = ..() if(params["owner"]) var/datum/mind/owner = spawnpoint?.params["owner"] @@ -55,7 +55,7 @@ desc = "Oh boy! Oh boy! A friend!" icon = 'icons/obj/cardboard_cutout.dmi' icon_state = "cutout_basic" - role_type = /datum/ghostrole/demonic_friend + role_type = /datum/role/ghostrole/demonic_friend /datum/outfit/demonic_friend name = "Demonic Friend" @@ -65,4 +65,4 @@ back = /obj/item/storage/backpack implants = list(/obj/item/implant/mindshield) //No revolutionaries, he's MY friend. id = /obj/item/card/id - access_clone = /datum/job/assistant + access_clone = /datum/role/job/assistant diff --git a/code/modules/ghostroles/roles/fugitives.dm b/code/modules/ghostroles/roles/fugitives.dm index dc2bdd33b08..208fba26ee0 100644 --- a/code/modules/ghostroles/roles/fugitives.dm +++ b/code/modules/ghostroles/roles/fugitives.dm @@ -1,9 +1,9 @@ -/datum/ghostrole/fugitive_hunter +/datum/role/ghostrole/fugitive_hunter name = "Fugitive Hunter" desc = "Independent bounty hunters sent after fugitives" instantiator = /datum/ghostrole_instantiator/human/random/fugitive_hunter -/datum/ghostrole/fugitive_hunter/PostInstantiate(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) +/datum/role/ghostrole/fugitive_hunter/PostInstantiate(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) . = ..() var/datum/antagonist/fugitive_hunter/fughunter = new fughunter.backstory = params["bcakstory"] @@ -31,7 +31,7 @@ return ..() /obj/structure/ghost_role_spawner/fugitive_hunter - role_type = /datum/ghostrole/fugitive_hunter + role_type = /datum/role/ghostrole/fugitive_hunter var/backstory var/outfit diff --git a/code/modules/ghostroles/roles/ghost_cafe.dm b/code/modules/ghostroles/roles/ghost_cafe.dm index c44b2467007..44aa3229c80 100644 --- a/code/modules/ghostroles/roles/ghost_cafe.dm +++ b/code/modules/ghostroles/roles/ghost_cafe.dm @@ -1,5 +1,5 @@ -/datum/ghostrole/ghost_cafe +/datum/role/ghostrole/ghost_cafe name = "Ghost Cafe Visitor" assigned_role = "Ghost Cafe Visitor" desc = "Off-station area for ghosts to roleplay in." @@ -11,7 +11,7 @@ name = "Ghost Cafe Sleeper" icon = 'icons/obj/machines/sleeper.dmi' icon_state = "sleeper" - role_type = /datum/ghostrole/ghost_cafe + role_type = /datum/role/ghostrole/ghost_cafe role_spawns = INFINITY /datum/action/toggle_dead_chat_mob @@ -97,7 +97,7 @@ H.remove_alt_appearance("ghost_cafe_disguise") currently_disguised = FALSE -/datum/ghostrole/ghost_cafe/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) +/datum/role/ghostrole/ghost_cafe/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) . = ..() to_chat(created,"Ghosting is free!") diff --git a/code/modules/ghostroles/roles/golem.dm b/code/modules/ghostroles/roles/golem.dm index 69d0b99648b..4a28ea35f28 100644 --- a/code/modules/ghostroles/roles/golem.dm +++ b/code/modules/ghostroles/roles/golem.dm @@ -1,7 +1,7 @@ -/datum/ghostrole/golem +/datum/role/ghostrole/golem instantiator = /datum/ghostrole_instantiator/human/random/species/golem -/datum/ghostrole/golem/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) +/datum/role/ghostrole/golem/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) . = ..() var/mob/living/carbon/human/H = created if(!istype(H)) @@ -11,18 +11,18 @@ return to_chat(created, G.info_text) -/datum/ghostrole/golem/free +/datum/role/ghostrole/golem/free name = "Free Golem" desc = "You are a Free Golem. Your family worships The Liberator." spawntext = "In his infinite and divine wisdom, he set your clan free to \ travel the stars with a single declaration: \"Yeah go do whatever.\" Though you are bound to the one who created you, it is customary in your society to repeat those same words to newborn \ golems, so that no golem may ever be forced to serve again." -/datum/ghostrole/golem/free/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) +/datum/role/ghostrole/golem/free/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) . = ..() to_chat(created, span_boldwarning("Build golem shells in the autolathe, and feed refined mineral sheets to the shells to bring them to life! You are generally a peaceful group unless provoked.")) -/datum/ghostrole/golem/servant +/datum/role/ghostrole/golem/servant name = "Servant Golem" desc = "You are a golem." spawntext = "You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools." @@ -30,7 +30,7 @@ "servant" = TRUE ) -/datum/ghostrole/golem/servant/PostInstantiate(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) +/datum/role/ghostrole/golem/servant/PostInstantiate(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) . = ..() var/datum/mind/creator_mind = params["creator"] if(!creator_mind) @@ -85,13 +85,13 @@ return ..(mapload, list( "species" = species, "creator" = creator && (istype(creator, /datum/mind)? creator : creator.mind) - ), (has_owner && creator)? /datum/ghostrole/golem/servant : /datum/ghostrole/golem/free) + ), (has_owner && creator)? /datum/role/ghostrole/golem/servant : /datum/role/ghostrole/golem/free) /obj/structure/ghost_role_spawner/golem/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(isgolem(user) && can_transfer) // this is a bit special // we want them to keep their mind, so.... - var/datum/ghostrole/G = get_ghostrole_datum(/datum/ghostrole/golem/free) + var/datum/role/ghostrole/G = get_ghostrole_datum(/datum/role/ghostrole/golem/free) if(!G?.instantiator) CRASH("Couldn't locate freegolem instantiator") var/datum/ghostrole_instantiator/I = G.instantiator diff --git a/code/modules/ghostroles/roles/hermit.dm b/code/modules/ghostroles/roles/hermit.dm index 199b1267497..a39ca2d7f0a 100644 --- a/code/modules/ghostroles/roles/hermit.dm +++ b/code/modules/ghostroles/roles/hermit.dm @@ -1,11 +1,11 @@ -/datum/ghostrole/hermit +/datum/role/ghostrole/hermit name = "Space Hermit" assigned_role = "Hermit" desc = "A stranded cryo-occupant in deep space." spawntext = "You've been late to awaken from your cryo slumber. Blasted machine, you set it to 10 days not 10 weeks! Where have the others gone while we were out? Did they manage to survive?" instantiator = /datum/ghostrole_instantiator/human/random/hermit -/datum/ghostrole/hermit/Instantiate(client/C, atom/loc, list/params) +/datum/role/ghostrole/hermit/Instantiate(client/C, atom/loc, list/params) var/rp = rand(1, 4) switch(rp) if(1) @@ -18,7 +18,7 @@ params["fluff"] = "tourist" return ..() -/datum/ghostrole/hermit/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) +/datum/role/ghostrole/hermit/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) . = ..() var/flavour_text = "Each day you barely scrape by, and between the terrible conditions of your makeshift shelter, \ the hostile creatures, and the relentless yawn of the cloudless skies, all you can wish for is the feel of soft grass between your toes and \ @@ -75,7 +75,7 @@ desc = "A humming sleeper with a silhouetted occupant inside. Its stasis function is broken and it's likely being used as a bed." icon = 'icons/obj/spawners.dmi' icon_state = "cryostasis_sleeper" - role_type = /datum/ghostrole/hermit + role_type = /datum/role/ghostrole/hermit qdel_on_deplete = TRUE /obj/structure/ghost_role_spawner/hermit/Destroy() diff --git a/code/modules/ghostroles/roles/hotel.dm b/code/modules/ghostroles/roles/hotel.dm index 15b8a4afd75..5a86f4ead6b 100644 --- a/code/modules/ghostroles/roles/hotel.dm +++ b/code/modules/ghostroles/roles/hotel.dm @@ -1,11 +1,11 @@ -/datum/ghostrole/space_hotel +/datum/role/ghostrole/space_hotel instantiator = /datum/ghostrole_instantiator/human/random/space_hotel name = "Space Hotel Staff" desc = "You are a staff member of a top-of-the-line space hotel! Cater to guests and make sure the manager doesn't fire you." automatic_objective = "You are a staff member of a top-of-the-line space hotel! Cater to guests and make sure the manager doesn't fire you." assigned_role = "Hotel Staff" -/datum/ghostrole/space_hotel/security +/datum/role/ghostrole/space_hotel/security instantiator = /datum/ghostrole_instantiator/human/random/space_hotel/security name = "Space Hotel Security" desc = "You have been assigned to this hotel to protect the interests of the company while keeping the peace between \ @@ -25,7 +25,7 @@ /obj/structure/ghost_role_spawner/space_hotel //not free antag u little shits name = "staff sleeper" desc = "A sleeper designed for long-term stasis between guest visits." - role_type = /datum/ghostrole/space_hotel + role_type = /datum/role/ghostrole/space_hotel icon = 'icons/obj/machines/sleeper.dmi' icon_state = "sleeper_s" @@ -35,7 +35,7 @@ /obj/structure/ghost_role_spawner/space_hotel/security name = "hotel security sleeper" - role_type = /datum/ghostrole/space_hotel/security + role_type = /datum/role/ghostrole/space_hotel/security /datum/outfit/hotelstaff name = "Hotel Staff" diff --git a/code/modules/ghostroles/roles/lifebringer.dm b/code/modules/ghostroles/roles/lifebringer.dm index a38a5fa6309..869e273bd33 100644 --- a/code/modules/ghostroles/roles/lifebringer.dm +++ b/code/modules/ghostroles/roles/lifebringer.dm @@ -1,4 +1,4 @@ -/datum/ghostrole/seed_vault +/datum/role/ghostrole/seed_vault name = "Lifebringer" desc = "You are a sentient ecosystem, an example of the mastery over life that your creators possessed." spawntext = "Your masters, benevolent as they were, created uncounted seed vaults and spread them across \ @@ -31,7 +31,7 @@ desc = "An ancient machine that seems to be used for storing plant matter. The glass is obstructed by a mat of vines." icon = 'icons/obj/lavaland/spawners.dmi' icon_state = "terrarium" - role_type = /datum/ghostrole/seed_vault + role_type = /datum/role/ghostrole/seed_vault /obj/structure/ghost_role_spawner/seed_vault/Destroy() new/obj/structure/fluff/empty_terrarium(get_turf(src)) diff --git a/code/modules/ghostroles/roles/oldresearch.dm b/code/modules/ghostroles/roles/oldresearch.dm index 72b924b5fc7..901b6740fd6 100644 --- a/code/modules/ghostroles/roles/oldresearch.dm +++ b/code/modules/ghostroles/roles/oldresearch.dm @@ -1,4 +1,4 @@ -/datum/ghostrole/old_research +/datum/role/ghostrole/old_research name = "Oldstation Crew" allow_pick_spawner = TRUE desc = "You were a Nanotrasen employee from an era past, stationed upon a state of the art research station. \ @@ -21,7 +21,7 @@ return /datum/outfit/old_research/scientist /obj/structure/ghost_role_spawner/old_research - role_type = /datum/ghostrole/old_research + role_type = /datum/role/ghostrole/old_research name = "old cryogenics pod" desc = "A humming cryo pod. You can barely recognise a security uniform underneath the built up ice. The machine is attempting to wake up its occupant." icon = 'icons/obj/machines/sleeper.dmi' diff --git a/code/modules/ghostroles/roles/pirate.dm b/code/modules/ghostroles/roles/pirate.dm index 1ce7290a865..fb42bdddcac 100644 --- a/code/modules/ghostroles/roles/pirate.dm +++ b/code/modules/ghostroles/roles/pirate.dm @@ -1,4 +1,4 @@ -/datum/ghostrole/pirate +/datum/role/ghostrole/pirate name = "Pirate" assigned_role = "Pirate" desc = "You are a pirate! A legendary, if oft maligned, profession." @@ -6,7 +6,7 @@ important_info = "You are a member of a pirate crew. You pillage, kidnap, and steal for profit and pleasure. Although you recently moved into this system, it is owned by NanoTrasen. A Corporate presence provides plenty of opportunities for plunder, but beware! Certain areas are considered off limits, even to pirates. Only a fool would anger Nebula Gas by raiding their station, although NebGas vessels in transit are fair game. Attempting to visit NanoTrasen's primary facility is equally dangerous and ill-advised. Focusing on isolated vessels in flight or expeditions on planets may be the most reliable way to score precious booty. Proteans and Xenochimerae are currently excluded from being Pirates, if you own either Whitelist." instantiator = /datum/ghostrole_instantiator/human/random/species/pirate -/datum/ghostrole/pirate/Instantiate(client/C, atom/loc, list/params) +/datum/role/ghostrole/pirate/Instantiate(client/C, atom/loc, list/params) var/rp = rand(1, 3) switch(rp) if(1) @@ -17,7 +17,7 @@ params["fluff"] = "professional" return ..() -/datum/ghostrole/pirate/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) +/datum/role/ghostrole/pirate/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) . = ..() var/flavour_text = "The sound of something dripping on the top of your bunk unit wakes you up. Spears of light shine in through old \ bullet holes. The unit's door slides back with the push of a button, letting stale recycled air rush out. A yellowed poster on the wall \ @@ -67,7 +67,7 @@ icon_state = "piratebunk" anchored = TRUE density = TRUE - role_type = /datum/ghostrole/pirate + role_type = /datum/role/ghostrole/pirate role_spawns = 1 //This is from the original untranslated DM. It still isn't translated, but this is neat and maybe we should use it sometime? It seems worth retaining for now. @@ -77,7 +77,7 @@ desc = "A cryo sleeper smelling faintly of rum. The sleeper looks unstable. Perhaps the pirate within can be killed with the right tools..." icon = 'icons/obj/machines/sleeper.dmi' icon_state = "sleeper" - role_type = /datum/ghostrole/pirate + role_type = /datum/role/ghostrole/pirate role_params = list( "rank" = "Mate" ) diff --git a/code/modules/ghostroles/roles/prisoner.dm b/code/modules/ghostroles/roles/prisoner.dm index 1909d71cbbf..9cfcca92e1c 100644 --- a/code/modules/ghostroles/roles/prisoner.dm +++ b/code/modules/ghostroles/roles/prisoner.dm @@ -1,10 +1,10 @@ -/datum/ghostrole/lavaland_prisoner +/datum/role/ghostrole/lavaland_prisoner name = "Lavaland Prisoner" desc = "You're a prisoner, sentenced to hard work in one of Nanotrasen's labor camps, but it seems as though fate has other plans for you." instantiator = /datum/ghostrole_instantiator/human/random/lavaland_prisoner assigned_role = "Escaped Prisoner" -/datum/ghostrole/lavaland_prisoner/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint) +/datum/role/ghostrole/lavaland_prisoner/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint) . = ..() var/list/crimes = list("murder", "larceny", "embezzlement", "unionization", "dereliction of duty", "kidnapping", "gross incompetence", "grand theft", "collaboration with the Syndicate", \ "worship of a forbidden deity", "interspecies relations", "mutiny") @@ -25,7 +25,7 @@ desc = "A sleeper designed to put its occupant into a deep coma, unbreakable until the sleeper turns off. This one's glass is cracked and you can see a pale, sleeping face staring out." icon = 'icons/obj/machines/sleeper.dmi' icon_state = "sleeper_s" - role_type = /datum/ghostrole/lavaland_prisoner + role_type = /datum/role/ghostrole/lavaland_prisoner /datum/outfit/lavalandprisoner name = "Lavaland Prisoner" diff --git a/code/modules/ghostroles/roles/timeless_prison.dm b/code/modules/ghostroles/roles/timeless_prison.dm index 4a89b733ee1..4c2e1fde0ad 100644 --- a/code/modules/ghostroles/roles/timeless_prison.dm +++ b/code/modules/ghostroles/roles/timeless_prison.dm @@ -1,11 +1,11 @@ -/datum/ghostrole/timeless_prison +/datum/role/ghostrole/timeless_prison name = "Timeless Prisoner" desc = "Years ago, you sacrificed the lives of your trusted friends and the humanity of yourself to reach the Wish Granter. Though you \ did so, it has come at a cost: your very body rejects the light, dooming you to wander endlessly in this horrible wasteland." instantiator = /datum/ghostrole_instantiator/human/random/species/shadow assigned_role = "Exile" -/datum/ghostrole/timeless_prison/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) +/datum/role/ghostrole/timeless_prison/Greet(mob/created, datum/component/ghostrole_spawnpoint/spawnpoint, list/params) . = ..() var/wish = rand(1,4) switch(wish) @@ -33,7 +33,7 @@ desc = "Although this stasis pod looks medicinal, it seems as though it's meant to preserve something for a very long time." icon = 'icons/obj/machines/sleeper.dmi' icon_state = "sleeper" - role_type = /datum/ghostrole/timeless_prison + role_type = /datum/role/ghostrole/timeless_prison /obj/structure/ghost_role_spawner/exile/Destroy() new/obj/structure/fluff/empty_sleeper(get_turf(src)) diff --git a/code/modules/ghostroles/roles/vet.dm b/code/modules/ghostroles/roles/vet.dm index 86fcf6b6417..068e2ed2d3c 100644 --- a/code/modules/ghostroles/roles/vet.dm +++ b/code/modules/ghostroles/roles/vet.dm @@ -1,4 +1,4 @@ -/datum/ghostrole/lavaland_vet +/datum/role/ghostrole/lavaland_vet name = "Lavaland Vet" desc = "You are a animal doctor who just woke up in lavaland" assigned_role = "Translocated Vet" @@ -10,7 +10,7 @@ /obj/structure/ghost_role_spawner/lavaland_vet name = "broken rejuvenation pod" desc = "A small sleeper typically used to instantly restore minor wounds. This one seems broken, and its occupant is comatose." - role_type = /datum/ghostrole/lavaland_vet + role_type = /datum/role/ghostrole/lavaland_vet /obj/structure/ghost_role_spawner/lavaland_vet/Destroy() var/obj/structure/fluff/empty_sleeper/S = new(drop_location()) diff --git a/code/modules/ghostroles/spawner.dm b/code/modules/ghostroles/spawner.dm index 7a2f538faac..59322690e6b 100644 --- a/code/modules/ghostroles/spawner.dm +++ b/code/modules/ghostroles/spawner.dm @@ -40,7 +40,7 @@ else AddComponent(/datum/component/ghostrole_spawnpoint, role_type, role_spawns, role_params, /obj/structure/ghost_role_spawner/proc/on_spawn, null, special_spawntext) -/obj/structure/ghost_role_spawner/proc/on_spawn(mob/created, datum/ghostrole/role, list/params, datum/component/ghostrole_spawnpoint/spawnpoint) +/obj/structure/ghost_role_spawner/proc/on_spawn(mob/created, datum/role/ghostrole/role, list/params, datum/component/ghostrole_spawnpoint/spawnpoint) if(qdel_on_deplete && !spawnpoint.SpawnsLeft()) qdel(src) @@ -66,7 +66,7 @@ return ..() /obj/structure/ghost_role_spawner/custom/proc/GenerateRole(id = role_type, mob_path = src.mob_path) - var/datum/ghostrole/G = get_ghostrole_datum(id) + var/datum/role/ghostrole/G = get_ghostrole_datum(id) if(G) return G = new(id) diff --git a/code/modules/ghostroles/spawnpoint.dm b/code/modules/ghostroles/spawnpoint.dm index 7c91eec5345..7792d5727b5 100644 --- a/code/modules/ghostroles/spawnpoint.dm +++ b/code/modules/ghostroles/spawnpoint.dm @@ -30,7 +30,7 @@ GLOBAL_LIST_EMPTY(ghostrole_spawnpoints) src.spawntext = spawntext src.proc_to_call_or_callback = proc_to_call_or_callback if(notify_ghosts) - var/datum/ghostrole/role = get_ghostrole_datum(role_type) + var/datum/role/ghostrole/role = get_ghostrole_datum(role_type) if(!role) return notify_ghosts("Ghostrole spawner created: [role.name] - [parent] - [get_area(parent)]", source = parent, ignore_mapload = TRUE, flashwindow = FALSE) @@ -72,7 +72,7 @@ GLOBAL_LIST_EMPTY(ghostrole_spawnpoints) /datum/component/ghostrole_spawnpoint/proc/SpawnsLeft(client/C) return max(0, max_spawns - spawns) -/datum/component/ghostrole_spawnpoint/proc/OnSpawn(mob/created, datum/ghostrole/role) +/datum/component/ghostrole_spawnpoint/proc/OnSpawn(mob/created, datum/role/ghostrole/role) if(istype(proc_to_call_or_callback)) proc_to_call_or_callback.Invoke(created, role, params, src) spawns++ @@ -89,13 +89,13 @@ GLOBAL_LIST_EMPTY(ghostrole_spawnpoints) /datum/component/ghostrole_spawnpoint/proc/Examine(datum/source, list/examine_list) if(isobserver(source)) - var/datum/ghostrole/role = get_ghostrole_datum(role_type) + var/datum/role/ghostrole/role = get_ghostrole_datum(role_type) if(!role) return examine_list += "Click this ghostrole spawner to become a [role.name]!" /datum/component/ghostrole_spawnpoint/proc/GhostInteract(datum/source, mob/user) - var/datum/ghostrole/role = get_ghostrole_datum(role_type) + var/datum/role/ghostrole/role = get_ghostrole_datum(role_type) if(!role) to_chat(user, SPAN_DANGER("No ghostrole datum found: [role_type]. Contact a coder!")) if(!(datum_flags & DF_VAR_EDITED)) diff --git a/code/modules/integrated_electronics/passive/power.dm b/code/modules/integrated_electronics/passive/power.dm index 2e9e9f8f739..5258ffa3a9e 100644 --- a/code/modules/integrated_electronics/passive/power.dm +++ b/code/modules/integrated_electronics/passive/power.dm @@ -143,7 +143,7 @@ var/list/data = reagents.get_data(I) if(data && istype(data["donor"], /mob/living/carbon/human)) var/mob/living/carbon/human/H = data["donor"] - if(H.mind && H.mind.key) + if(H.mind && H.mind.ckey) power *= 10 if(reagents.remove_reagent(I, 1)) assembly.give_power(fuel[I]) diff --git a/code/modules/jobs/_alt_title.dm b/code/modules/jobs/_alt_title.dm deleted file mode 100644 index acf676a2a90..00000000000 --- a/code/modules/jobs/_alt_title.dm +++ /dev/null @@ -1,8 +0,0 @@ -///////////////////////////////////////// -// Alt Title Code -///////////////////////////////////////// - -/datum/alt_title - var/title = "GENERIC ALT TITLE" // What the Alt-Title is called - var/title_blurb = null // What's amended to the job description for this Job title. If nothing's added, leave null. - var/title_outfit = null // The outfit used by the alt-title. If it's the same as the base job, leave this null. diff --git a/code/modules/jobs/access.dm b/code/modules/jobs/access.dm index 9873b21f113..7fd37b6268f 100644 --- a/code/modules/jobs/access.dm +++ b/code/modules/jobs/access.dm @@ -192,9 +192,9 @@ /proc/get_all_jobs() var/list/all_jobs = list() - var/list/all_datums = typesof(/datum/job) + var/list/all_datums = typesof(/datum/role/job) all_datums -= exclude_jobs - var/datum/job/jobdatum + var/datum/role/job/jobdatum for(var/jobtype in all_datums) jobdatum = new jobtype all_jobs.Add(jobdatum.title) diff --git a/code/modules/jobs/alt_title.dm b/code/modules/jobs/alt_title.dm new file mode 100644 index 00000000000..c72f61ec909 --- /dev/null +++ b/code/modules/jobs/alt_title.dm @@ -0,0 +1,24 @@ +///////////////////////////////////////// +// Alt Title Code +///////////////////////////////////////// + +/datum/prototype/alt_title + abstract_type = /datum/prototype/alt_title + namespace = "role_title" + anonymous = TRUE + + var/title = "GENERIC ALT TITLE" // What the Alt-Title is called + var/title_blurb = null // What's amended to the job description for this Job title. If nothing's added, leave null. + var/title_outfit = null // The outfit used by the alt-title. If it's the same as the base job, leave this null. + + /// restricted: require these hardcoded lore datums to be associated with the characters by typepath or id. + /// null for anything/anyone + var/list/background_restricted + +/datum/prototype/alt_title/New() + for(var/i in 1 to length(background_restricted)) + var/thing = background_restricted[i] + if(ispath(thing)) + var/datum/lore/character_background/bg = thing + background_restricted[i] = initial(bg.id) + return ..() diff --git a/code/modules/jobs/job.dm b/code/modules/jobs/job.dm index 88b57c04c06..e7616da4fc4 100644 --- a/code/modules/jobs/job.dm +++ b/code/modules/jobs/job.dm @@ -1,6 +1,6 @@ -/datum/job +/datum/role/job /// Abstract type. - abstract_type = /datum/job + abstract_type = /datum/role/job //? Intrinsics /// ID of the job, used for save/load @@ -18,8 +18,8 @@ /// starting money multiplier var/economy_payscale = ECONOMY_PAYSCALE_JOB_DEFAULT + //? unsorted // Job access. The use of minimal_access or access is determined by a config setting: config.jobs_have_minimal_access - /// Useful for servers which prefer to only have access given to the places a job absolutely needs (Larger server population). var/list/minimal_access = list() /// Useful for servers which either have fewer players, so each person needs to fill more than one role, or servers which like to give more access, so players can't hide forever in their super secure departments (I'm looking at you, chemistry!). @@ -41,6 +41,9 @@ var/selection_color = COLOR_WHITE /// List of alternate titles; There is no need for an alt-title datum for the base job title. var/list/alt_titles = null + // todo: optimize this, it's very non-performant. + /// Strict title mode: If an alt title is available for a specific background someone has, only that and other alt titles with that background can be chosen. + var/strict_titles = FALSE /// If this is set to 1, a text is printed to the player when jobs are assigned, telling him that he should let admins know that he has to disconnect. var/req_admin_notify /// If you have use_age_restriction_for_jobs config option enabled and the database set up, this option will add a requirement for players to be at least minimal_player_age days old. (meaning they first signed in at least that many days before.) @@ -83,16 +86,18 @@ // Disallow joining as this job midround from off-duty position via going on-duty var/disallow_jobhop = FALSE -/datum/job/New() +/datum/role/job/New() . = ..() GLOB.department_accounts = GLOB.department_accounts || departments_managed +//? Availability + /** * checks slots remaining * * @return 0 to number of slots remaining */ -/datum/job/proc/slots_remaining(latejoin) +/datum/role/job/proc/slots_remaining(latejoin) if(!latejoin) if(spawn_positions == -1) return INFINITY @@ -110,7 +115,7 @@ * * todo: check ckey proc too? */ -/datum/job/proc/check_client_availability(client/C, check_char, latejoin) +/datum/role/job/proc/check_client_availability(client/C, check_char, latejoin) . = NONE if(whitelist_only && !config.check_job_whitelist(ckey(title), C.ckey)) . |= ROLE_UNAVAILABLE_WHITELIST @@ -143,7 +148,7 @@ * * todo: check ckey proc too? */ -/datum/job/proc/check_client_availability_one(client/C, check_char, latejoin) +/datum/role/job/proc/check_client_availability_one(client/C, check_char, latejoin) . = NONE if(whitelist_only && !config.check_job_whitelist(ckey(title), C.ckey)) return ROLE_UNAVAILABLE_WHITELIST @@ -166,10 +171,30 @@ // todo: JEXP/ROLE-EXP hours system +// todo: this entire system is hellish and needs redone i hate preferences code +/** + * checks if we're available for a given *mob*, but short circuits with the most common + * checks first. + * + * this is used for stuff like jobswitch code + */ +/datum/role/job/proc/check_mob_availability_one(mob/M) + . = NONE + if(whitelist_only) // don't even bother checking mind + return ROLE_UNAVAILABLE_WHITELIST + else if(!slots_remaining(TRUE)) + return ROLE_UNAVAILABLE_SLOTS_FULL + else if(jobban_isbanned(M, title)) + return ROLE_UNAVAILABLE_BANNED + if(M.mind) + var/datum/lore/character_background/faction/fact = M.mind.original_background_faction() + if(fact && !fact.check_job_id(id)) + return ROLE_UNAVAILABLE_CHAR_FACTION + // todo: species check /** * get an user-friendly reason of why they can't spawn as us */ -/datum/job/proc/get_availability_reason(client/C, reason) +/datum/role/job/proc/get_availability_reason(client/C, reason) if(reason & ROLE_UNAVAILABLE_BANNED) return "BANNED" if(reason & ROLE_UNAVAILABLE_SLOTS_FULL) @@ -193,7 +218,7 @@ /** * get a short abbreviation for why they can't spawn as us; used for preferences */ -/datum/job/proc/get_availability_error(client/C, reason) +/datum/role/job/proc/get_availability_error(client/C, reason) if(reason & ROLE_UNAVAILABLE_BANNED) return "BANNED" if(reason & ROLE_UNAVAILABLE_SLOTS_FULL) @@ -205,7 +230,7 @@ if(reason & ROLE_UNAVAILABLE_WHITELIST) return "WHITELISTED" if(reason & ROLE_UNAVAILABLE_CONNECT_TIME) - return "IN [available_in_days(C)] DAYS" + return C? "IN [available_in_days(C)] DAYS" : "MIN ACCOUNT AGE" if(reason & ROLE_UNAVAILABLE_CHAR_AGE) return "MIN AGE: [minimum_character_age]" if(reason & ROLE_UNAVAILABLE_CHAR_FACTION) @@ -214,16 +239,90 @@ return "SPECIES" return "UNKNOWN (BUG)" -/datum/job/proc/equip(var/mob/living/carbon/human/H, var/alt_title) +//? Alt Titles + +/** + * get available alt title names for a given set of character backgrounds + */ +/datum/role/job/proc/alt_title_query(list/datum/lore/character_background/backgrounds = list()) + RETURN_TYPE(/list) + var/list/transformed = list() + for(var/datum/lore/character_background/bg as anything in backgrounds) + transformed += bg.id + if(strict_titles) + var/list/normal = list(title) + var/list/restricted = list() + for(var/title in alt_titles) + var/datum/prototype/alt_title/alt_datum = SSrepository.fetch(alt_titles[title]) + if(isnull(alt_datum)) + continue + if(isnull(alt_datum.background_restricted)) + normal |= alt_datum.title + continue + if(!length(alt_datum.background_restricted & transformed)) + normal -= alt_datum.title + // allow us to forcefully register the "main" title under alt title system + continue + restricted |= alt_datum.title + . = length(restricted)? restricted : normal + else + var/list/found = list(title) + for(var/title in alt_titles) + var/datum/prototype/alt_title/alt_datum = SSrepository.fetch(alt_titles[title]) + if(isnull(alt_datum)) + continue + if(isnull(alt_datum.background_restricted)) + found |= alt_datum.title + continue + if(!length(alt_datum.background_restricted & transformed)) + found -= alt_datum.title + // allow us to forcefully register the "main" title under alt title system + continue + found |= alt_datum.title + . = found + return length(.)? . : list(title) + +/** + * chcek if an alt title is available for a given set of backgrounds + */ +/datum/role/job/proc/alt_title_check(alt_title, list/datum/lore/character_background/backgrounds = list()) + var/list/transformed = list() + for(var/datum/lore/character_background/bg as anything in backgrounds) + transformed += bg.id + if(strict_titles) + var/found = FALSE + for(var/other_title in alt_titles) + var/datum/prototype/alt_title/alt_datum = SSrepository.fetch(alt_titles[other_title]) + if(length(alt_datum.background_restricted & transformed)) + found = TRUE + break + var/datum/prototype/alt_title/alt_datum = SSrepository.fetch(alt_titles?[alt_title]) + if(isnull(alt_datum)) + if(alt_title == title) + return !found + else + return FALSE + return length(alt_datum.background_restricted & transformed) || (!found && !alt_datum.background_restricted) + else + if(alt_title == title) + return TRUE + var/datum/prototype/alt_title/alt_datum = SSrepository.fetch(alt_titles?[alt_title]) + if(isnull(alt_datum)) + return FALSE + return isnull(alt_datum.background_restricted) || length(transformed & alt_datum.background_restricted) + +//? Unsorted + +/datum/role/job/proc/equip(var/mob/living/carbon/human/H, var/alt_title) var/datum/outfit/outfit = get_outfit(H, alt_title) if(!outfit) return FALSE . = outfit.equip(H, title, alt_title) return 1 -/datum/job/proc/get_outfit(var/mob/living/carbon/human/H, var/alt_title) +/datum/role/job/proc/get_outfit(var/mob/living/carbon/human/H, var/alt_title) if(alt_title && alt_titles) - var/datum/alt_title/A = alt_titles[alt_title] + var/datum/prototype/alt_title/A = alt_titles[alt_title] if(A && initial(A.title_outfit)) . = initial(A.title_outfit) . = . || outfit_type @@ -232,11 +331,11 @@ // TODO: job refactor -/datum/job/proc/get_economic_payscale() +/datum/role/job/proc/get_economic_payscale() var/datum/department/D = SSjob.get_primary_department_of_job(src) return economy_payscale * (istype(D)? D.economy_payscale : 1) -/datum/job/proc/setup_account(var/mob/living/carbon/human/H) +/datum/role/job/proc/setup_account(var/mob/living/carbon/human/H) if(!account_allowed || (H.mind && H.mind.initial_account)) return @@ -260,61 +359,61 @@ to_chat(H, "Your account number is: [M.account_number], your account pin is: [M.remote_access_pin]") // Overrideable separately so AIs/borgs can have cardborg hats without unneccessary new()/qdel() -/datum/job/proc/equip_preview(mob/living/carbon/human/H, var/alt_title) +/datum/role/job/proc/equip_preview(mob/living/carbon/human/H, var/alt_title) var/datum/outfit/outfit = get_outfit(H, alt_title) if(!outfit) return FALSE . = outfit.equip_base(H, title, alt_title) -/datum/job/proc/get_access() +/datum/role/job/proc/get_access() if(!config || config_legacy.jobs_have_minimal_access) return src.minimal_access.Copy() else return src.access.Copy() // 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/job/proc/player_old_enough(client/C) +/datum/role/job/proc/player_old_enough(client/C) return (available_in_days(C) == 0) // Available in 0 days = available right now = player is old enough to play. -/datum/job/proc/available_in_days(client/C) +/datum/role/job/proc/available_in_days(client/C) if(C.has_jexp_bypass()) return 0 if(C && config_legacy.use_age_restriction_for_jobs && isnum(C.player_age) && isnum(minimal_player_age)) return max(0, minimal_player_age - C.player_age) return 0 -/datum/job/proc/apply_fingerprints(var/mob/living/carbon/human/target) +/datum/role/job/proc/apply_fingerprints(var/mob/living/carbon/human/target) if(!istype(target)) return 0 for(var/obj/item/item in target.contents) apply_fingerprints_to_item(target, item) return 1 -/datum/job/proc/apply_fingerprints_to_item(var/mob/living/carbon/human/holder, var/obj/item/item) +/datum/role/job/proc/apply_fingerprints_to_item(var/mob/living/carbon/human/holder, var/obj/item/item) item.add_fingerprint(holder,1) if(item.contents.len) for(var/obj/item/sub_item in item.contents) apply_fingerprints_to_item(holder, sub_item) -/datum/job/proc/is_position_available() +/datum/role/job/proc/is_position_available() return (current_positions < total_positions) || (total_positions == -1) -/datum/job/proc/has_alt_title(var/mob/H, var/supplied_title, var/desired_title) +/datum/role/job/proc/has_alt_title(var/mob/H, var/supplied_title, var/desired_title) return (supplied_title == desired_title) || (H.mind && H.mind.role_alt_title == desired_title) -/datum/job/proc/get_description_blurb(var/alt_title) +/datum/role/job/proc/get_description_blurb(var/alt_title) var/list/message = list() message |= desc if(alt_title && alt_titles) var/typepath = alt_titles[alt_title] if(typepath) - var/datum/alt_title/A = new typepath() + var/datum/prototype/alt_title/A = new typepath() if(A.title_blurb) message |= A.title_blurb return message -/datum/job/proc/get_job_icon() +/datum/role/job/proc/get_job_icon() if(!SSjob.job_icons[title]) var/mob/living/carbon/human/dummy/mannequin/mannequin = get_mannequin("#job_icon") dress_mannequin(mannequin) @@ -327,17 +426,17 @@ return SSjob.job_icons[title] -/datum/job/proc/dress_mannequin(mob/living/carbon/human/dummy/mannequin/mannequin) +/datum/role/job/proc/dress_mannequin(mob/living/carbon/human/dummy/mannequin/mannequin) mannequin.delete_inventory(TRUE) equip_preview(mannequin) if(mannequin.back) qdel(mannequin.back) /// Check client-specific availability rules. -/datum/job/proc/player_has_enough_pto(client/C) +/datum/role/job/proc/player_has_enough_pto(client/C) return timeoff_factor >= 0 || (C && LAZYACCESS(C.department_hours, pto_type) > 0) -/datum/job/proc/equip_backpack(mob/living/carbon/human/H) +/datum/role/job/proc/equip_backpack(mob/living/carbon/human/H) switch(H.backbag) if(2) H.equip_to_slot_or_del(new /obj/item/storage/backpack(H), SLOT_ID_BACK) diff --git a/code/modules/jobs/job_types/station.dm b/code/modules/jobs/job_types/station.dm index 16261213156..987b9ce6922 100644 --- a/code/modules/jobs/job_types/station.dm +++ b/code/modules/jobs/job_types/station.dm @@ -1,3 +1,3 @@ -/datum/job/station +/datum/role/job/station faction = JOB_FACTION_STATION - abstract_type = /datum/job/station + abstract_type = /datum/role/job/station diff --git a/code/modules/jobs/job_types/station/admin/centcom_officer.dm b/code/modules/jobs/job_types/station/admin/centcom_officer.dm index ac58f180c2b..b545b362293 100644 --- a/code/modules/jobs/job_types/station/admin/centcom_officer.dm +++ b/code/modules/jobs/job_types/station/admin/centcom_officer.dm @@ -1,4 +1,4 @@ -/datum/job/station/centcom_officer //For Business +/datum/role/job/station/centcom_officer //For Business id = JOB_ID_CENTCOM_OFFICER title = "CentCom Officer" economy_payscale = ECONOMY_PAYSCALE_JOB_ADMIN @@ -22,7 +22,7 @@ pto_type = PTO_CIVILIAN -/datum/job/station/centcom_officer/get_access() +/datum/role/job/station/centcom_officer/get_access() return get_all_accesses().Copy() /datum/outfit/job/station/centcom_officer diff --git a/code/modules/jobs/job_types/station/admin/emergency_responder.dm b/code/modules/jobs/job_types/station/admin/emergency_responder.dm index b1a712cbedb..655fc715d65 100644 --- a/code/modules/jobs/job_types/station/admin/emergency_responder.dm +++ b/code/modules/jobs/job_types/station/admin/emergency_responder.dm @@ -1,4 +1,4 @@ -/datum/job/station/emergency_responder //For staff managing/leading ERTs +/datum/role/job/station/emergency_responder //For staff managing/leading ERTs id = JOB_ID_EMERGENCY_RESPONDER title = "Emergency Responder" economy_payscale = ECONOMY_PAYSCALE_JOB_ADMIN @@ -21,7 +21,7 @@ pto_type = PTO_CIVILIAN -/datum/job/station/emergency_responder/get_access() +/datum/role/job/station/emergency_responder/get_access() return get_all_accesses().Copy() /datum/outfit/job/station/emergency_responder diff --git a/code/modules/jobs/job_types/station/civillian/assistant.dm b/code/modules/jobs/job_types/station/civillian/assistant.dm index a51d3b62d09..e324735904c 100644 --- a/code/modules/jobs/job_types/station/civillian/assistant.dm +++ b/code/modules/jobs/job_types/station/civillian/assistant.dm @@ -1,4 +1,4 @@ -/datum/job/station/assistant +/datum/role/job/station/assistant id = JOB_ID_ASSISTANT title = USELESS_JOB flag = ASSISTANT @@ -9,39 +9,39 @@ spawn_positions = -1 supervisors = "nobody! You don't work here" selection_color = "#515151" - access = list() //See /datum/job/station/assistant/get_access() - minimal_access = list() //See /datum/job/station/assistant/get_access() + access = list() //See /datum/role/job/station/assistant/get_access() + minimal_access = list() //See /datum/role/job/station/assistant/get_access() timeoff_factor = 0 outfit_type = /datum/outfit/job/station/assistant alt_titles = list( - "Visitor" = /datum/alt_title/visitor, - "Server" = /datum/alt_title/server, - "Morale Officer" = /datum/alt_title/morale_officer, - "Assistant" = /datum/alt_title/assistant + "Visitor" = /datum/prototype/alt_title/visitor, + "Server" = /datum/prototype/alt_title/server, + "Morale Officer" = /datum/prototype/alt_title/morale_officer, + "Assistant" = /datum/prototype/alt_title/assistant ) -/datum/job/station/assistant/get_access() +/datum/role/job/station/assistant/get_access() if(config_legacy.assistant_maint) return list(access_maint_tunnels) else return list() -/datum/job/station/assistant/get_access() +/datum/role/job/station/assistant/get_access() return list() -/datum/alt_title/visitor +/datum/prototype/alt_title/visitor title = "Visitor" title_outfit = /datum/outfit/job/station/assistant/visitor -/datum/alt_title/server +/datum/prototype/alt_title/server title = "Server" title_outfit = /datum/outfit/job/station/assistant/server -/datum/alt_title/morale_officer +/datum/prototype/alt_title/morale_officer title = "Morale Officer" -/datum/alt_title/assistant +/datum/prototype/alt_title/assistant title = "Assistant" title_outfit = /datum/outfit/job/station/assistant diff --git a/code/modules/jobs/job_types/station/civillian/chaplain.dm b/code/modules/jobs/job_types/station/civillian/chaplain.dm index e4efd1743f7..fab61cd2405 100644 --- a/code/modules/jobs/job_types/station/civillian/chaplain.dm +++ b/code/modules/jobs/job_types/station/civillian/chaplain.dm @@ -1,4 +1,4 @@ -/datum/job/station/chaplain +/datum/role/job/station/chaplain id = JOB_ID_CHAPLAIN title = "Chaplain" flag = CHAPLAIN @@ -15,23 +15,23 @@ outfit_type = /datum/outfit/job/station/chaplain desc = "The Chaplain ministers to the spiritual needs of the crew." alt_titles = list( - "Counselor" = /datum/alt_title/counselor, - "Religious Affairs Advisor" = /datum/alt_title/chaplain/advisor + "Counselor" = /datum/prototype/alt_title/counselor, + "Religious Affairs Advisor" = /datum/prototype/alt_title/chaplain/advisor ) // Chaplain Alt Titles -/datum/alt_title/counselor +/datum/prototype/alt_title/counselor title = "Counselor" title_blurb = "The Counselor attends to the emotional needs of the crew, without a specific medicinal or spiritual focus." -/datum/alt_title/chaplain/advisor +/datum/prototype/alt_title/chaplain/advisor title = "Religious Affairs Advisor" -/datum/job/station/chaplain/equip(mob/living/carbon/human/H, src) +/datum/role/job/station/chaplain/equip(mob/living/carbon/human/H, src) . = ..() if(H.mind) H.mind.isholy = TRUE -/datum/job/station/chaplain/equip(var/mob/living/carbon/human/H, var/alt_title, var/ask_questions = TRUE) +/datum/role/job/station/chaplain/equip(var/mob/living/carbon/human/H, var/alt_title, var/ask_questions = TRUE) . = ..() if(!.) return diff --git a/code/modules/jobs/job_types/station/civillian/clown.dm b/code/modules/jobs/job_types/station/civillian/clown.dm index 5c493471aba..a6c552478e0 100644 --- a/code/modules/jobs/job_types/station/civillian/clown.dm +++ b/code/modules/jobs/job_types/station/civillian/clown.dm @@ -1,4 +1,4 @@ -/datum/job/station/clown +/datum/role/job/station/clown id = JOB_ID_CLOWN title = "Clown" flag = CLOWN @@ -14,15 +14,15 @@ whitelist_only = 1 outfit_type = /datum/outfit/job/station/clown pto_type = PTO_CIVILIAN - alt_titles = list("Jester" = /datum/alt_title/clown/jester, "Fool" = /datum/alt_title/clown/fool) + alt_titles = list("Jester" = /datum/prototype/alt_title/clown/jester, "Fool" = /datum/prototype/alt_title/clown/fool) -/datum/alt_title/clown/jester +/datum/prototype/alt_title/clown/jester title = "Jester" -/datum/alt_title/clown/fool +/datum/prototype/alt_title/clown/fool title = "Fool" -/datum/job/station/clown/get_access() +/datum/role/job/station/clown/get_access() if(config_legacy.assistant_maint) return list(access_maint_tunnels, access_entertainment, access_clown, access_tomfoolery) else diff --git a/code/modules/jobs/job_types/station/civillian/entertainer.dm b/code/modules/jobs/job_types/station/civillian/entertainer.dm index 0ac739ec305..d8a4bb27187 100644 --- a/code/modules/jobs/job_types/station/civillian/entertainer.dm +++ b/code/modules/jobs/job_types/station/civillian/entertainer.dm @@ -1,4 +1,4 @@ -/datum/job/station/entertainer +/datum/role/job/station/entertainer id = JOB_ID_ENTERTAINER title = "Entertainer" flag = ENTERTAINER @@ -15,50 +15,50 @@ outfit_type = /datum/outfit/job/station/assistant desc = "An entertainer does just that, entertains! Put on plays, play music, sing songs, tell stories, or read your favorite fanfic." alt_titles = list( - "Performer" = /datum/alt_title/entertainer/performer, - "Musician" = /datum/alt_title/entertainer/musician, - "Stagehand" = /datum/alt_title/entertainer/stagehand, - "Actor" = /datum/alt_title/entertainer/actor, - "Dancer" = /datum/alt_title/entertainer/dancer, - "Singer" = /datum/alt_title/entertainer/singer, - "Magician" = /datum/alt_title/entertainer/magician, - "Comedian" = /datum/alt_title/entertainer/comedian, - "Tragedian" = /datum/alt_title/entertainer/tragedian + "Performer" = /datum/prototype/alt_title/entertainer/performer, + "Musician" = /datum/prototype/alt_title/entertainer/musician, + "Stagehand" = /datum/prototype/alt_title/entertainer/stagehand, + "Actor" = /datum/prototype/alt_title/entertainer/actor, + "Dancer" = /datum/prototype/alt_title/entertainer/dancer, + "Singer" = /datum/prototype/alt_title/entertainer/singer, + "Magician" = /datum/prototype/alt_title/entertainer/magician, + "Comedian" = /datum/prototype/alt_title/entertainer/comedian, + "Tragedian" = /datum/prototype/alt_title/entertainer/tragedian ) // Entertainer Alt Titles -/datum/alt_title/entertainer/actor +/datum/prototype/alt_title/entertainer/actor title = "Actor" title_blurb = "An Actor is someone who acts out a role! Whatever sort of character it is, get into it and impress people with power of comedy and tragedy!" -/datum/alt_title/entertainer/performer +/datum/prototype/alt_title/entertainer/performer title = "Performer" title_blurb = "A Performer is someone who performs! Whatever sort of performance will come to your mind, the world's a stage!" -/datum/alt_title/entertainer/musician +/datum/prototype/alt_title/entertainer/musician title = "Musician" title_blurb = "A Musician is someone who makes music with a wide variety of musical instruments!" -/datum/alt_title/entertainer/stagehand +/datum/prototype/alt_title/entertainer/stagehand title = "Stagehand" title_blurb = "A Stagehand typically performs everything the rest of the entertainers don't. Operate lights, shutters, windows, or narrate through your voicebox!" -/datum/alt_title/entertainer/dancer +/datum/prototype/alt_title/entertainer/dancer title = "Dancer" title_blurb = "A Dancer is someone who impresses people through power of their own body! From waltz to breakdance, as long as crowd as cheering!" -/datum/alt_title/entertainer/singer +/datum/prototype/alt_title/entertainer/singer title = "Singer" title_blurb = "A Singer is someone with gift of melodious voice! Impress people with your vocal range!" -/datum/alt_title/entertainer/magician +/datum/prototype/alt_title/entertainer/magician title = "Magician" title_blurb = "A Magician is someone who awes those around them with impossible! Show off your repertoire of magic tricks, while keeping the secret hidden!" -/datum/alt_title/entertainer/comedian +/datum/prototype/alt_title/entertainer/comedian title = "Comedian" title_blurb = "A Comedian will focus on making people laugh with the power of wit! Telling jokes, stand-up comedy, you are here to make others smile!" -/datum/alt_title/entertainer/tragedian +/datum/prototype/alt_title/entertainer/tragedian title = "Tragedian" title_blurb = "A Tragedian will focus on making people think about life and world around them! Life is a tragedy, and who's better to convey its emotions than you?" diff --git a/code/modules/jobs/job_types/station/civillian/internals_affairs_agent.dm b/code/modules/jobs/job_types/station/civillian/internals_affairs_agent.dm index a7bd677208a..59e6de27150 100644 --- a/code/modules/jobs/job_types/station/civillian/internals_affairs_agent.dm +++ b/code/modules/jobs/job_types/station/civillian/internals_affairs_agent.dm @@ -1,4 +1,4 @@ -/datum/job/station/lawyer +/datum/role/job/station/lawyer id = JOB_ID_LAWYER title = "Internal Affairs Agent" flag = LAWYER @@ -14,16 +14,16 @@ minimal_player_age = 7 outfit_type = /datum/outfit/job/station/internal_affairs_agent - alt_titles = list("Regulatory Affairs Agent" = /datum/alt_title/iaa/regulator) + alt_titles = list("Regulatory Affairs Agent" = /datum/prototype/alt_title/iaa/regulator) desc = "An Internal Affairs Agent makes sure that the crew is following Standard Operating Procedure. They also \ handle complaints against crew members, and can have issues brought to the attention of Central Command, \ assuming their paperwork is in order." -/datum/alt_title/iaa/regulator +/datum/prototype/alt_title/iaa/regulator title = "Regulatory Affairs Agent" /* -/datum/job/station/lawyer/equip(var/mob/living/carbon/human/H) +/datum/role/job/station/lawyer/equip(var/mob/living/carbon/human/H) . = ..() if(.) H.implant_loyalty(H) diff --git a/code/modules/jobs/job_types/station/civillian/librarian.dm b/code/modules/jobs/job_types/station/civillian/librarian.dm index da5fa141704..234d41513ac 100644 --- a/code/modules/jobs/job_types/station/civillian/librarian.dm +++ b/code/modules/jobs/job_types/station/civillian/librarian.dm @@ -1,4 +1,4 @@ -/datum/job/station/librarian +/datum/role/job/station/librarian id = JOB_ID_LIBRARIAN title = "Librarian" flag = LIBRARIAN @@ -16,51 +16,51 @@ outfit_type = /datum/outfit/job/station/librarian desc = "The Librarian curates the book selection in the Library, so the crew might enjoy it." alt_titles = list( - "Journalist" = /datum/alt_title/librarian/journalist, - "Reporter" = /datum/alt_title/librarian/reporter, - "Writer" = /datum/alt_title/librarian/writer, - "Historian" = /datum/alt_title/librarian/historian, - "Archivist" = /datum/alt_title/librarian/archivist, - "Professor" = /datum/alt_title/librarian/professor, - "Academic" = /datum/alt_title/librarian/academic, - "Philosopher" = /datum/alt_title/librarian/philosopher + "Journalist" = /datum/prototype/alt_title/librarian/journalist, + "Reporter" = /datum/prototype/alt_title/librarian/reporter, + "Writer" = /datum/prototype/alt_title/librarian/writer, + "Historian" = /datum/prototype/alt_title/librarian/historian, + "Archivist" = /datum/prototype/alt_title/librarian/archivist, + "Professor" = /datum/prototype/alt_title/librarian/professor, + "Academic" = /datum/prototype/alt_title/librarian/academic, + "Philosopher" = /datum/prototype/alt_title/librarian/philosopher ) -/datum/alt_title/librarian/librarian/reporter +/datum/prototype/alt_title/librarian/librarian/reporter title = "Reporter" title_blurb = "Although NanoTrasen's official Press outlet is managed by Central Command, they often hire freelance journalists for local coverage." title_outfit = /datum/outfit/job/station/librarian/reporter // Librarian Alt Titles -/datum/alt_title/librarian/journalist +/datum/prototype/alt_title/librarian/journalist title = "Journalist" title_blurb = "The Journalist uses the Library as a base of operations, from which they can report the news and goings-on on the station with their camera." -/datum/alt_title/librarian/writer +/datum/prototype/alt_title/librarian/writer title = "Writer" title_blurb = "The Writer uses the Library as a quiet place to write whatever it is they choose to write." -/datum/alt_title/librarian/reporter +/datum/prototype/alt_title/librarian/reporter title = "Reporter" title_blurb = "The Reporter uses the Library as a base of operations, from which they can report the news and goings-on on the station with their camera." -/datum/alt_title/librarian/historian +/datum/prototype/alt_title/librarian/historian title = "Historian" title_blurb = "The Historian uses the Library as a base of operation to record any important events occuring on station." -/datum/alt_title/librarian/archivist +/datum/prototype/alt_title/librarian/archivist title = "Archivist" title_blurb = "The Archivist uses the Library as a base of operation to record any important events occuring on station." -/datum/alt_title/librarian/professor +/datum/prototype/alt_title/librarian/professor title = "Professor" title_blurb = "The Professor uses the Library as a base of operations to share their vast knowledge with the crew." -/datum/alt_title/librarian/academic +/datum/prototype/alt_title/librarian/academic title = "Academic" title_blurb = "The Academic uses the Library as a base of operations to share their vast knowledge with the crew." -/datum/alt_title/librarian/philosopher +/datum/prototype/alt_title/librarian/philosopher title = "Philosopher" title_blurb = "The Philosopher uses the Library as a base of operation to ruminate on nature of life and other great questions, and share their opinions with the crew." diff --git a/code/modules/jobs/job_types/station/civillian/mime.dm b/code/modules/jobs/job_types/station/civillian/mime.dm index 5fb531489f5..1a92fbae218 100644 --- a/code/modules/jobs/job_types/station/civillian/mime.dm +++ b/code/modules/jobs/job_types/station/civillian/mime.dm @@ -1,4 +1,4 @@ -/datum/job/station/mime +/datum/role/job/station/mime id = JOB_ID_MIME title = "Mime" flag = MIME @@ -11,15 +11,15 @@ access = list(access_entertainment) minimal_access = list(access_entertainment) desc = "A Mime is there to entertain the crew and keep high morale using unbelievable performances and acting skills!" - alt_titles = list("Poseur" = /datum/alt_title/mime/poseur) + alt_titles = list("Poseur" = /datum/prototype/alt_title/mime/poseur) whitelist_only = 1 outfit_type = /datum/outfit/job/station/mime pto_type = PTO_CIVILIAN -/datum/alt_title/mime/poseur +/datum/prototype/alt_title/mime/poseur title = "Poseur" -/datum/job/station/mime/get_access() +/datum/role/job/station/mime/get_access() if(config_legacy.assistant_maint) return list(access_maint_tunnels, access_entertainment, access_tomfoolery, access_mime) else diff --git a/code/modules/jobs/job_types/station/civillian/pilot.dm b/code/modules/jobs/job_types/station/civillian/pilot.dm index 54add9f7f1e..b62a488b189 100644 --- a/code/modules/jobs/job_types/station/civillian/pilot.dm +++ b/code/modules/jobs/job_types/station/civillian/pilot.dm @@ -1,4 +1,4 @@ -/datum/job/station/pilot +/datum/role/job/station/pilot id = JOB_ID_PILOT title = "Pilot" economy_payscale = ECONOMY_PAYSCALE_JOB_HELM @@ -17,15 +17,15 @@ outfit_type = /datum/outfit/job/station/pilot desc = "A Pilot flies the various shuttles in the Virgo-Erigone System." alt_titles = list( - "Co-Pilot" = /datum/alt_title/co_pilot, - "Navigator" = /datum/alt_title/navigator + "Co-Pilot" = /datum/prototype/alt_title/co_pilot, + "Navigator" = /datum/prototype/alt_title/navigator ) -/datum/alt_title/co_pilot +/datum/prototype/alt_title/co_pilot title = "Co-Pilot" title_blurb = "A Co-Pilot is there primarily to assist main pilot as well as learn from them" -/datum/alt_title/navigator +/datum/prototype/alt_title/navigator title = "Navigator" /datum/outfit/job/station/pilot diff --git a/code/modules/jobs/job_types/station/command/captain.dm b/code/modules/jobs/job_types/station/command/captain.dm index c6c1499095f..6b0dff7a601 100644 --- a/code/modules/jobs/job_types/station/command/captain.dm +++ b/code/modules/jobs/job_types/station/command/captain.dm @@ -1,6 +1,6 @@ var/datum/legacy_announcement/minor/captain_announcement = new(do_newscast = 1) -/datum/job/station/captain +/datum/role/job/station/captain id = JOB_ID_CAPTAIN title = "Facility Director" economy_payscale = ECONOMY_PAYSCALE_JOB_CAPTAIN @@ -29,26 +29,26 @@ var/datum/legacy_announcement/minor/captain_announcement = new(do_newscast = 1) they do not understand everything, and are expected to delegate tasks to the appropriate crew member. The Facility Director is expected to \ have an understanding of Standard Operating Procedure, and is subject to it, and legal action, in the same way as every other crew member." alt_titles = list( - "Overseer"= /datum/alt_title/overseer, - "Site Manager" = /datum/alt_title/captain/site, - "Director of Operations" = /datum/alt_title/captain/director, - "Captain" = /datum/alt_title/captain/captain + "Overseer"= /datum/prototype/alt_title/overseer, + "Site Manager" = /datum/prototype/alt_title/captain/site, + "Director of Operations" = /datum/prototype/alt_title/captain/director, + "Captain" = /datum/prototype/alt_title/captain/captain ) -/datum/job/station/captain/get_access() +/datum/role/job/station/captain/get_access() return get_all_station_access().Copy() -/datum/alt_title/overseer +/datum/prototype/alt_title/overseer title = "Overseer" -/datum/alt_title/captain/site +/datum/prototype/alt_title/captain/site title = "Site Manager" -/datum/alt_title/captain/director +/datum/prototype/alt_title/captain/director title = "Director of Operations" -/datum/alt_title/captain/captain +/datum/prototype/alt_title/captain/captain title = "Captain" /datum/outfit/job/station/captain diff --git a/code/modules/jobs/job_types/station/command/command_secretary.dm b/code/modules/jobs/job_types/station/command/command_secretary.dm index 10a14fa78c2..f0aa46cbd81 100644 --- a/code/modules/jobs/job_types/station/command/command_secretary.dm +++ b/code/modules/jobs/job_types/station/command/command_secretary.dm @@ -1,4 +1,4 @@ -/datum/job/station/command_secretary +/datum/role/job/station/command_secretary id = JOB_ID_COMMAND_SECRETARY title = "Command Secretary" economy_payscale = ECONOMY_PAYSCALE_JOB_HELM @@ -22,30 +22,30 @@ They are not Heads of Staff, and have no real authority." alt_titles = list( - "Command Liaison" = /datum/alt_title/command_liaison, - "Bridge Secretary" = /datum/alt_title/bridge_secretary, - "Command Assistant" = /datum/alt_title/command_assistant, - "Command Intern" = /datum/alt_title/command_intern, - "Helmsman" = /datum/alt_title/commsec/helmsman, - "Bridge Officer" = /datum/alt_title/commsec/officer + "Command Liaison" = /datum/prototype/alt_title/command_liaison, + "Bridge Secretary" = /datum/prototype/alt_title/bridge_secretary, + "Command Assistant" = /datum/prototype/alt_title/command_assistant, + "Command Intern" = /datum/prototype/alt_title/command_intern, + "Helmsman" = /datum/prototype/alt_title/commsec/helmsman, + "Bridge Officer" = /datum/prototype/alt_title/commsec/officer ) -/datum/alt_title/command_liaison +/datum/prototype/alt_title/command_liaison title = "Command Liaison" -/datum/alt_title/bridge_secretary +/datum/prototype/alt_title/bridge_secretary title = "Bridge Secretary" -/datum/alt_title/command_assistant +/datum/prototype/alt_title/command_assistant title = "Command Assistant" -/datum/alt_title/command_intern +/datum/prototype/alt_title/command_intern title = "Command Intern" -/datum/alt_title/commsec/helmsman +/datum/prototype/alt_title/commsec/helmsman title = "Helmsman" -/datum/alt_title/commsec/officer +/datum/prototype/alt_title/commsec/officer title = "Bridge Officer" title_outfit = /datum/outfit/job/station/command_secretary/bridge_officer diff --git a/code/modules/jobs/job_types/station/command/head_of_personnel.dm b/code/modules/jobs/job_types/station/command/head_of_personnel.dm index b2336c113a8..b71a3742041 100644 --- a/code/modules/jobs/job_types/station/command/head_of_personnel.dm +++ b/code/modules/jobs/job_types/station/command/head_of_personnel.dm @@ -1,4 +1,4 @@ -/datum/job/station/head_of_personnel +/datum/role/job/station/head_of_personnel id = JOB_ID_HEAD_OF_PERSONNEL title = "Head of Personnel" flag = HOP @@ -25,8 +25,8 @@ manage the Supply department, through the Quartermaster. In addition, the Head of Personnel oversees the personal accounts \ of the crew, including their money and access. If necessary, the Head of Personnel is first in line to assume Acting Command." alt_titles = list( - "Crew Resources Officer" = /datum/alt_title/cro, - "Deputy Director" = /datum/alt_title/hop/deputy + "Crew Resources Officer" = /datum/prototype/alt_title/cro, + "Deputy Director" = /datum/prototype/alt_title/hop/deputy ) access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers, @@ -42,10 +42,10 @@ access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station, access_hop, access_RC_announce, access_keycard_auth, access_gateway) -/datum/alt_title/cro +/datum/prototype/alt_title/cro title = "Crew Resources Officer" -/datum/alt_title/hop/deputy +/datum/prototype/alt_title/hop/deputy title = "Deputy Director" /datum/outfit/job/station/head_of_personnel diff --git a/code/modules/jobs/job_types/station/engineering/atmospherics_technician.dm b/code/modules/jobs/job_types/station/engineering/atmospherics_technician.dm index a5846a64f51..b901faad8c1 100644 --- a/code/modules/jobs/job_types/station/engineering/atmospherics_technician.dm +++ b/code/modules/jobs/job_types/station/engineering/atmospherics_technician.dm @@ -1,4 +1,4 @@ -/datum/job/station/atmos +/datum/role/job/station/atmos id = JOB_ID_ATMOSPHERIC_TECHNICIAN title = "Atmospheric Technician" flag = ATMOSTECH @@ -21,19 +21,19 @@ understanding of the pipes, vents, and scrubbers that move gasses around the station, and to be familiar with proper firefighting procedure." alt_titles = list( - "Atmospherics Maintainer" = /datum/alt_title/atmos_maint, - "Pipe Network Specialist" = /datum/alt_title/pipe_spec, - "Disposals Technician" = /datum/alt_title/disposals_tech + "Atmospherics Maintainer" = /datum/prototype/alt_title/atmos_maint, + "Pipe Network Specialist" = /datum/prototype/alt_title/pipe_spec, + "Disposals Technician" = /datum/prototype/alt_title/disposals_tech ) // Atmos Tech Alt Titles -/datum/alt_title/atmos_maint +/datum/prototype/alt_title/atmos_maint title = "Atmospherics Maintainer" -/datum/alt_title/pipe_spec +/datum/prototype/alt_title/pipe_spec title = "Pipe Network Specialist" -/datum/alt_title/disposals_tech +/datum/prototype/alt_title/disposals_tech title = "Disposals Technician" title_blurb = "A Disposals Technician is an Atmospheric Technician still and can fulfill all the same duties, although specializes more in disposals delivery system's operations and configurations." diff --git a/code/modules/jobs/job_types/station/engineering/chief_engineer.dm b/code/modules/jobs/job_types/station/engineering/chief_engineer.dm index 0ef2f33ea79..b8f083c500b 100644 --- a/code/modules/jobs/job_types/station/engineering/chief_engineer.dm +++ b/code/modules/jobs/job_types/station/engineering/chief_engineer.dm @@ -1,4 +1,4 @@ -/datum/job/station/chief_engineer +/datum/role/job/station/chief_engineer id = JOB_ID_CHIEF_ENGINEER title = "Chief Engineer" economy_payscale = ECONOMY_PAYSCALE_JOB_COMMAND @@ -29,9 +29,9 @@ access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload) minimal_player_age = 7 alt_titles = list( - "Head Engineer" = /datum/alt_title/head_engineer, - "Maintenance Manager" = /datum/alt_title/maintenance_manager, - "Engineering Director" = /datum/alt_title/engineering_director + "Head Engineer" = /datum/prototype/alt_title/head_engineer, + "Maintenance Manager" = /datum/prototype/alt_title/maintenance_manager, + "Engineering Director" = /datum/prototype/alt_title/engineering_director ) outfit_type = /datum/outfit/job/station/chief_engineer @@ -39,13 +39,13 @@ of manpower as much as they handle hands-on operations and repairs. They are also expected to keep the rest of the station informed of \ any structural threats to the station that may be hazardous to health or disruptive to work." -/datum/alt_title/engineering_director +/datum/prototype/alt_title/engineering_director title = "Engineering Director" -/datum/alt_title/head_engineer +/datum/prototype/alt_title/head_engineer title = "Head Engineer" -/datum/alt_title/maintenance_manager +/datum/prototype/alt_title/maintenance_manager title = "Maintenance Manager" /datum/outfit/job/station/chief_engineer diff --git a/code/modules/jobs/job_types/station/engineering/senior_engineer.dm b/code/modules/jobs/job_types/station/engineering/senior_engineer.dm index 45a6b020d2a..ff93b5a69c5 100644 --- a/code/modules/jobs/job_types/station/engineering/senior_engineer.dm +++ b/code/modules/jobs/job_types/station/engineering/senior_engineer.dm @@ -1,4 +1,4 @@ -/datum/job/station/senior_engineer +/datum/role/job/station/senior_engineer title = "Senior Engineer" id = JOB_ID_SENIOR_ENGINEER economy_payscale = ECONOMY_PAYSCALE_JOB_SENIOR diff --git a/code/modules/jobs/job_types/station/engineering/station_engineer.dm b/code/modules/jobs/job_types/station/engineering/station_engineer.dm index ada0676d957..56a03132879 100644 --- a/code/modules/jobs/job_types/station/engineering/station_engineer.dm +++ b/code/modules/jobs/job_types/station/engineering/station_engineer.dm @@ -1,4 +1,4 @@ -/datum/job/station/engineer +/datum/role/job/station/engineer id = JOB_ID_STATION_ENGINEER title = "Station Engineer" flag = ENGINEER @@ -15,11 +15,11 @@ minimal_access = list(access_eva, access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_external_airlocks, access_construction) alt_titles = list( - "Maintenance Technician" = /datum/alt_title/maint_tech, - "Engine Technician" = /datum/alt_title/engine_tech, - "Electrician" = /datum/alt_title/electrician, - "Apprentice Engineer" = /datum/alt_title/apprentice_engineer, - "Construction Engineer" = /datum/alt_title/construction_engi + "Maintenance Technician" = /datum/prototype/alt_title/maint_tech, + "Engine Technician" = /datum/prototype/alt_title/engine_tech, + "Electrician" = /datum/prototype/alt_title/electrician, + "Apprentice Engineer" = /datum/prototype/alt_title/apprentice_engineer, + "Construction Engineer" = /datum/prototype/alt_title/construction_engi ) minimal_player_age = 3 @@ -27,25 +27,25 @@ outfit_type = /datum/outfit/job/station/station_engineer desc = "An Engineer keeps the station running. They repair damages, keep the atmosphere stable, and ensure that power is being \ generated and distributed. On quiet shifts, they may be called upon to make cosmetic alterations to the station." -/datum/alt_title/maint_tech +/datum/prototype/alt_title/maint_tech title = "Maintenance Technician" title_blurb = "A Maintenance Technician is generally a junior Engineer, and can be expected to run the mildly unpleasant or boring tasks that other \ Engineers don't care to do." -/datum/alt_title/engine_tech +/datum/prototype/alt_title/engine_tech title = "Engine Technician" title_blurb = "An Engine Technician tends to the engine, most commonly a Supermatter crystal. They are expected to be able to keep it stable, and \ possibly even run it beyond normal tolerances." -/datum/alt_title/electrician +/datum/prototype/alt_title/electrician title = "Electrician" title_blurb = "An Electrician's primary duty is making sure power is properly distributed thoughout the station, utilizing solars, substations, and other \ methods to ensure every department has power in an emergency." -/datum/alt_title/apprentice_engineer +/datum/prototype/alt_title/apprentice_engineer title = "Apprentice Engineer" -/datum/alt_title/construction_engi +/datum/prototype/alt_title/construction_engi title = "Construction Engineer" title_blurb = "A Construction Engineer fulfills similar duties to other engineers, but usually occupies spare time with construction of extra facilities in dedicated areas or \ as additions to station layout." diff --git a/code/modules/jobs/job_types/station/exploration/explorer.dm b/code/modules/jobs/job_types/station/exploration/explorer.dm index e8472166b25..de0972550a6 100644 --- a/code/modules/jobs/job_types/station/exploration/explorer.dm +++ b/code/modules/jobs/job_types/station/exploration/explorer.dm @@ -1,4 +1,4 @@ -/datum/job/station/explorer +/datum/role/job/station/explorer id = JOB_ID_EXPLORER title = "Explorer" economy_payscale = ECONOMY_PAYSCALE_JOB_DANGER @@ -16,26 +16,26 @@ outfit_type = /datum/outfit/job/station/explorer desc = "An Explorer searches for interesting things, and returns them to the station." alt_titles = list( - "Surveyor" = /datum/alt_title/surveyor, - "Offsite Scout" = /datum/alt_title/offsite_scout, - "Field Scout" = /datum/alt_title/explorer/field_scout, - "Pioneer" = /datum/alt_title/explorer/pioneer, - "Jr. Explorer" = /datum/alt_title/explorer/junior + "Surveyor" = /datum/prototype/alt_title/surveyor, + "Offsite Scout" = /datum/prototype/alt_title/offsite_scout, + "Field Scout" = /datum/prototype/alt_title/explorer/field_scout, + "Pioneer" = /datum/prototype/alt_title/explorer/pioneer, + "Jr. Explorer" = /datum/prototype/alt_title/explorer/junior ) -/datum/alt_title/surveyor +/datum/prototype/alt_title/surveyor title = "Surveyor" -/datum/alt_title/offsite_scout +/datum/prototype/alt_title/offsite_scout title = "Offsite Scout" -/datum/alt_title/explorer/field_scout +/datum/prototype/alt_title/explorer/field_scout title = "Field Scout" -/datum/alt_title/explorer/pioneer +/datum/prototype/alt_title/explorer/pioneer title = "Pioneer" -/datum/alt_title/explorer/junior +/datum/prototype/alt_title/explorer/junior title = "Jr. Explorer" /datum/outfit/job/station/explorer diff --git a/code/modules/jobs/job_types/station/exploration/field_medic.dm b/code/modules/jobs/job_types/station/exploration/field_medic.dm index 41871cb9b58..a9de09e2bb3 100644 --- a/code/modules/jobs/job_types/station/exploration/field_medic.dm +++ b/code/modules/jobs/job_types/station/exploration/field_medic.dm @@ -1,4 +1,4 @@ -/datum/job/station/field_medic +/datum/role/job/station/field_medic id = JOB_ID_FIELD_MEDIC title = "Field Medic" economy_payscale = ECONOMY_PAYSCALE_JOB_DANGER @@ -17,14 +17,14 @@ outfit_type = /datum/outfit/job/station/sar desc = "A Field medic works as the field doctor of expedition teams." alt_titles = list( - "Expedition Medic" = /datum/alt_title/expedition_medic, - "Search and Rescue" = /datum/alt_title/field_medic/sar + "Expedition Medic" = /datum/prototype/alt_title/expedition_medic, + "Search and Rescue" = /datum/prototype/alt_title/field_medic/sar ) -/datum/alt_title/expedition_medic +/datum/prototype/alt_title/expedition_medic title = "Expedition Medic" -/datum/alt_title/field_medic/sar +/datum/prototype/alt_title/field_medic/sar title = "Search and Rescue" /datum/outfit/job/station/sar diff --git a/code/modules/jobs/job_types/station/exploration/pathfinder.dm b/code/modules/jobs/job_types/station/exploration/pathfinder.dm index c16ae4499aa..d8fc06998b7 100644 --- a/code/modules/jobs/job_types/station/exploration/pathfinder.dm +++ b/code/modules/jobs/job_types/station/exploration/pathfinder.dm @@ -1,4 +1,4 @@ -/datum/job/station/pathfinder +/datum/role/job/station/pathfinder id = JOB_ID_PATHFINDER title = "Pathfinder" economy_payscale = ECONOMY_PAYSCALE_JOB_SENIOR @@ -20,18 +20,18 @@ outfit_type = /datum/outfit/job/station/pathfinder desc = "The Pathfinder's job is to lead and manage expeditions, and is the primary authority on all off-station expeditions." alt_titles = list( - "Expedition Lead" = /datum/alt_title/expedition_lead, - "Exploration Manager" = /datum/alt_title/exploration_manager, - "Lead Pioneer" = /datum/alt_title/pathfinder/pioneer + "Expedition Lead" = /datum/prototype/alt_title/expedition_lead, + "Exploration Manager" = /datum/prototype/alt_title/exploration_manager, + "Lead Pioneer" = /datum/prototype/alt_title/pathfinder/pioneer ) -/datum/alt_title/expedition_lead +/datum/prototype/alt_title/expedition_lead title = "Expedition Lead" -/datum/alt_title/exploration_manager +/datum/prototype/alt_title/exploration_manager title = "Exploration Manager" -/datum/alt_title/pathfinder/pioneer +/datum/prototype/alt_title/pathfinder/pioneer title = "Lead Pioneer" /datum/outfit/job/station/pathfinder diff --git a/code/modules/jobs/job_types/station/medical/chemist.dm b/code/modules/jobs/job_types/station/medical/chemist.dm index 44f7219245c..56b1267073d 100644 --- a/code/modules/jobs/job_types/station/medical/chemist.dm +++ b/code/modules/jobs/job_types/station/medical/chemist.dm @@ -1,4 +1,4 @@ -/datum/job/station/chemist +/datum/role/job/station/chemist id = JOB_ID_CHEMIST title = "Chemist" flag = CHEMIST @@ -18,14 +18,14 @@ desc = "A Chemist produces and maintains a stock of basic to advanced chemicals for medical and occasionally research use. \ They are likely to know the use and dangers of many lab-produced chemicals." alt_titles = list( - "Pharmacist" = /datum/alt_title/pharmacist, - "Pharmacologist" = /datum/alt_title/pharmacologist + "Pharmacist" = /datum/prototype/alt_title/pharmacist, + "Pharmacologist" = /datum/prototype/alt_title/pharmacologist ) -/datum/alt_title/pharmacist +/datum/prototype/alt_title/pharmacist title = "Pharmacist" title_blurb = "A Pharmacist focuses on the chemical needs of the Medical Department, and often offers to fill crew prescriptions at their discretion." -/datum/alt_title/pharmacologist +/datum/prototype/alt_title/pharmacologist title = "Pharmacologist" title_blurb = "A Pharmacologist focuses on the chemical needs of the Medical Department, primarily specializing in producing more advanced forms of medicine." diff --git a/code/modules/jobs/job_types/station/medical/chief_medical_officer.dm b/code/modules/jobs/job_types/station/medical/chief_medical_officer.dm index a0c4f6c0e9d..13a1352d743 100644 --- a/code/modules/jobs/job_types/station/medical/chief_medical_officer.dm +++ b/code/modules/jobs/job_types/station/medical/chief_medical_officer.dm @@ -1,4 +1,4 @@ -/datum/job/station/chief_medical_officer +/datum/role/job/station/chief_medical_officer id = JOB_ID_CHIEF_MEDICAL_OFFICER title = "Chief Medical Officer" economy_payscale = ECONOMY_PAYSCALE_JOB_COMMAND @@ -32,18 +32,18 @@ transported to Medical for treatment. They are expected to keep the crew informed about threats to their health and safety, and \ about the importance of Suit Sensors." alt_titles = list ( - "Chief Physician" = /datum/alt_title/cmo/physician, - "Director of Medicine" = /datum/alt_title/cmo/director, - "Chief Surgeon" = /datum/alt_title/cmo/surgeon + "Chief Physician" = /datum/prototype/alt_title/cmo/physician, + "Director of Medicine" = /datum/prototype/alt_title/cmo/director, + "Chief Surgeon" = /datum/prototype/alt_title/cmo/surgeon ) -/datum/alt_title/cmo/physician +/datum/prototype/alt_title/cmo/physician title = "Chief Physician" -/datum/alt_title/cmo/director +/datum/prototype/alt_title/cmo/director title = "Director of Medicine" -/datum/alt_title/cmo/surgeon +/datum/prototype/alt_title/cmo/surgeon title = "Chief Surgeon" /datum/outfit/job/station/chief_medical_officer diff --git a/code/modules/jobs/job_types/station/medical/geneticist.dm b/code/modules/jobs/job_types/station/medical/geneticist.dm index 0e29a9b5c5f..188d9dc0a86 100644 --- a/code/modules/jobs/job_types/station/medical/geneticist.dm +++ b/code/modules/jobs/job_types/station/medical/geneticist.dm @@ -3,7 +3,7 @@ ////////////////////////////////// // Geneticist ////////////////////////////////// -/datum/job/station/geneticist +/datum/role/job/station/geneticist id = "geneticist" title = "Geneticist" flag = GENETICIST diff --git a/code/modules/jobs/job_types/station/medical/head_nurse.dm b/code/modules/jobs/job_types/station/medical/head_nurse.dm index ba54a530760..d8597fa4854 100644 --- a/code/modules/jobs/job_types/station/medical/head_nurse.dm +++ b/code/modules/jobs/job_types/station/medical/head_nurse.dm @@ -1,4 +1,4 @@ -/datum/job/station/head_nurse +/datum/role/job/station/head_nurse title = "Head Nurse" id = JOB_ID_HEAD_NURSE flag = HEAD_NURSE @@ -23,18 +23,18 @@ ideal_character_age = 45 alt_titles = list ( - "Medical Specialist" = /datum/alt_title/medical_specialist, - "Consultant Physician" = /datum/alt_title/consultant_physician, + "Medical Specialist" = /datum/prototype/alt_title/medical_specialist, + "Consultant Physician" = /datum/prototype/alt_title/consultant_physician, ) -/datum/alt_title/medical_specialist +/datum/prototype/alt_title/medical_specialist title = "Medical Specialist" title_blurb = "A Medical Specialist is a senior medical professional with extensive knowledge within a particular field of medicine which \ is expected to perform the standard duties of a medical doctor, as well as offer training, guidance and oversight to both resident \ and attending physicians in all matters, especially when presented with difficult situations within their field of expertise." title_outfit = /datum/outfit/job/station/medical_doctor -/datum/alt_title/consultant_physician +/datum/prototype/alt_title/consultant_physician title = "Consultant Physician" title_blurb = "A Consultant Physician is a senior medical professional with extensive training in general medical practice which is expected to perform the \ standard duties of a medical doctor, as well as offer training, guidance and oversight to resident and attending physicians, especially when presented with difficult \ diff --git a/code/modules/jobs/job_types/station/medical/medical_doctor.dm b/code/modules/jobs/job_types/station/medical/medical_doctor.dm index 6c01af6fd3a..e86407740e1 100644 --- a/code/modules/jobs/job_types/station/medical/medical_doctor.dm +++ b/code/modules/jobs/job_types/station/medical/medical_doctor.dm @@ -1,4 +1,4 @@ -/datum/job/station/doctor +/datum/role/job/station/doctor id = JOB_ID_MEDICAL_DOCTOR title = "Medical Doctor" flag = DOCTOR @@ -17,52 +17,52 @@ familiar with basic first aid, and a number of accompanying medications, and can generally save, if not cure, a majority of the \ patients they encounter." alt_titles = list( - "Surgeon" = /datum/alt_title/surgeon, - "Emergency Physician" = /datum/alt_title/emergency_physician, - "Nurse" = /datum/alt_title/nurse, - "Virologist" = /datum/alt_title/virologist, - "Medical Resident" = /datum/alt_title/doctor/resident, - "Medical Intern" = /datum/alt_title/doctor/intern, - "Orderly" = /datum/alt_title/orderly + "Surgeon" = /datum/prototype/alt_title/surgeon, + "Emergency Physician" = /datum/prototype/alt_title/emergency_physician, + "Nurse" = /datum/prototype/alt_title/nurse, + "Virologist" = /datum/prototype/alt_title/virologist, + "Medical Resident" = /datum/prototype/alt_title/doctor/resident, + "Medical Intern" = /datum/prototype/alt_title/doctor/intern, + "Orderly" = /datum/prototype/alt_title/orderly ) // Medical Doctor Alt Titles -/datum/alt_title/surgeon +/datum/prototype/alt_title/surgeon title = "Surgeon" title_blurb = "A Surgeon specializes in providing surgical aid to injured patients, up to and including amputation and limb reattachement. They are expected \ to know the ins and outs of anesthesia and surgery." title_outfit = /datum/outfit/job/station/medical_doctor/surgeon -/datum/alt_title/orderly +/datum/prototype/alt_title/orderly title = "Orderly" title_blurb = "An Orderly acts as Medbay's general helping hand, assisting any doctor that might need some form of help, as well as handling manual \ and dirty labor around the department." title_outfit = /datum/outfit/job/station/medical_doctor/nurse -/datum/alt_title/emergency_physician +/datum/prototype/alt_title/emergency_physician title = "Emergency Physician" title_blurb = "An Emergency Physician is a Medical professional trained for stabilizing and treating severely injured and/or dying patients. \ They are generally the first response for any such individual brought to the Medbay, and can sometimes be expected to help their patients \ make a full recovery." title_outfit = /datum/outfit/job/station/medical_doctor/emergency_physician -/datum/alt_title/nurse +/datum/prototype/alt_title/nurse title = "Nurse" title_blurb = "A Nurse acts as a general purpose Doctor's Aide, providing basic care to non-critical patients, and stabilizing critical patients during \ busy periods. They frequently watch the suit sensors console, to help manage the time of other Doctors. In rare occasions, a Nurse can be \ called upon to revive deceased crew members." title_outfit = /datum/outfit/job/station/medical_doctor/nurse -/datum/alt_title/virologist +/datum/prototype/alt_title/virologist title = "Virologist" title_blurb = "A Virologist cures active diseases in the crew, and prepares antibodies for possible infections. They also have the skills \ to produce the various types of virus foods or mutagens." title_outfit = /datum/outfit/job/station/medical_doctor/virologist -/datum/alt_title/doctor/resident +/datum/prototype/alt_title/doctor/resident title = "Medical Resident" -/datum/alt_title/doctor/intern +/datum/prototype/alt_title/doctor/intern title = "Medical Intern" /datum/outfit/job/station/medical_doctor diff --git a/code/modules/jobs/job_types/station/medical/paramedic.dm b/code/modules/jobs/job_types/station/medical/paramedic.dm index 70e17d242ff..6769226bf3b 100644 --- a/code/modules/jobs/job_types/station/medical/paramedic.dm +++ b/code/modules/jobs/job_types/station/medical/paramedic.dm @@ -1,4 +1,4 @@ -/datum/job/station/paramedic +/datum/role/job/station/paramedic id = JOB_ID_PARAMEDIC title = "Paramedic" flag = PARAMEDIC @@ -16,17 +16,17 @@ desc = "A Paramedic is primarily concerned with the recovery of patients who are unable to make it to the Medical Department on their own. \ They may also be called upon to keep patients stable when Medical is busy or understaffed." alt_titles = list( - "Emergency Medical Technician" = /datum/alt_title/emt, - "Medical Responder" = /datum/alt_title/medical_responder + "Emergency Medical Technician" = /datum/prototype/alt_title/emt, + "Medical Responder" = /datum/prototype/alt_title/medical_responder ) -/datum/alt_title/emt +/datum/prototype/alt_title/emt title = "Emergency Medical Technician" title_blurb = "An Emergency Medical Technician is primarily concerned with the recovery of patients who are unable to make it to the Medical Department on their \ own. They are capable of keeping a patient stabilized until they reach the hands of someone with more training." title_outfit = /datum/outfit/job/station/paramedic/emt -/datum/alt_title/medical_responder +/datum/prototype/alt_title/medical_responder title = "Medical Responder" title_blurb = "A Medical Responder is primarily concerned with the recovery of patients who are unable to make it to the Medical Department on their \ own. They are capable of keeping a patient stabilized until they reach the hands of someone with more training." diff --git a/code/modules/jobs/job_types/station/medical/psychiatrist.dm b/code/modules/jobs/job_types/station/medical/psychiatrist.dm index 703d6ee3a9b..b2fe6ee93ac 100644 --- a/code/modules/jobs/job_types/station/medical/psychiatrist.dm +++ b/code/modules/jobs/job_types/station/medical/psychiatrist.dm @@ -1,4 +1,4 @@ -/datum/job/station/psychiatrist +/datum/role/job/station/psychiatrist id = JOB_ID_PSYCHIATRIST title = "Psychiatrist" flag = PSYCHIATRIST @@ -16,27 +16,27 @@ desc = "A Psychiatrist provides mental health services to crew members in need. They may also be called upon to determine whatever \ ails the mentally unwell, frequently under Security supervision. They understand the effects of various psychoactive drugs." alt_titles = list( - "Psychologist" = /datum/alt_title/psychologist, - "Psychoanalyst" = /datum/alt_title/psychologist/psychoanalyst, - "Counselor" = /datum/alt_title/counselor, - "Therapist" = /datum/alt_title/therapist + "Psychologist" = /datum/prototype/alt_title/psychologist, + "Psychoanalyst" = /datum/prototype/alt_title/psychologist/psychoanalyst, + "Counselor" = /datum/prototype/alt_title/counselor, + "Therapist" = /datum/prototype/alt_title/therapist ) -/datum/alt_title/psychologist +/datum/prototype/alt_title/psychologist title = "Psychologist" title_blurb = "A Psychologist provides mental health services to crew members in need, focusing more on therapy than medication. They may also be \ called upon to determine whatever ails the mentally unwell, frequently under Security supervision." title_outfit = /datum/outfit/job/station/psychiatrist/psychologist -/datum/alt_title/psychologist/psychoanalyst +/datum/prototype/alt_title/psychologist/psychoanalyst title = "Psychoanalyst" title_blurb = "A Psychoanalyst provides mental health services to crew members in need, focusing more on therapy than medication. They may also be \ called upon to determine whatever ails the mentally unwell, frequently under Security supervision." -/datum/alt_title/counselor +/datum/prototype/alt_title/counselor title = "Counselor" -/datum/alt_title/therapist +/datum/prototype/alt_title/therapist title = "Therapist" /datum/outfit/job/station/psychiatrist diff --git a/code/modules/jobs/job_types/station/offduty/_offduty.dm b/code/modules/jobs/job_types/station/offduty/_offduty.dm index cf49ea9b540..105212f81f3 100644 --- a/code/modules/jobs/job_types/station/offduty/_offduty.dm +++ b/code/modules/jobs/job_types/station/offduty/_offduty.dm @@ -1,5 +1,5 @@ -/datum/job/station/off_duty - abstract_type = /datum/job/station/off_duty +/datum/role/job/station/off_duty + abstract_type = /datum/role/job/station/off_duty join_types = JOB_LATEJOIN timeoff_factor = -1 total_positions = -1 diff --git a/code/modules/jobs/job_types/station/offduty/civillian.dm b/code/modules/jobs/job_types/station/offduty/civillian.dm index 4695bc26ab4..88a68d4ebf9 100644 --- a/code/modules/jobs/job_types/station/offduty/civillian.dm +++ b/code/modules/jobs/job_types/station/offduty/civillian.dm @@ -1,4 +1,4 @@ -/datum/job/station/off_duty/civilian +/datum/role/job/station/off_duty/civilian id = JOB_ID_OFFDUTY_CIVILLIAN title = "Off-duty Worker" selection_color = "#9b633e" diff --git a/code/modules/jobs/job_types/station/offduty/command.dm b/code/modules/jobs/job_types/station/offduty/command.dm index 039bdf164c8..b7c3784e6ca 100644 --- a/code/modules/jobs/job_types/station/offduty/command.dm +++ b/code/modules/jobs/job_types/station/offduty/command.dm @@ -1,4 +1,4 @@ -/datum/job/station/off_duty/command +/datum/role/job/station/off_duty/command id = JOB_ID_OFFDUTY_COMMAND title = "Off-duty Command" timeoff_factor = -1 diff --git a/code/modules/jobs/job_types/station/offduty/engineering.dm b/code/modules/jobs/job_types/station/offduty/engineering.dm index fc652722937..c12f203969b 100644 --- a/code/modules/jobs/job_types/station/offduty/engineering.dm +++ b/code/modules/jobs/job_types/station/offduty/engineering.dm @@ -1,4 +1,4 @@ -/datum/job/station/off_duty/engineering +/datum/role/job/station/off_duty/engineering id = JOB_ID_OFFDUTY_ENGINEER title = "Off-duty Engineer" selection_color = "#5B4D20" diff --git a/code/modules/jobs/job_types/station/offduty/exploration.dm b/code/modules/jobs/job_types/station/offduty/exploration.dm index 782b48af724..a71bb69f8aa 100644 --- a/code/modules/jobs/job_types/station/offduty/exploration.dm +++ b/code/modules/jobs/job_types/station/offduty/exploration.dm @@ -1,4 +1,4 @@ -/datum/job/station/off_duty/exploration +/datum/role/job/station/off_duty/exploration id = JOB_ID_OFFDUTY_EXPLORER title = "Off-duty Explorer" selection_color = "#999440" diff --git a/code/modules/jobs/job_types/station/offduty/medical.dm b/code/modules/jobs/job_types/station/offduty/medical.dm index 9b18a921504..f69e6448f69 100644 --- a/code/modules/jobs/job_types/station/offduty/medical.dm +++ b/code/modules/jobs/job_types/station/offduty/medical.dm @@ -1,4 +1,4 @@ -/datum/job/station/off_duty/medical +/datum/role/job/station/off_duty/medical id = JOB_ID_OFFDUTY_MEDBAY title = "Off-duty Medic" selection_color = "#013D3B" diff --git a/code/modules/jobs/job_types/station/offduty/science.dm b/code/modules/jobs/job_types/station/offduty/science.dm index 0fc149cf28f..59f21275ef9 100644 --- a/code/modules/jobs/job_types/station/offduty/science.dm +++ b/code/modules/jobs/job_types/station/offduty/science.dm @@ -1,4 +1,4 @@ -/datum/job/station/off_duty/science +/datum/role/job/station/off_duty/science id = JOB_ID_OFFDUTY_SCIENCE title = "Off-duty Scientist" selection_color = "#633D63" diff --git a/code/modules/jobs/job_types/station/offduty/security.dm b/code/modules/jobs/job_types/station/offduty/security.dm index a01de547b9f..98c9afa7e48 100644 --- a/code/modules/jobs/job_types/station/offduty/security.dm +++ b/code/modules/jobs/job_types/station/offduty/security.dm @@ -1,4 +1,4 @@ -/datum/job/station/off_duty/security +/datum/role/job/station/off_duty/security id = JOB_ID_OFFDUTY_SECURITY title = "Off-duty Officer" selection_color = "#601C1C" diff --git a/code/modules/jobs/job_types/station/offduty/supply.dm b/code/modules/jobs/job_types/station/offduty/supply.dm index 7e6dcd7b4fa..cff90498cf1 100644 --- a/code/modules/jobs/job_types/station/offduty/supply.dm +++ b/code/modules/jobs/job_types/station/offduty/supply.dm @@ -1,4 +1,4 @@ -/datum/job/station/off_duty/cargo +/datum/role/job/station/off_duty/cargo id = JOB_ID_OFFDUTY_CARGO title = "Off-duty Cargo" selection_color = "#9b633e" diff --git a/code/modules/jobs/job_types/station/science/research_director.dm b/code/modules/jobs/job_types/station/science/research_director.dm index f9d3f840c64..2c9b12f3ef7 100644 --- a/code/modules/jobs/job_types/station/science/research_director.dm +++ b/code/modules/jobs/job_types/station/science/research_director.dm @@ -1,4 +1,4 @@ -/datum/job/station/research_director +/datum/role/job/station/research_director id = JOB_ID_RESEARCH_DIRECTOR title = "Research Director" economy_payscale = ECONOMY_PAYSCALE_JOB_COMMAND @@ -34,18 +34,18 @@ might originate from Research. The Research Director often has at least passing knowledge of most of the Research department, but \ are encouraged to allow their staff to perform their own duties." alt_titles = list( - "Research Supervisor" = /datum/alt_title/research_supervisor, - "Head of Development" = /datum/alt_title/head_of_development, - "Head Scientist" = /datum/alt_title/head_scientist + "Research Supervisor" = /datum/prototype/alt_title/research_supervisor, + "Head of Development" = /datum/prototype/alt_title/head_of_development, + "Head Scientist" = /datum/prototype/alt_title/head_scientist ) -/datum/alt_title/research_supervisor +/datum/prototype/alt_title/research_supervisor title = "Research Supervisor" -/datum/alt_title/head_of_development +/datum/prototype/alt_title/head_of_development title = "Head of Development" -/datum/alt_title/head_scientist +/datum/prototype/alt_title/head_scientist title = "Head Scientist" /datum/outfit/job/station/research_director diff --git a/code/modules/jobs/job_types/station/science/roboticist.dm b/code/modules/jobs/job_types/station/science/roboticist.dm index 17ad1bd1e50..9d1dc5ba6df 100644 --- a/code/modules/jobs/job_types/station/science/roboticist.dm +++ b/code/modules/jobs/job_types/station/science/roboticist.dm @@ -1,4 +1,4 @@ -/datum/job/station/roboticist +/datum/role/job/station/roboticist id = JOB_ID_ROBOTICIST title = "Roboticist" flag = ROBOTICIST @@ -17,22 +17,22 @@ desc = "A Roboticist maintains and repairs the station's synthetics, including crew with prosthetic limbs. \ They can also assist the station by producing simple robots and even pilotable exosuits." alt_titles = list( - "Biomechanical Engineer" = /datum/alt_title/biomech, - "Mechatronic Engineer" = /datum/alt_title/mech_tech, - "Prosthetists" = /datum/alt_title/prosthetists + "Biomechanical Engineer" = /datum/prototype/alt_title/biomech, + "Mechatronic Engineer" = /datum/prototype/alt_title/mech_tech, + "Prosthetists" = /datum/prototype/alt_title/prosthetists ) -/datum/alt_title/biomech +/datum/prototype/alt_title/biomech title = "Biomechanical Engineer" title_blurb = "A Biomechanical Engineer primarily works on prosthetics, and the organic parts attached to them. They may have some \ knowledge of the relatively simple surgical procedures used in making cyborgs and attaching prosthesis." -/datum/alt_title/mech_tech +/datum/prototype/alt_title/mech_tech title = "Mechatronic Engineer" title_blurb = "A Mechatronic Engineer focuses on the construction and maintenance of Exosuits, and should be well versed in their use. \ They may also be called upon to work on synthetics and prosthetics, if needed." -/datum/alt_title/prosthetists +/datum/prototype/alt_title/prosthetists title = "Prosthetists" title_blurb = "Prosthetists design and fabricate medical supportive devices and measure and fit patients for them. These devices \ include artificial limbs (arms, hands, legs, and feet), braces, and other medical or surgical devices." diff --git a/code/modules/jobs/job_types/station/science/scientist.dm b/code/modules/jobs/job_types/station/science/scientist.dm index 0c0e9b669da..296a0d063ee 100644 --- a/code/modules/jobs/job_types/station/science/scientist.dm +++ b/code/modules/jobs/job_types/station/science/scientist.dm @@ -1,4 +1,4 @@ -/datum/job/station/scientist +/datum/role/job/station/scientist id = JOB_ID_SCIENTIST title = "Scientist" flag = SCIENTIST @@ -20,62 +20,62 @@ the principles and requirements of Research and Development. They may also formulate experiments of their own devising, if \ they find an appropriate topic." alt_titles = list( - "Junior Scientist" = /datum/alt_title/scientist/junior, - "Lab Assistant" = /datum/alt_title/scientist/assistant, - "Researcher" = /datum/alt_title/scientist/researcher, - "Xenoarchaeologist" = /datum/alt_title/scientist/xenoarch, - "Anomalist" = /datum/alt_title/scientist/anomalist, \ - "Phoron Researcher" = /datum/alt_title/scientist/phoron_research, - "Circuit Designer" = /datum/alt_title/scientist/circuit, - "Research Field Technician" = /datum/alt_title/scientist/fieldtech, - "Xenobotanist" = /datum/alt_title/scientist/xenobotanist, - "Xenobiologist" = /datum/alt_title/scientist/xenobiologist + "Junior Scientist" = /datum/prototype/alt_title/scientist/junior, + "Lab Assistant" = /datum/prototype/alt_title/scientist/assistant, + "Researcher" = /datum/prototype/alt_title/scientist/researcher, + "Xenoarchaeologist" = /datum/prototype/alt_title/scientist/xenoarch, + "Anomalist" = /datum/prototype/alt_title/scientist/anomalist, \ + "Phoron Researcher" = /datum/prototype/alt_title/scientist/phoron_research, + "Circuit Designer" = /datum/prototype/alt_title/scientist/circuit, + "Research Field Technician" = /datum/prototype/alt_title/scientist/fieldtech, + "Xenobotanist" = /datum/prototype/alt_title/scientist/xenobotanist, + "Xenobiologist" = /datum/prototype/alt_title/scientist/xenobiologist ) -/datum/alt_title/scientist/junior +/datum/prototype/alt_title/scientist/junior title = "Junior Scientist" title_blurb = "A Junior Scientist is a lower-level member of research staff, whose main purpose is to help scientists with their specialized work in more menial fashion, while also \ learning the specializations in process." -/datum/alt_title/scientist/assistant +/datum/prototype/alt_title/scientist/assistant title = "Lab Assistant" title_blurb = "A Lab Assistant is a lower-level member of research staff, whose main purpose is to help scientists with their specialized work in more menial fashion, while also \ learning the specializations in process." -/datum/alt_title/scientist/researcher +/datum/prototype/alt_title/scientist/researcher title = "Researcher" -/datum/alt_title/scientist/xenoarch +/datum/prototype/alt_title/scientist/xenoarch title = "Xenoarchaeologist" title_blurb = "A Xenoarchaeologist enters digsites in search of artifacts of alien origin. These digsites are frequently in vacuum or other inhospitable \ locations, and as such a Xenoarchaeologist should be prepared to handle hostile evironmental conditions." -/datum/alt_title/scientist/anomalist +/datum/prototype/alt_title/scientist/anomalist title = "Anomalist" title_blurb = "An Anomalist is a Scientist whose expertise is analyzing alien artifacts. They are familar with the most common methods of testing artifact \ function. They work closely with Xenoarchaeologists, or Miners, if either role is present." -/datum/alt_title/scientist/phoron_research +/datum/prototype/alt_title/scientist/phoron_research title = "Phoron Researcher" title_blurb = "A Phoron Researcher is a specialist in the practical applications of phoron, and has knowledge of its practical uses and dangers. \ Many Phoron Researchers are interested in the combustability and explosive properties of gaseous phoron, as well as the specific hazards \ of working with the substance in that state." -/datum/alt_title/scientist/circuit +/datum/prototype/alt_title/scientist/circuit title = "Circuit Designer" title_blurb = "A Circuit Designer is a Scientist whose expertise is working with integrated circuits. They are familar with the workings and programming of those devices. \ They work to create various useful devices using the capabilities of integrated circuitry." -/datum/alt_title/scientist/fieldtech +/datum/prototype/alt_title/scientist/fieldtech title = "Research Field Technician" -/datum/alt_title/scientist/xenobiologist +/datum/prototype/alt_title/scientist/xenobiologist title = "Xenobiologist" title_blurb = "A Xenobiologist studies esoteric lifeforms, usually in the relative safety of their lab. They attempt to find ways to benefit \ from the byproducts of these lifeforms, and their main subject at present is the Giant Slime." title_outfit = /datum/outfit/job/station/scientist/xenobiologist -/datum/alt_title/scientist/xenobotanist +/datum/prototype/alt_title/scientist/xenobotanist title = "Xenobotanist" title_blurb = "A Xenobotanist grows and cares for a variety of abnormal, custom made, and frequently dangerous plant life. When the products of these plants \ are both safe and beneficial to the station, they may choose to introduce it to the rest of the crew." diff --git a/code/modules/jobs/job_types/station/science/senior_researcher.dm b/code/modules/jobs/job_types/station/science/senior_researcher.dm index e243684fcb9..3ab16d120c4 100644 --- a/code/modules/jobs/job_types/station/science/senior_researcher.dm +++ b/code/modules/jobs/job_types/station/science/senior_researcher.dm @@ -1,4 +1,4 @@ -/datum/job/station/senior_researcher +/datum/role/job/station/senior_researcher title = "Senior Researcher" economy_payscale = ECONOMY_PAYSCALE_JOB_SENIOR id = JOB_ID_SENIOR_RESEARCHER diff --git a/code/modules/jobs/job_types/station/science/xenobiologist.dm b/code/modules/jobs/job_types/station/science/xenobiologist.dm index 18f99ba5760..41f6ff6ec68 100644 --- a/code/modules/jobs/job_types/station/science/xenobiologist.dm +++ b/code/modules/jobs/job_types/station/science/xenobiologist.dm @@ -2,7 +2,7 @@ ////////////////////////////////// // Xenobiologist ////////////////////////////////// -/datum/job/station/xenobiologist +/datum/role/job/station/xenobiologist title = "Xenobiologist" flag = XENOBIOLOGIST departments = list(DEPARTMENT_RESEARCH) @@ -23,16 +23,16 @@ from the byproducts of these lifeforms, and their main subject at present is the Giant Slime." alt_titles = list( - "Xenozoologist" = /datum/alt_title/xenozoologist, - "Xenoanthropologist" = /datum/alt_title/xenoanthropologist + "Xenozoologist" = /datum/prototype/alt_title/xenozoologist, + "Xenoanthropologist" = /datum/prototype/alt_title/xenoanthropologist ) // Xenibiologist Alt Titles -/datum/alt_title/xenozoologist +/datum/prototype/alt_title/xenozoologist title = "Xenozoologist" title_blurb = "Xenozoologists are well versed in their study of extra-terrestrial life." // Someone make a better blurb please -/datum/alt_title/xenoanthropologist +/datum/prototype/alt_title/xenoanthropologist title = "Xenoanthropologist" title_blurb = "Xenoanthropologist still heavily focuses their study on alien lifeforms, but their specialty leans more towards fellow sapient beings than simple animals." */ diff --git a/code/modules/jobs/job_types/station/science/xenobotanist.dm b/code/modules/jobs/job_types/station/science/xenobotanist.dm index 34acc4bc57e..a8a166a0a64 100644 --- a/code/modules/jobs/job_types/station/science/xenobotanist.dm +++ b/code/modules/jobs/job_types/station/science/xenobotanist.dm @@ -2,7 +2,7 @@ ////////////////////////////////// // Xenobotanist ////////////////////////////////// -/datum/job/station/xenobotanist +/datum/role/job/station/xenobotanist title = "Xenobotanist" flag = XENOBOTANIST departments = list(DEPARTMENT_RESEARCH) @@ -21,13 +21,13 @@ desc = "A Xenobotanist grows and cares for a variety of abnormal, custom made, and frequently dangerous plant life. When the products of these plants \ are both safe and beneficial to the station, they may choose to introduce it to the rest of the crew." alt_titles = list( - "Xenohydroponicist" = /datum/alt_title/xenohydroponicist, - "Xenoflorist" = /datum/alt_title/xenoflorist + "Xenohydroponicist" = /datum/prototype/alt_title/xenohydroponicist, + "Xenoflorist" = /datum/prototype/alt_title/xenoflorist ) -/datum/alt_title/xenoflorist +/datum/prototype/alt_title/xenoflorist title = "Xenoflorist" -/datum/alt_title/xenohydroponicist +/datum/prototype/alt_title/xenohydroponicist title = "Xenohydroponicist" */ diff --git a/code/modules/jobs/job_types/station/security/detective.dm b/code/modules/jobs/job_types/station/security/detective.dm index 5a1ae18ba6c..c0693affe79 100644 --- a/code/modules/jobs/job_types/station/security/detective.dm +++ b/code/modules/jobs/job_types/station/security/detective.dm @@ -1,4 +1,4 @@ -/datum/job/station/detective +/datum/role/job/station/detective id = JOB_ID_DETECTIVE title = "Detective" flag = DETECTIVE @@ -17,15 +17,15 @@ desc = "A Detective works to help Security find criminals who have not properly been identified, through interviews and forensic work. \ For crimes only witnessed after the fact, or those with no survivors, they attempt to piece together what they can from pure evidence." alt_titles = list( - "Forensic Technician" = /datum/alt_title/detective/forensics_tech, - "Crime Scene Investigator" = /datum/alt_title/detective/csi + "Forensic Technician" = /datum/prototype/alt_title/detective/forensics_tech, + "Crime Scene Investigator" = /datum/prototype/alt_title/detective/csi ) -/datum/alt_title/detective/csi +/datum/prototype/alt_title/detective/csi title = "Crime Scene Investigator" /// Detective Alt Titles -/datum/alt_title/detective/forensics_tech +/datum/prototype/alt_title/detective/forensics_tech title = "Forensic Technician" title_blurb = "A Forensic Technician works more with hard evidence and labwork than a Detective, but they share the purpose of solving crimes." title_outfit = /datum/outfit/job/station/detective/forensic diff --git a/code/modules/jobs/job_types/station/security/head_of_security.dm b/code/modules/jobs/job_types/station/security/head_of_security.dm index 32d3860f8dc..d7855474377 100644 --- a/code/modules/jobs/job_types/station/security/head_of_security.dm +++ b/code/modules/jobs/job_types/station/security/head_of_security.dm @@ -1,4 +1,4 @@ -/datum/job/station/head_of_security +/datum/role/job/station/head_of_security id = JOB_ID_HEAD_OF_SECURITY economy_payscale = ECONOMY_PAYSCALE_JOB_COMMAND title = "Head of Security" @@ -32,18 +32,18 @@ keep the other Department Heads, and the rest of the crew, aware of developing situations that may be a threat. If necessary, the HoS may \ perform the duties of absent Security roles, such as distributing gear from the Armory." alt_titles = list( - "Security Commander" = /datum/alt_title/hos/commander, - "Chief of Security" = /datum/alt_title/hos/chief, - "Defense Director" = /datum/alt_title/hos/director + "Security Commander" = /datum/prototype/alt_title/hos/commander, + "Chief of Security" = /datum/prototype/alt_title/hos/chief, + "Defense Director" = /datum/prototype/alt_title/hos/director ) -/datum/alt_title/hos/commander +/datum/prototype/alt_title/hos/commander title = "Security Commander" -/datum/alt_title/hos/chief +/datum/prototype/alt_title/hos/chief title = "Chief of Security" -/datum/alt_title/hos/director +/datum/prototype/alt_title/hos/director title = "Defense Director" /datum/outfit/job/station/head_of_security diff --git a/code/modules/jobs/job_types/station/security/security_officer.dm b/code/modules/jobs/job_types/station/security/security_officer.dm index d494d103dab..e4e6dbc8b41 100644 --- a/code/modules/jobs/job_types/station/security/security_officer.dm +++ b/code/modules/jobs/job_types/station/security/security_officer.dm @@ -1,4 +1,4 @@ -/datum/job/station/officer +/datum/role/job/station/officer id = JOB_ID_SECURITY_OFFICER title = "Security Officer" flag = OFFICER @@ -19,21 +19,21 @@ apprehending criminals. A Security Officer is responsible for the health, safety, and processing of any prisoner they arrest. \ No one is above the Law, not Security or Command." alt_titles = list( - "Junior Officer" = /datum/alt_title/security_officer/junior, - "Security Cadet" = /datum/alt_title/security_officer/cadet, - "Security Guard" = /datum/alt_title/security_officer/guard + "Junior Officer" = /datum/prototype/alt_title/security_officer/junior, + "Security Cadet" = /datum/prototype/alt_title/security_officer/cadet, + "Security Guard" = /datum/prototype/alt_title/security_officer/guard ) -/datum/alt_title/security_officer/junior +/datum/prototype/alt_title/security_officer/junior title = "Junior Officer" title_blurb = "A Junior Officer is an inexperienced Security Officer. They likely have training, but not experience, and are frequently \ paired off with a more senior co-worker. Junior Officers may also be expected to take over the boring duties of other Officers \ including patrolling the station or maintaining specific posts." -/datum/alt_title/security_officer/cadet +/datum/prototype/alt_title/security_officer/cadet title = "Security Cadet" -/datum/alt_title/security_officer/guard +/datum/prototype/alt_title/security_officer/guard title = "Security Guard" /datum/outfit/job/station/security_officer diff --git a/code/modules/jobs/job_types/station/security/warden.dm b/code/modules/jobs/job_types/station/security/warden.dm index b372238301f..aaa4b61d508 100644 --- a/code/modules/jobs/job_types/station/security/warden.dm +++ b/code/modules/jobs/job_types/station/security/warden.dm @@ -1,4 +1,4 @@ -/datum/job/station/warden +/datum/role/job/station/warden id = JOB_ID_WARDEN economy_payscale = ECONOMY_PAYSCALE_JOB_SENIOR title = "Warden" @@ -22,14 +22,14 @@ Armoury gear in a crisis, and retrieving it when the crisis has passed. In an emergency, the Warden may be called upon to direct the \ Security Department as a whole." alt_titles = list( - "Jailor" = /datum/alt_title/warden/jailor, - "Dispatch Officer" = /datum/alt_title/warden/dispatch_officer + "Jailor" = /datum/prototype/alt_title/warden/jailor, + "Dispatch Officer" = /datum/prototype/alt_title/warden/dispatch_officer ) -/datum/alt_title/warden/jailor +/datum/prototype/alt_title/warden/jailor title = "Jailor" -/datum/alt_title/warden/dispatch_officer +/datum/prototype/alt_title/warden/dispatch_officer title = "Dispatch Officer" /datum/outfit/job/station/warden diff --git a/code/modules/jobs/job_types/station/service/bartender.dm b/code/modules/jobs/job_types/station/service/bartender.dm index de6cb66f1bd..b00212a30e0 100644 --- a/code/modules/jobs/job_types/station/service/bartender.dm +++ b/code/modules/jobs/job_types/station/service/bartender.dm @@ -1,4 +1,4 @@ -/datum/job/station/bartender +/datum/role/job/station/bartender id = JOB_ID_BARTENDER title = "Bartender" flag = BARTENDER @@ -16,18 +16,18 @@ outfit_type = /datum/outfit/job/station/bartender desc = "A Bartender mixes drinks for the crew. They generally have permission to charge for drinks or deny service to unruly patrons." alt_titles = list( - "Barista" = /datum/alt_title/bartender/barista, - "Barkeeper" = /datum/alt_title/bartender/barkeeper, - "Barmaid" = /datum/alt_title/bartender/barmaid + "Barista" = /datum/prototype/alt_title/bartender/barista, + "Barkeeper" = /datum/prototype/alt_title/bartender/barkeeper, + "Barmaid" = /datum/prototype/alt_title/bartender/barmaid ) -/datum/alt_title/bartender/barkeeper +/datum/prototype/alt_title/bartender/barkeeper title = "Barkeeper" -/datum/alt_title/bartender/barmaid +/datum/prototype/alt_title/bartender/barmaid title = "Barmaid" -/datum/alt_title/bartender/barista +/datum/prototype/alt_title/bartender/barista title = "Barista" title_blurb = "A barista mans the Cafe, serving primarily non-alcoholic drinks to the crew. They generally have permission to charge for drinks \ or deny service to unruly patrons." diff --git a/code/modules/jobs/job_types/station/service/botanist.dm b/code/modules/jobs/job_types/station/service/botanist.dm index 1b135857eec..ff8626201c4 100644 --- a/code/modules/jobs/job_types/station/service/botanist.dm +++ b/code/modules/jobs/job_types/station/service/botanist.dm @@ -1,4 +1,4 @@ -/datum/job/station/hydro +/datum/role/job/station/hydro id = JOB_ID_BOTANIST title = "Botanist" flag = BOTANIST @@ -16,9 +16,9 @@ outfit_type = /datum/outfit/job/station/botanist/gardener desc = "A Botanist grows plants for the Chef and Bartender." - alt_titles = list("Gardener" = /datum/alt_title/gardener) + alt_titles = list("Gardener" = /datum/prototype/alt_title/gardener) -/datum/alt_title/gardener +/datum/prototype/alt_title/gardener title = "Gardener" title_blurb = "A Gardener may be less professional than their counterparts, and are more likely to tend to the public gardens if they aren't needed elsewhere." diff --git a/code/modules/jobs/job_types/station/service/chef.dm b/code/modules/jobs/job_types/station/service/chef.dm index 807d122c000..c6d4e988f10 100644 --- a/code/modules/jobs/job_types/station/service/chef.dm +++ b/code/modules/jobs/job_types/station/service/chef.dm @@ -1,4 +1,4 @@ -/datum/job/station/chef +/datum/role/job/station/chef id = JOB_ID_CHEF title = "Chef" flag = CHEF @@ -16,24 +16,24 @@ outfit_type = /datum/outfit/job/station/chef desc = "A Chef cooks food for the crew. They generally have permission to charge for food or deny service to unruly diners." alt_titles = list( - "Cook" = /datum/alt_title/chef/cook, - "Sous-chef" = /datum/alt_title/chef/souschef, - "Kitchen Worker" = /datum/alt_title/chef/kitchen_worker, - "Line Cook" = /datum/alt_title/chef/line + "Cook" = /datum/prototype/alt_title/chef/cook, + "Sous-chef" = /datum/prototype/alt_title/chef/souschef, + "Kitchen Worker" = /datum/prototype/alt_title/chef/kitchen_worker, + "Line Cook" = /datum/prototype/alt_title/chef/line ) -/datum/alt_title/chef/souschef +/datum/prototype/alt_title/chef/souschef title = "Sous-chef" -/datum/alt_title/chef/kitchen_worker +/datum/prototype/alt_title/chef/kitchen_worker title = "Kitchen Worker" title_blurb = "A Kitchen Worker has the same duties, though they may be less experienced." -/datum/alt_title/chef/line +/datum/prototype/alt_title/chef/line title = "Line Cook" // Chef Alt Titles -/datum/alt_title/chef/cook +/datum/prototype/alt_title/chef/cook title = "Cook" title_blurb = "A Cook has the same duties, though they may be less experienced." diff --git a/code/modules/jobs/job_types/station/service/janitor.dm b/code/modules/jobs/job_types/station/service/janitor.dm index 2e26a13d320..bedf376502a 100644 --- a/code/modules/jobs/job_types/station/service/janitor.dm +++ b/code/modules/jobs/job_types/station/service/janitor.dm @@ -1,4 +1,4 @@ -/datum/job/station/janitor +/datum/role/job/station/janitor id = JOB_ID_JANITOR title = "Janitor" flag = JANITOR @@ -16,22 +16,22 @@ outfit_type = /datum/outfit/job/station/janitor desc = "A Janitor keeps the station clean, as long as it doesn't interfere with active crime scenes." alt_titles = list( - "Custodian" = /datum/alt_title/janitor/custodian, - "Sanitation Technician" = /datum/alt_title/janitor/tech, - "Viscera Cleaner" = /datum/alt_title/janitor/gorecleaner, - "Maid" = /datum/alt_title/janitor/maid + "Custodian" = /datum/prototype/alt_title/janitor/custodian, + "Sanitation Technician" = /datum/prototype/alt_title/janitor/tech, + "Viscera Cleaner" = /datum/prototype/alt_title/janitor/gorecleaner, + "Maid" = /datum/prototype/alt_title/janitor/maid ) -/datum/alt_title/janitor/custodian +/datum/prototype/alt_title/janitor/custodian title = "Custodian" -/datum/alt_title/janitor/tech +/datum/prototype/alt_title/janitor/tech title = "Sanitation Technician" -/datum/alt_title/janitor/gorecleaner +/datum/prototype/alt_title/janitor/gorecleaner title = "Viscera Cleaner" -/datum/alt_title/janitor/maid +/datum/prototype/alt_title/janitor/maid title = "Maid" title_outfit = /datum/outfit/job/station/janitor/maid diff --git a/code/modules/jobs/job_types/station/silicon/ai.dm b/code/modules/jobs/job_types/station/silicon/ai.dm index 9bcde1c8e2d..78bae1fe28d 100644 --- a/code/modules/jobs/job_types/station/silicon/ai.dm +++ b/code/modules/jobs/job_types/station/silicon/ai.dm @@ -1,4 +1,4 @@ -/datum/job/station/ai +/datum/role/job/station/ai id = JOB_ID_AI title = "AI" flag = AI @@ -23,20 +23,20 @@ disallow_jobhop = TRUE // AI procs -/datum/job/station/ai/equip(var/mob/living/carbon/human/H) +/datum/role/job/station/ai/equip(var/mob/living/carbon/human/H) if(!H) return 0 return 1 -/datum/job/station/ai/slots_remaining(latejoin) +/datum/role/job/station/ai/slots_remaining(latejoin) if(latejoin) return GLOB.empty_playable_ai_cores.len return ..() -/datum/job/station/ai/is_position_available() +/datum/role/job/station/ai/is_position_available() return (GLOB.empty_playable_ai_cores.len != 0) -/datum/job/station/ai/equip_preview(mob/living/carbon/human/H) +/datum/role/job/station/ai/equip_preview(mob/living/carbon/human/H) H.equip_to_slot_or_del(new /obj/item/clothing/suit/straight_jacket(H), SLOT_ID_SUIT) H.equip_to_slot_or_del(new /obj/item/clothing/head/cardborg(H), SLOT_ID_HEAD) return 1 diff --git a/code/modules/jobs/job_types/station/silicon/cyborg.dm b/code/modules/jobs/job_types/station/silicon/cyborg.dm index 0c51504d071..5e6efb3554f 100644 --- a/code/modules/jobs/job_types/station/silicon/cyborg.dm +++ b/code/modules/jobs/job_types/station/silicon/cyborg.dm @@ -1,4 +1,4 @@ -/datum/job/station/cyborg +/datum/role/job/station/cyborg id = JOB_ID_CYBORG title = "Cyborg" flag = CYBORG @@ -18,27 +18,27 @@ desc = "A Cyborg is a mobile station synthetic, piloted by a cybernetically preserved brain. It is considered a person, but is still required \ to follow its Laws." alt_titles = list( - "Robot" = /datum/alt_title/robot, - "Drone" = /datum/alt_title/drone + "Robot" = /datum/prototype/alt_title/robot, + "Drone" = /datum/prototype/alt_title/drone ) // Cyborg Alt Titles -/datum/alt_title/robot +/datum/prototype/alt_title/robot title = "Robot" title_blurb = "A Robot is a mobile station synthetic, piloted by an advanced piece of technology called a Positronic Brain. It is considered a person, \ legally, but is required to follow its Laws." -/datum/alt_title/drone +/datum/prototype/alt_title/drone title = "Drone" title_blurb = "A Drone is a mobile station synthetic, piloted by a simple computer-based AI. As such, it is not a person, but rather an expensive and \ and important piece of station property, and is expected to follow its Laws." // Cyborg procs -/datum/job/station/cyborg/equip(var/mob/living/carbon/human/H) +/datum/role/job/station/cyborg/equip(var/mob/living/carbon/human/H) if(!H) return 0 return 1 -/datum/job/station/cyborg/equip_preview(mob/living/carbon/human/H) +/datum/role/job/station/cyborg/equip_preview(mob/living/carbon/human/H) H.equip_to_slot_or_del(new /obj/item/clothing/suit/cardborg(H), SLOT_ID_SUIT) H.equip_to_slot_or_del(new /obj/item/clothing/head/cardborg(H), SLOT_ID_HEAD) return 1 diff --git a/code/modules/jobs/job_types/station/supply/cargo_technician.dm b/code/modules/jobs/job_types/station/supply/cargo_technician.dm index fd63d8b18a3..69b2ebdf5ec 100644 --- a/code/modules/jobs/job_types/station/supply/cargo_technician.dm +++ b/code/modules/jobs/job_types/station/supply/cargo_technician.dm @@ -1,4 +1,4 @@ -/datum/job/station/cargo_tech +/datum/role/job/station/cargo_tech id = JOB_ID_CARGO_TECHNICIAN title = "Cargo Technician" flag = CARGOTECH @@ -15,9 +15,9 @@ outfit_type = /datum/outfit/job/station/cargo_technician desc = "A Cargo Technician fills and delivers cargo orders. They are encouraged to return delivered crates to the Cargo Shuttle, \ because Central Command gives a partial refund." - alt_titles = list("Logistics Specialist" = /datum/alt_title/logi_spec) + alt_titles = list("Logistics Specialist" = /datum/prototype/alt_title/logi_spec) -/datum/alt_title/logi_spec +/datum/prototype/alt_title/logi_spec title = "Logistics Specialist" /datum/outfit/job/station/cargo_technician diff --git a/code/modules/jobs/job_types/station/supply/quartermaster.dm b/code/modules/jobs/job_types/station/supply/quartermaster.dm index 2d7ccdd79a7..5cb858c22ff 100644 --- a/code/modules/jobs/job_types/station/supply/quartermaster.dm +++ b/code/modules/jobs/job_types/station/supply/quartermaster.dm @@ -1,4 +1,4 @@ -/datum/job/station/quartermaster +/datum/role/job/station/quartermaster id = JOB_ID_QUARTERMASTER title = "Quartermaster" economy_payscale = ECONOMY_PAYSCALE_JOB_SENIOR @@ -20,9 +20,9 @@ outfit_type = /datum/outfit/job/station/quartermaster desc = "The Quartermaster manages the Supply department, checking cargo orders and ensuring supplies get to where they are needed." - alt_titles = list("Supply Chief" = /datum/alt_title/supply_chief) + alt_titles = list("Supply Chief" = /datum/prototype/alt_title/supply_chief) -/datum/alt_title/supply_chief +/datum/prototype/alt_title/supply_chief title = "Supply Chief" /datum/outfit/job/station/quartermaster diff --git a/code/modules/jobs/job_types/station/supply/shaft_miner.dm b/code/modules/jobs/job_types/station/supply/shaft_miner.dm index c7d7c5f501a..d49b84e9606 100644 --- a/code/modules/jobs/job_types/station/supply/shaft_miner.dm +++ b/code/modules/jobs/job_types/station/supply/shaft_miner.dm @@ -1,4 +1,4 @@ -/datum/job/station/mining +/datum/role/job/station/mining id = JOB_ID_SHAFT_MINER title = "Shaft Miner" flag = MINER @@ -17,15 +17,18 @@ outfit_type = /datum/outfit/job/station/shaft_miner desc = "A Shaft Miner mines and processes minerals to be delivered to departments that need them." alt_titles = list( - "Drill Technician" = /datum/alt_title/drill_tech, - "Belt Miner" = /datum/alt_title/miner/belt + "Drill Technician" = /datum/prototype/alt_title/miner/drill_tech, + "Belt Miner" = /datum/prototype/alt_title/miner/belt ) -/datum/alt_title/drill_tech +/datum/prototype/alt_title/miner + abstract_type = /datum/prototype/alt_title/miner + +/datum/prototype/alt_title/miner/drill_tech title = "Drill Technician" title_blurb = "A Drill Technician specializes in operating and maintaining the machinery needed to extract ore from veins deep below the surface." -/datum/alt_title/miner/belt +/datum/prototype/alt_title/miner/belt title = "Belt Miner" /datum/outfit/job/station/shaft_miner diff --git a/code/modules/jobs/jobs.dm b/code/modules/jobs/jobs.dm index c658f29185a..496ef15ba34 100644 --- a/code/modules/jobs/jobs.dm +++ b/code/modules/jobs/jobs.dm @@ -61,10 +61,10 @@ var/const/TRADER =(1<<15) /proc/get_job_datums() var/list/occupations = list() - var/list/all_jobs = typesof(/datum/job) + var/list/all_jobs = typesof(/datum/role/job) for(var/A in all_jobs) - var/datum/job/job = new A() + var/datum/role/job/job = new A() if(!job) continue occupations += job @@ -74,7 +74,7 @@ var/const/TRADER =(1<<15) var/list/jobs = get_job_datums() var/list/titles = list() - for(var/datum/job/J in jobs) + for(var/datum/role/job/J in jobs) if(J.title == job) titles = J.alt_titles diff --git a/code/modules/jobs/outfit.dm b/code/modules/jobs/outfit.dm index 178891eb3b7..d01f020292e 100644 --- a/code/modules/jobs/outfit.dm +++ b/code/modules/jobs/outfit.dm @@ -17,7 +17,7 @@ var/obj/item/card/id/C = ..() if(!C) return - var/datum/job/J = SSjob.get_job(rank) + var/datum/role/job/J = SSjob.get_job(rank) if(J) C.access = J.get_access() if(H.mind) diff --git a/code/modules/lore_hardcoded/_hardcoded.dm b/code/modules/lore_hardcoded/_hardcoded.dm index e94d76c1acb..03cf0788052 100644 --- a/code/modules/lore_hardcoded/_hardcoded.dm +++ b/code/modules/lore_hardcoded/_hardcoded.dm @@ -9,6 +9,8 @@ var/name = "Unknown" /// id - **must be unique on subtypes var/id + /// category + var/category = "Misc" /// description/what the player sees var/desc = "What is this?" /// subspecies are counted as the master species diff --git a/code/modules/lore_hardcoded/faction.dm b/code/modules/lore_hardcoded/faction.dm index f1d99946457..a1ce26d686f 100644 --- a/code/modules/lore_hardcoded/faction.dm +++ b/code/modules/lore_hardcoded/faction.dm @@ -1,6 +1,6 @@ /datum/lore/character_background/faction abstract_type = /datum/lore/character_background/faction - /// station job types you can play as under this - **typepaths** e.g. /datum/job/station/security_officer, etc + /// station job types you can play as under this - **typepaths** e.g. /datum/role/job/station/security_officer, etc /// if null, you can play as everything var/list/job_whitelist = list() /// job blacklist diff --git a/code/modules/lore_hardcoded/origin.dm b/code/modules/lore_hardcoded/origin.dm index 5b46658968f..7840da9eb12 100644 --- a/code/modules/lore_hardcoded/origin.dm +++ b/code/modules/lore_hardcoded/origin.dm @@ -1,7 +1,5 @@ /datum/lore/character_background/origin abstract_type = /datum/lore/character_background/origin - /// category - var/category = "Misc" /datum/lore/character_background/origin/check_character_species(datum/character_species/S) if(S.species_fluff_flags & SPECIES_FLUFF_PICKY_ORIGIN) diff --git a/code/modules/maps/overmap/space/talon/talon_jobs.dm b/code/modules/maps/overmap/space/talon/talon_jobs.dm index 827c17e56aa..187cc62a854 100644 --- a/code/modules/maps/overmap/space/talon/talon_jobs.dm +++ b/code/modules/maps/overmap/space/talon/talon_jobs.dm @@ -18,7 +18,7 @@ assignable = FALSE visible = FALSE -/datum/job/talon_captain +/datum/role/job/talon_captain title = "Talon Captain" flag = TALCAP department_flag = TALON @@ -37,12 +37,12 @@ pto_type = null access = list(access_talon) minimal_access = list(access_talon) - alt_titles = list("Talon Commander" = /datum/alt_title/talon_commander) + alt_titles = list("Talon Commander" = /datum/prototype/alt_title/talon_commander) -/datum/alt_title/talon_commander +/datum/prototype/alt_title/talon_commander title = "Talon Commander" -/datum/job/talon_doctor +/datum/role/job/talon_doctor title = "Talon Doctor" flag = TALDOC department_flag = TALON @@ -60,13 +60,13 @@ pto_type = null access = list(access_talon) minimal_access = list(access_talon) - alt_titles = list("Talon Medic" = /datum/alt_title/talon_medic) + alt_titles = list("Talon Medic" = /datum/prototype/alt_title/talon_medic) -/datum/alt_title/talon_medic +/datum/prototype/alt_title/talon_medic title = "Talon Medic" -/datum/job/talon_engineer +/datum/role/job/talon_engineer title = "Talon Engineer" flag = TALENG department_flag = TALON @@ -84,13 +84,13 @@ pto_type = null access = list(access_talon) minimal_access = list(access_talon) - alt_titles = list("Talon Technician" = /datum/alt_title/talon_tech) + alt_titles = list("Talon Technician" = /datum/prototype/alt_title/talon_tech) -/datum/alt_title/talon_tech +/datum/prototype/alt_title/talon_tech title = "Talon Technician" -/datum/job/talon_pilot +/datum/role/job/talon_pilot title = "Talon Pilot" flag = TALPIL department_flag = TALON @@ -108,13 +108,13 @@ pto_type = null access = list(access_talon) minimal_access = list(access_talon) - alt_titles = list("Talon Helmsman" = /datum/alt_title/talon_helmsman) + alt_titles = list("Talon Helmsman" = /datum/prototype/alt_title/talon_helmsman) -/datum/alt_title/talon_helmsman +/datum/prototype/alt_title/talon_helmsman title = "Talon Helmsman" -/datum/job/talon_guard +/datum/role/job/talon_guard title = "Talon Guard" flag = TALSEC department_flag = TALON @@ -132,9 +132,9 @@ pto_type = null access = list(access_talon) minimal_access = list(access_talon) - alt_titles = list("Talon Security" = /datum/alt_title/talon_security) + alt_titles = list("Talon Security" = /datum/prototype/alt_title/talon_security) -/datum/alt_title/talon_security +/datum/prototype/alt_title/talon_security title = "Talon Security" diff --git a/code/modules/maps/overmap/space/trade_station/trade_station_jobs.dm b/code/modules/maps/overmap/space/trade_station/trade_station_jobs.dm index 61e6ff970c8..c9ab597f8a9 100644 --- a/code/modules/maps/overmap/space/trade_station/trade_station_jobs.dm +++ b/code/modules/maps/overmap/space/trade_station/trade_station_jobs.dm @@ -7,7 +7,7 @@ assignable = FALSE visible = FALSE -/datum/job/trader +/datum/role/job/trader title = "Trader" flag = TRADER id = JOB_ID_TRADER @@ -35,15 +35,15 @@ access = list(access_trader) minimal_access = list(access_trader) alt_titles = list( - "Trade Manager" = /datum/alt_title/trade_manager, - "Merchant" = /datum/alt_title/merchant + "Trade Manager" = /datum/prototype/alt_title/trade_manager, + "Merchant" = /datum/prototype/alt_title/merchant ) -/datum/alt_title/trade_manager +/datum/prototype/alt_title/trade_manager title = "Trade Manager" // title_blurb = "A Drill Technician specializes in operating and maintaining the machinery needed to extract ore from veins deep below the surface." -/datum/alt_title/merchant +/datum/prototype/alt_title/merchant title = "Merchant" /datum/outfit/trade diff --git a/code/modules/metric/department.dm b/code/modules/metric/department.dm index 4792434f772..15c1420ed40 100644 --- a/code/modules/metric/department.dm +++ b/code/modules/metric/department.dm @@ -34,18 +34,18 @@ // Like before, records are the most reliable way. var/datum/data/record/R = find_general_record("name", M.real_name) if(R) // They got a record, now find the job datum. - var/datum/job/J = SSjob.get_job(R.fields["real_rank"]) + var/datum/role/job/J = SSjob.get_job(R.fields["real_rank"]) if(istype(J)) return J // Try the mind. if(M.mind) - var/datum/job/J = SSjob.get_job(M.mind.assigned_role) + var/datum/role/job/J = SSjob.get_job(M.mind.assigned_role) if(istype(J)) return J // Last ditch effort, check for job assigned to the mob itself. - var/datum/job/J = SSjob.get_job(M.job) + var/datum/role/job/J = SSjob.get_job(M.job) if(istype(J)) return J @@ -54,7 +54,7 @@ // Feed this proc the name of a job, and it will try to figure out what department they are apart of. // Improved with the addition of SSjob, which has departments be an actual thing and not a virtual concept. /datum/metric/proc/role_name_to_department(var/role_name) - var/datum/job/J = SSjob.get_job(role_name) + var/datum/role/job/J = SSjob.get_job(role_name) if(istype(J)) if(LAZYLEN(J.departments)) return J.departments @@ -84,13 +84,13 @@ /datum/metric/proc/get_people_with_job(job_type, cutoff = 75) . = list() // First, get the name. - var/datum/job/J = SSjob.job_by_type(job_type) + var/datum/role/job/J = SSjob.job_by_type(job_type) if(!istype(J)) return // Now find people with the job name. for(var/M in GLOB.player_list) - var/datum/job/their_job = guess_job(M) + var/datum/role/job/their_job = guess_job(M) if(!istype(their_job)) // No job was guessed. continue if(their_job.title != J.title) // Jobs don't match. @@ -109,8 +109,8 @@ . = list() var/list/people_with_jobs = get_people_with_job(job_type, cutoff) - var/datum/job/J = SSjob.job_by_type(job_type) - var/datum/alt_title/A = new alt_title_type() + var/datum/role/job/J = SSjob.job_by_type(job_type) + var/datum/prototype/alt_title/A = new alt_title_type() for(var/M in people_with_jobs) if(J.has_alt_title(M, null, A.title)) diff --git a/code/modules/mob/characteristics/helpers.dm b/code/modules/mob/characteristics/helpers.dm new file mode 100644 index 00000000000..e5f71336afa --- /dev/null +++ b/code/modules/mob/characteristics/helpers.dm @@ -0,0 +1,11 @@ +/** + * checks if characteristics system is enabled + */ +/proc/characteristics_enabled() + return CONFIG_GET(flag/characteristics_enabled) + +/** + * checks if characteristics system is active + */ +/proc/characteristics_active() + return CONFIG_GET(flag/characteristics_active) diff --git a/code/modules/mob/characteristics/holder.dm b/code/modules/mob/characteristics/holder.dm new file mode 100644 index 00000000000..9ce0b73f00a --- /dev/null +++ b/code/modules/mob/characteristics/holder.dm @@ -0,0 +1,143 @@ +/** + * holds characteristics data + * + * can be just used as a holder datum but can also be used as a 1:1 with a mind + * downsides: can only be associated with one mind at a time, for now. + * if this belongs to a mind the mind has free reign to qdel it. you have been warned. + */ +/datum/characteristics_holder + //! ownership + /// current mind that holds us; **CAN BE NULL** + var/datum/mind/mind + + //! characteristics + /// skill ids associated to values + var/list/skills + /// stat ids associated to values + var/list/stats + /// talent ids associated to arbitrary metadata, usually just 1 for assoc lookup; said metadata should eval to true in logic. + var/list/talents + // todo: modifiers + +/datum/characteristics_holder/Destroy() + if(mind) + disassociate_from_mind(mind) + return ..() + +/datum/characteristics_holder/proc/associate_with_mind(datum/mind/M) + if(M.current) + associate_with_mob(M.current) + if(M.characteristics) + stack_trace("mind already had characteristics") + M.characteristics = src + for(var/id in talents) + var/datum/characteristic_talent/talent = resolve_characteristics_talent(id) + talent.gain(M, talents[id]) + +/datum/characteristics_holder/proc/disassociate_from_mind(datum/mind/M) + if(M.current) + disassociate_from_mob(M.current) + if(M.characteristics != src) + stack_trace("mind characteristics was not self") + for(var/id in talents) + var/datum/characteristic_talent/talent = resolve_characteristics_talent(id) + talent.lose(M, talents[id]) + M.characteristics = null + +/datum/characteristics_holder/proc/associate_with_mob(mob/M) + for(var/id in talents) + var/datum/characteristic_talent/talent = resolve_characteristics_talent(id) + talent.attach(M, talents[id]) + +/datum/characteristics_holder/proc/disassociate_from_mob(mob/M) + for(var/id in talents) + var/datum/characteristic_talent/talent = resolve_characteristics_talent(id) + talent.detach(M, talents[id]) + +/datum/characteristics_holder/proc/set_stat(datum/characteristic_stat/id_or_typepath, val) + LAZYINITLIST(stats) + stats[ispath(id_or_typepath)? initial(id_or_typepath.id) : id_or_typepath] = val + +/datum/characteristics_holder/proc/set_skill(datum/characteristic_skill/id_or_typepath, val) + LAZYINITLIST(skills) + skills[ispath(id_or_typepath)? initial(id_or_typepath.id) : id_or_typepath] = val + +/datum/characteristics_holder/proc/get_stat(datum/characteristic_stat/id_or_typepath) + . = stats?[ispath(id_or_typepath)? initial(id_or_typepath.id) : id_or_typepath] + +/datum/characteristics_holder/proc/get_skill(datum/characteristic_skill/id_or_typepath) + . = skills?[ispath(id_or_typepath)? initial(id_or_typepath.id) : id_or_typepath] || CHARACTER_SKILL_UNTRAINED + +/datum/characteristics_holder/proc/add_talent(datum/characteristic_talent/id_or_typepath, ...) + var/id = ispath(id_or_typepath)? initial(id_or_typepath.id) : id_or_typepath + if(talents?[id]) + // do NOT allow overwrite! + return FALSE + var/datum/characteristic_talent/talent = resolve_characteristics_talent(id) + talents[id] = talent.metadata(arglist(args.Copy(2))) + if(mind) + if(mind.current) + talent.attach(mind.current, talents[id]) + talent.gain(mind, talents[id]) + +/datum/characteristics_holder/proc/remove_talent(datum/characteristic_talent/id_or_typepath) + var/id = ispath(id_or_typepath)? initial(id_or_typepath.id) : id_or_typepath + if(!talents?[id]) + return FALSE + var/datum/characteristic_talent/talent = resolve_characteristics_talent(id) + if(mind) + if(mind.current) + talent.detach(mind.current, talents[id]) + talent.lose(mind, talents[id]) + talents -= id + return TRUE + +/datum/characteristics_holder/proc/has_talent(datum/characteristic_talent/id_or_typepath) + return !!talents[ispath(id_or_typepath)? initial(id_or_typepath.id) : id_or_typepath] + +/** + * apply a preset to us + * + * @params + * - typepath_or_preset - typepath or preset datum + * - overwrite - should we replace everything in us or instead raise / append if needed? + */ +/datum/characteristics_holder/proc/apply_preset(datum/characteristic_preset/typepath_or_preset, overwrite = FALSE) + if(ispath(typepath_or_preset)) + typepath_or_preset = resolve_characteristics_preset(typepath_or_preset) + if(typepath_or_preset.skills) + LAZYINITLIST(skills) + if(overwrite) + skills = typepath_or_preset.skills.Copy() + else + for(var/id in typepath_or_preset.skills) + skills[id] = max(skills[id], typepath_or_preset.skills[id]) + if(typepath_or_preset.stats) + LAZYINITLIST(stats) + if(overwrite) + stats = typepath_or_preset.stats.Copy() + else + for(var/id in typepath_or_preset.stats) + var/datum/characteristic_stat/stat = resolve_characteristics_stat(id) + stats[id] = stat.greater_value(stats[id], typepath_or_preset.stats[id]) + if(typepath_or_preset.talents) + LAZYINITLIST(talents) + for(var/id in typepath_or_preset.talents) + if(has_talent(id)) + continue + if(typepath_or_preset.talents[id]) + add_talent(arglist(list(id) + typepath_or_preset.talents[id])) + else + add_talent(id) + return TRUE + +/** + * clones + */ +/datum/characteristics_holder/proc/clone() + RETURN_TYPE(/datum/characteristics_holder) + var/datum/characteristics_holder/cloning = new + cloning.skills = skills.Copy() + cloning.stats = stats.Copy() + cloning.talents = talents.Copy() + return cloning diff --git a/code/modules/mob/characteristics/mob.dm b/code/modules/mob/characteristics/mob.dm new file mode 100644 index 00000000000..358a5f9969d --- /dev/null +++ b/code/modules/mob/characteristics/mob.dm @@ -0,0 +1,98 @@ +//? file contains mob helpers and whatnot + +//! direct lookup +/** + * checks if we have a characteristic talent + * + * @params + * - typepath_or_id - typepath or id; prefer typepath during compile time + * + * @return TRUE/FALSE + */ +/mob/proc/has_characteristic_talent(datum/characteristic_talent/typepath_or_id) + if(!characteristics_active()) + return FALSE + return mind?.characteristics?.has_talent(typepath_or_id) + +/** + * checks the value of one of our characteristic stats + * + * @params + * - typepath_or_id - typepath or id; prefer typepath during compile time + * + * @return raw value + */ +/mob/proc/get_characteristic_stat(datum/characteristic_stat/typepath_or_id) + if(!characteristics_active()) + typepath_or_id = resolve_characteristics_stat(typepath_or_id) + return typepath_or_id.baseline_value + return mind?.characteristics?.get_stat(typepath_or_id) + +/** + * gets the skill value enum of one of our characteristic skills + * + * @params + * - typepath_or_id - typepath or id; prefer typepath during compile time + * + * @return skill level + */ +/mob/proc/get_characteristic_skill(datum/characteristic_skill/typepath_or_id) + if(!characteristics_active()) + typepath_or_id = resolve_characteristics_stat(typepath_or_id) + return typepath_or_id.baseline_value + return mind?.characteristics?.get_skill(typepath_or_id) + +//! checks + +//? no stat check ; stats are raw values + +//? no talent check ; talents are boolean for checks + +//? skill checks + +/** + * scales a number with requested skill scaling + * + * @params + * * typepath_or_id - typepath or id of skill + * * level - what level is wanted + * * constant - constant for scaling + * * method - skill scaling enum, see __DEFINES/mobs/characteristics.dm + */ +/mob/proc/characteristic_skill_scaling(datum/characteristic_skill/typepath_or_id, level, constant, method) + var/diff = level - get_characteristic_skill(typepath_or_id) + switch(method) + if(SKILL_SCALING_EXPONENTIAL_HARD) + return constant * (2 ** diff) + if(SKILL_SCALING_EXPONENTIAL_SOFT) + return constant * (1.5 ** diff) + if(SKILL_SCALING_LINEAR) + return diff * constant + +/** + * checks if we have a skill at a required level. + * + * @params + * * typepath_or_id - typepath or id of skill + * * level - what level is needed + */ +/mob/proc/characteristic_skill_check(datum/characteristic_skill/typepath_or_id, level) + return level <= get_characteristic_skill(typepath_or_id) + +/** + * gets skill difference + * + * @params + * * typepath_or_id - typepath or id of skill + * * level - what level is needed + */ +/mob/proc/characteristic_skill_difference(datum/characteristic_skill/typepath_or_id, level) + return level - get_characteristic_skill(typepath_or_id) + +/** + * get or create characteristics holder + */ +/mob/proc/characteristics_holder() + if(!mind) + mind_initialize() + return mind.characteristics_holder() diff --git a/code/modules/mob/characteristics/modifier.dm b/code/modules/mob/characteristics/modifier.dm new file mode 100644 index 00000000000..10804784a27 --- /dev/null +++ b/code/modules/mob/characteristics/modifier.dm @@ -0,0 +1,8 @@ +/** + * modifiers applied to characteristics holders temporarily + */ +/datum/characteristic_modifier + + + +// todo: this file isn't done yet. diff --git a/code/modules/mob/characteristics/presets.dm b/code/modules/mob/characteristics/presets.dm new file mode 100644 index 00000000000..fa5aa99add9 --- /dev/null +++ b/code/modules/mob/characteristics/presets.dm @@ -0,0 +1,55 @@ +GLOBAL_LIST_EMPTY(characteristics_presets) + +/** + * gets a skill-holder preset + * + * use typepaths whenever possible for compile time! + */ +/proc/resolve_characteristics_preset(datum/characteristic_preset/typepath_or_instance) + RETURN_TYPE(/datum/characteristic_preset) + if(istype(typepath_or_instance)) + return typepath_or_instance + . = GLOB.characteristics_presets[typepath_or_instance] + if(!.) + return (GLOB.characteristics_presets[typepath_or_instance] = (new typepath_or_instance)) + +/** + * holds presets for skills/whatont + */ +/datum/characteristic_preset + /// name for debugging ; optional + var/name + + /// skill tpyepaths or ids associated to values + var/list/skills + /// stat typepaths or ids associated to values + var/list/stats + /// talent typepaths or ids associated to lists (or null) of what to pass in for arglist in talent add. + var/list/talents + +/datum/characteristic_preset/New(list/skills = list(), list/stats = list(), list/talents = list()) + src.skills = skills.Copy() + src.stats = stats.Copy() + src.talents = talents.Copy() + transform() + +/** + * flatten everything into ids + */ +/datum/characteristic_preset/proc/transform() + var/datum/characteristic_skill/skillpath_or_id + var/datum/characteristic_stat/statpath_or_id + var/datum/characteristic_talent/talentpath_or_id + for(var/i in 1 to length(skills)) + skillpath_or_id = skills[i] + if(ispath(skillpath_or_id)) + skills[i] = initial(skillpath_or_id.id) + for(var/i in 1 to length(stats)) + statpath_or_id = stats[i] + if(ispath(statpath_or_id)) + stats[i] = initial(statpath_or_id.id) + for(var/i in 1 to length(talents)) + talentpath_or_id = talents[i] + if(ispath(talentpath_or_id)) + talents[i] = initial(talentpath_or_id.id) + diff --git a/code/modules/mob/characteristics/readme.md b/code/modules/mob/characteristics/readme.md new file mode 100644 index 00000000000..f626f28c33d --- /dev/null +++ b/code/modules/mob/characteristics/readme.md @@ -0,0 +1,45 @@ +# Characteristics + +A system to do character stats. + +This page is heavily WIP. + +## Config + +CHARACTERISTICS_ENABLED - defaults to true; without this, preferences won't show these things at all. +CHARACTERISTICS_ACTIVE - defaults to false; nothing happens without this, everyone gets baseline average. + +## Specializations + +Special modifiers that increase adaptation towards one archetype +Should be very broad and encourage character development towards a specific field + +Heavily WIP + +## Skills + +Bay-like enum'd numeric stats with levels from 0 to 6 (basic to professional) + +### Recommended Use Cases + +WIP + +## Stats + +Heavily numeric stats that are really low level. +It's not recommended to use these for "abstract" concepts to prevent minmaxing. +It's not recommended to overuse these at all to prevent minmaxing. + +### Recommended Use Cases + +WIP + +## Talents + +Boolean abilities that potentially have special code handling. +Allows for tracking mobs, almost like a /datum/element. +Think Barotrauma talents. + +### Recommended Use Cases + +WIP diff --git a/code/modules/mob/characteristics/skill.dm b/code/modules/mob/characteristics/skill.dm new file mode 100644 index 00000000000..08e2e453b06 --- /dev/null +++ b/code/modules/mob/characteristics/skill.dm @@ -0,0 +1,102 @@ +GLOBAL_LIST_INIT(characteristics_skills, _create_characteristics_skills()) + +/proc/_create_characteristics_skills() + . = list() + for(var/datum/characteristic_skill/skill in subtypesof(/datum/characteristic_skill)) + if(is_abstract(skill)) + continue + . = new skill + if(isnull(skill.id)) + stack_trace("null id on [skill.type]") + continue + if(.[skill.id]) + stack_trace("collision on id [skill.id] between types [skill.type] and [.[skill.id]:type]") + continue + .[skill.id] = skill + +/** + * gets a skill datum + * + * use typepaths whenever possible for compile time! + */ +/proc/resolve_characteristics_skill(datum/characteristic_skill/typepath_or_id) + RETURN_TYPE(/datum/characteristic_skill) + return GLOB.characteristics_skills[ispath(typepath_or_id)? initial(typepath_or_id.id) : typepath_or_id] + +/** + * skills - more enum-like numerics/whatnot than boolean-like talents + * are held in skill holder + * + * skills are untrained when unset, and baseline when characteristics are disabled + */ +/datum/characteristic_skill + abstract_type = /datum/characteristic_skill + //? basics + /// unique id + var/id + /// name + var/name = "ERROR" + /// desc + var/desc = "An unknown skill. Someone needs to set this!" + /// category - just strings for now, don't need defines yet + var/category = "Unsorted" + + //? values + /// what to return if characteristics are disabled + var/baseline_value = CHARACTER_SKILL_ENUM_MIN + /// max skill value + var/max_value = CHARACTER_SKILL_ENUM_MAX + + //? costs - these are additive! + var/cost_novice = 0 + var/cost_trained = 0 + var/cost_experienced = 0 + var/cost_professional = 0 + + var/tmp/total_cost_novice + var/tmp/total_cost_trained + var/tmp/total_cost_experienced + var/tmp/total_cost_professional + + //? descriptions + var/desc_untrained = "ERR: NO UNTRAINED DESC" + var/desc_novice = "ERR: NO NOVICE DESC" + var/desc_trained = "ERR: NO TRAINED DESC" + var/desc_experienced = "ERR: NO EXPERIENCED DESC" + var/desc_professional = "ERR: NO PROFESSIONAL DESC" + +/datum/characteristic_skill/New() + compute_caches() + +/datum/characteristic_skill/proc/total_cost(level) + switch(level) + if(CHARACTER_SKILL_UNTRAINED) + return 0 + if(CHARACTER_SKILL_NOVICE) + . = total_cost_novice + if(CHARACTER_SKILL_TRAINED) + . = total_cost_trained + if(CHARACTER_SKILL_EXPERIENCED) + . = total_cost_experienced + if(CHARACTER_SKILL_PROFESSIONAL) + . = total_cost_professional + +/datum/characteristic_skill/proc/compute_caches() + var/total = 0 + total_cost_novice = round(total, 1) + total_cost_trained = round(total, 1) + total_cost_experienced = round(total, 1) + total_cost_professional = round(total, 1) + +/datum/characteristic_skill/proc/level_description(level) + switch(level) + if(CHARACTER_SKILL_UNTRAINED) + return desc_untrained + if(CHARACTER_SKILL_NOVICE) + return desc_novice + if(CHARACTER_SKILL_TRAINED) + return desc_trained + if(CHARACTER_SKILL_EXPERIENCED) + return desc_experienced + if(CHARACTER_SKILL_PROFESSIONAL) + return desc_professional diff --git a/code/modules/mob/characteristics/skills/engineering.dm b/code/modules/mob/characteristics/skills/engineering.dm new file mode 100644 index 00000000000..0af3d807008 --- /dev/null +++ b/code/modules/mob/characteristics/skills/engineering.dm @@ -0,0 +1,79 @@ +/datum/characteristic_skill/engineering + abstract_type = /datum/characteristic_skill/engineering + category = "Engineering" + +/** + * Electrical Engineering: Wiring, power, etc + * + * Implementation status: not started + */ +/datum/characteristic_skill/engineering/electrical + id = "electrical" + name = "Electrical Engineering" + desc = "How experienced you are with powe, wiring, hacking, etc." + desc_untrained = "What even are wires? You should not be caught dead without insulated gloves if you are messing with a panel. You probably will be caught dead if you do it anyways. Wiring interfaces can become shuffled at random." + desc_novice = "You have some practice with wiring and electricity. Panels are no longer randomized." + desc_trained = "You have general training in electrical maintenance. You can now perform some actions on hacking interfaces without testing for wires, at a random chance depending on the object in question." + desc_experienced = "You do a lot of work with electronics. Departmental wire sets now always order the same way for you. More actions can be used without wire pulsing, and some wires reveal their functions entirely." + desc_professional = "You are a highly skilled electrician. Wires always render in the same order for you, and you can simply manipulate most lower-end devices without hacking or access if you can get the cover off." + cost_novice = SKILLCOST_INCREMENT_MINOR + cost_trained = SKILLCOST_INCREMENT_MODERATE + cost_experienced = SKILLCOST_INCREMENT_MODERATE + cost_professional = SKILLCOST_INCREMENT_MAJOR + +/** + * Construction: Building, Teardowns, etc + * + * Implementation status: not started + */ +/datum/characteristic_skill/engineering/construction + id = "construction" + name = "Construction" + desc = "How good you are at building or breaking things down." + desc_untrained = "You need an instruction manual to put together even a table. All construction are slightly slower for you." + desc_novice = "You've had some practice building things. Construction is now faster." + desc_trained = "You're a handyman of sorts. Construction and deconstruction are now faster. Things will prompt you with what can be used on them if applicable." + desc_experienced = "You're a skilled construction engineer. Automatic construction/deconstruction at a boosted speed is now available for you. Lathes are slightly more efficient for you. Construction is more efficient for you." + desc_professional = "You're a master builder or ship architect. RCDs are more efficient for you. All speeds and lathe handling boosted. You can build more for less." + cost_novice = SKILLCOST_INCREMENT_MINOR + cost_trained = SKILLCOST_INCREMENT_MODERATE + cost_experienced = SKILLCOST_INCREMENT_MODERATE + cost_professional = SKILLCOST_INCREMENT_MAJOR + +/** + * Atmospherics + * + * Implementation status: not started + */ +/datum/characteristic_skill/engineering/atmospherics + id = "atmospherics" + name = "Atmospherics" + desc = "How experienced you are with gas mechanics, atmospherics machinery, etc." + desc_untrained = "What's an air network? All you recall from the academy is PV=NRT. All atmospherics operations tend to slow for you." + desc_novice = "You've had some practice managing air systems. Doing maintenance is now faster. Air alarms show slightly more information. Using an analyzer can be done at range." + desc_trained = "You're an apprentice air technician. Speeds globally increased. You can do basic pipenet tracing with an analyzer rather than T-rays. You can memorize where pipes are after a pulse for a little while." + desc_experienced = "You can intuit some information from the room, as well as some air networks with a glance. Speeds globally increased." + desc_professional = "You can track multiple pieces of atmospherics machinery with a glance, even while far away. You can see the direction of breaches." + cost_novice = SKILLCOST_INCREMENT_MINOR + cost_trained = SKILLCOST_INCREMENT_MINOR + cost_experienced = SKILLCOST_INCREMENT_MAJOR + cost_professional = SKILLCOST_INCREMENT_MAJOR + +/** + * Engines & Ship Systems + * + * Implementation status: not started + */ +/datum/characteristic_skill/engineering/engines + id = "engines" + name = "Engine & Voidcraft Operation" + desc = "How experienced you are with various engines, as well as with systems aboard a ship." + desc_untrained = "You probably shouldn't be touching engines." + desc_novice = "You've been shown how to set up a basic reactor, tune ship systems, so on and so forth. You can now do more efficient repairs on ship systems." + desc_trained = "You've been working on ships, or complex industrial systems for a while. You can check components and efficiencies with a glance." + desc_experienced = "You're a long-time reactor or ship technician. You can overclock ship components while near them. You can now see the engine's EER with a quick glance. You are no longer affected by certain engine emissions." + desc_professional = "You are a master of everything electromechanical. You can now overclock ship components remotely, as well as perform stronger overclocking on the spot." + cost_novice = SKILLCOST_INCREMENT_MINOR + cost_trained = SKILLCOST_INCREMENT_MINOR + cost_experienced = SKILLCOST_INCREMENT_MAJOR + cost_professional = SKILLCOST_INCREMENT_MAJOR diff --git a/code/modules/mob/characteristics/skills/logistics.dm b/code/modules/mob/characteristics/skills/logistics.dm new file mode 100644 index 00000000000..5dae0800411 --- /dev/null +++ b/code/modules/mob/characteristics/skills/logistics.dm @@ -0,0 +1,39 @@ +/datum/characteristic_skill/logistics + abstract_type = /datum/characteristic_skill/logistics + category = "Logistics" + +/** + * Salvage: mining, etc + * + * Implementation status: not started + */ +/datum/characteristic_skill/logistics/salvage + id = "salvage" + name = "Salvage" + desc = "How experienced you are with salvaging and mining. Each level provides additional boosts to mining equipment speed and efficiency." + desc_untrained = "Hitting rocks is unskilled labor, and you are the unskilled labor." + desc_novice = "You have been mining, or salvagingfor a while. Kinetic weaponry and other tooling now have less recoil." + desc_trained = "You are a trained miner. Drills and other equipment you set gain a small speed boost, if configured by you." + desc_experienced = "You're a space salvager. Some EVA skill boosts apply to you as well. You gain very slightly higher ore yields while mining." + desc_professional = "They said robots can replace you, but clearly, they were wrong. Kinetic tooling can now be used by you with almost no one-handing penalties, and you can use some equipment meant for two people by yourself efficiently." + cost_novice = SKILLCOST_INCREMENT_MINOR + cost_trained = SKILLCOST_INCREMENT_MINOR + cost_experienced = SKILLCOST_INCREMENT_MAJOR + cost_professional = SKILLCOST_INCREMENT_MAJOR + +/** + * Logistics: cargo, etc + * + * Implementation status: not started + */ +/datum/characteristic_skill/logistics/cargo + id = "cargo" + name = "Logistics" + desc = "How experienced you are running logistics, deck supply, etc." + desc_untrained = "Surely pushing crates and signing off on orders is easy. Right? Right?!" + desc_novice = "You've been doing logistics for a while. Crates can now be moved at full speed." + desc_trained = "You have been trained in logistics. Crates can now fit more when you pack them. Price scanners and other scanners may now be used at range." + desc_experienced = "You're a master at running a shipyard, or logistics deck. You now automatically negate certain penalties for not labelling crates when exporting. Work mechas now move and operates faster for you. You can intuit the prices of most objects at a glance." + cost_novice = SKILLCOST_INCREMENT_MODERATE + cost_trained = SKILLCOST_INCREMENT_MODERATE + cost_experienced = SKILLCOST_INCREMENT_MAJOR diff --git a/code/modules/mob/characteristics/skills/medical.dm b/code/modules/mob/characteristics/skills/medical.dm new file mode 100644 index 00000000000..6375636617b --- /dev/null +++ b/code/modules/mob/characteristics/skills/medical.dm @@ -0,0 +1,61 @@ +/datum/characteristic_skill/medical + abstract_type = /datum/characteristic_skill/medical + category = "Medical" + +/** + * anatomy: surgery / evaluations / whatnot + * + * implementation status: not started + */ +/datum/characteristic_skill/medical/anatomy + id = "anatomy" + name = "Anatomy" + desc = "How well you know the anatomical structures of living things." + desc_untrained = "You really don't know much about the inner workings of living things beyond the basics. You cannot do surgery well other than in a perfect suite with holographic assistance from a computer." + desc_novice = "You have had a little bit of study into the anatomy of living things. Surgery and dissections are now a bit faster, and you can see a bit more information on wounds with a glance." + desc_trained = "You have formal anatomical training. You can now do risk-free surgery without holographic assistance, in a good enough lab." + desc_experienced = "You have a decent amount of surgery experience. You now have less penalty from bad environments during surgery, and have some basic bonuses to surgery upon xenobiological lifeforms." + desc_professional = "You are a world class surgeon. You can do surgery anywhere, at any place, only risking minor failures, as long as you are careful enough. You are great at avoiding wound infections during surgery and can perform experimental biotuning procedures with ease." + cost_novice = SKILLCOST_INCREMENT_MAJOR + cost_trained = SKILLCOST_INCREMENT_MAJOR + cost_experienced = SKILLCOST_INCREMENT_MODERATE + cost_professional = SKILLCOST_INCREMENT_MODERATE + +/** + * medicine: medical in general + * + * implementation status: not started + */ +/datum/characteristic_skill/medical/medicine + id = "medicine" + name = "Medicine" + desc = "How well you know the nitty gritty of practicing medicine. Each level gives small boosts to tasks like CPR and equipment operation speed." + desc_untrained = "You probably have to follow a step by step guide to treat anyone well. You get raw medical information from scanners - great if you practice on your own time, terrible in a pinch." + desc_novice = "You have some experience with nursing, or similar. You get slightly more information from medical scanners, as well as when inspecting people visually." + desc_trained = "You are a physician in training. You get more information from scanners, and more information on visual inspection. You can administer medicine with ease." + desc_experienced = "You have had many years under your belt as a doctor. Many afflictions can be diagnosed at a close examination, and the intrinsics of treatment and triage are second nature to you." + desc_professional = "You are a true, tried and tested, doctor. All but the most invasive problems can be determined by you without technological assistance, and you practically have a third sense for injury. Medical speed and efficiency globally increased. You will see visual pings when people are dying of common afflictions." + // extremely harsh scaling as this skill is very useful + cost_novice = SKILLCOST_INCREMENT_MAJOR + cost_trained = SKILLCOST_INCREMENT_MAJOR + cost_experienced = SKILLCOST_INCREMENT_MAJOR + cost_professional = SKILLCOST_INCREMENT_MAJOR + +/** + * chemistry + * + * implementation status: not started + */ +/datum/characteristic_skill/medical/chemistry + id = "chemistry" + name = "Chemistry" + desc = "How well you know chemistry." + desc_untrained = "You don't know much about the nitty gritty of chemistry. Mixing chemicals is slow and tedious and you probably need a book with exact recipes." + desc_novice = "You've had a few lessons in chemistry. Common chemicals are now second nature to you and can be made easily without much problems." + desc_trained = "You have formal, or equivalent, training in chemistry. You can discern some basic things about reagents and mixtures at a glance, and more chemicals are now easily accessible by you." + desc_experienced = "You have a lot of experience with chemicals. Some basic chemicals themselves can be discerned at a glance, and metabolic information can be read directly from some scanners." + desc_professional = "You have been working with chemicals all your life. Nothing gets past your skills of perception, and you are able to go as far as to determine certain active ingrediants from trace signs alone. Chemistry machines now operate at a higher efficiency when used by you, with more product and less waste." + cost_novice = SKILLCOST_INCREMENT_MAJOR + cost_trained = SKILLCOST_INCREMENT_MINOR + cost_experienced = SKILLCOST_INCREMENT_MODERATE + cost_professional = SKILLCOST_INCREMENT_MODERATE diff --git a/code/modules/mob/characteristics/skills/misc.dm b/code/modules/mob/characteristics/skills/misc.dm new file mode 100644 index 00000000000..89688da1edb --- /dev/null +++ b/code/modules/mob/characteristics/skills/misc.dm @@ -0,0 +1,23 @@ +/datum/characteristic_skill/misc + abstract_type = /datum/characteristic_skill/misc + category = "General" + +/** + * Atheletics - TBD + * + * Scaling is harsh due to being a general skill. + * + * Implementation status: Not started + */ +/datum/characteristic_skill/security/athletics + id = "athletics" + name = "Athletics" + desc = "How skilled you are with gymnastics, athletics, as well as general hand-eye coordination." + desc_untrained = "You don't really have any experience with gymnastics or serious fitness." + desc_novice = "You have a bit of recreational exercise. Fall damage is slightly decreased, and some minor tasks are slightly faster." + desc_trained = "You are a recreational athlete. Fall damage is more decreased, and you get up faster from falls. Your metabolism is slightly more efficient." + desc_experienced = "You are practically a professional gymnast. You can withstand minor falls with ease, as long as you are not in heavy equipment, and find yourself to be more resilient to many physical stressors." + max_value = CHARACTER_SKILL_EXPERIENCED + cost_novice = SKILLCOST_INCREMENT_MINOR + cost_trained = SKILLCOST_INCREMENT_MAJOR + cost_experienced = SKILLCOST_INCREMENT_MAJOR diff --git a/code/modules/mob/characteristics/skills/science.dm b/code/modules/mob/characteristics/skills/science.dm new file mode 100644 index 00000000000..9452b55f54e --- /dev/null +++ b/code/modules/mob/characteristics/skills/science.dm @@ -0,0 +1,77 @@ +/datum/characteristic_skill/science + abstract_type = /datum/characteristic_skill/science + category = "Research" + +/** + * R&D / Anomalies / Tech + * + * Implementation status: Not started + */ +/datum/characteristic_skill/science/devices + id = "devices" + name = "Complex Devices" + desc = "Your ability to fabricate, utilize, maintain, and analyze complex machinery." + desc_untrained = "You can follow the on screen instructions of most consoles. Cool, I guess." + desc_novice = "You are a hobbyist gizmo enthusiast. You can probably figure out how to use some machines decently well, even without an interface. Some global speed bonuses are buffed, including lathe speed, to a small extent." + desc_trained = "You are a tinkerer by trade, perhaps even a scientist. Bonuses increased. You now have an easier time figuring out truly alien contraptions." + desc_experienced = "You've been a scientist or engineer for a long time. Complicated mechanisms are now second nature to you, and you can even overclock some things much like an engineer can." + desc_professional = "You are a professional reverse engineer. You can intuit things about alien machinery and technology, and things just work for you." + cost_novice = SKILLCOST_INCREMENT_MODERATE + cost_trained = SKILLCOST_INCREMENT_MODERATE + cost_experienced = SKILLCOST_INCREMENT_MAJOR + cost_professional = SKILLCOST_INCREMENT_MAJOR + +/** + * Robolimbs / Cyborgs / Cybernetics + * + * Implementation status: Not started + */ +/datum/characteristic_skill/science/robotics + id = "robotics" + name = "Robotics" + desc = "Your ability to build and maintain prosthetics, synthetics, and robots in general. Each level gives slight increases in repair rate, as well as fabrication rate for related machinery." + desc_untrained = "Building a robot for you is like trying to put together a replica model brick set with no manual. Or with a manual, in this case. No active bonuses." + desc_novice = "You have had some experience with synthetics and related technologies. Repair efficiency is boosted as well as speed from here on out." + desc_trained = "You are trained to assemble synthetics and robotic platforms with ease. Prosthetic surgeries can be safely done at this level without surgical suites, or skills. Surgeries will be automatically boosted from here on out regardless of surgery skill." + desc_experienced = "You have spent a good deal of your life dealing with synthetics. Prosthetic surgeries are further tuned, and cybernetics you install start out optimized. You can now operate cyborg wiring panels without testing for wires. All parts you construct gain temporary bonuses." + desc_professional = "You are a master roboticist. You can now overclock prosthetics and cybernetics to boost them for their user for hours, or even days at a time. Prosthetics surgeries are second nature to you, regardless of your anatomical knowledge." + cost_novice = SKILLCOST_INCREMENT_MINOR + cost_trained = SKILLCOST_INCREMENT_MINOR + cost_experienced = SKILLCOST_INCREMENT_MAJOR + cost_professional = SKILLCOST_INCREMENT_MAJOR + +/** + * Mechs / Rigsuits + * + * Implementation status: Not started + */ +/datum/characteristic_skill/science/mecha + id = "mecha" + name = "Mechatronics" + desc = "Your ability to pilot and maintain exosuits, as well as powered hardsuits. Each level gives benefits to repair speed and efficiency (diminishing returns)." + desc_untrained = "Piloting a mech is just like a really big hardsuit, right? What even is a hardsuit?" + desc_novice = "You have had some practice with mechatronics. You can probably maintain one without a manual now. Hardsuit deployment speed, hardware installation speed, and mecha enter/exit speeds boosted." + desc_trained = "You are a trained mechatronic engineer, or an experienced operator. Speeds further boosted. Mecha can now natively strafe at full speed with you at the helm (adds automatic face-cursor mode)." + desc_experienced = "You spend a great deal of time working with powered suits. Mecha now suffer less movement cost and recoil with you at the helm. You can salvage more parts out of destroyed mecha." + max_value = CHARACTER_SKILL_EXPERIENCED + cost_novice = SKILLCOST_INCREMENT_MINOR + cost_trained = SKILLCOST_INCREMENT_MODERATE + cost_experienced = SKILLCOST_INCREMENT_MODERATE + +/** + * biology: xenobiology, genetics, nanoswarms, etc + */ +/datum/characteristic_skill/medical/biology + id = "biotech" + name = "Biotechnology" + desc = "How well you understand biology, genetics, xeno-lifeform research, nanoswarms, and anything else relating to weird life sciences." + desc_untrained = "You really shouldn't be anywhere near xenobiology, let alone aliens, without a full biosuit." + desc_novice = "You have had some training with biohazardous protocol. Biosuits now slow you down less. Radsuits now slow you down less." + desc_trained = "You have been working exotic organisms and/or other exotic biotechnologies as an assistant. Genetics scanners are less harmful to you. Slimes deal slightly less damage to you, and find you less threatening." + desc_experienced = "You are a trained xenobiologist, geneticist, or bioengineer. You gain innate resistance to virus spread, and now have a slight global stat boost to resistances. Furthermore, you may analyze the function of certain genes faster, at a random chance, and can read information about slimes with a glance." + desc_professional = "You are a master biologist-engineer. Slimes rarely attack you. Global speed modifier increased. You can now operate xenobio-botanical and genetics machinery at maximum speed." + // pretty busted skill once released + cost_novice = SKILLCOST_INCREMENT_MODERATE + cost_trained = SKILLCOST_INCREMENT_MODERATE + cost_trained = SKILLCOST_INCREMENT_MAJOR + cost_experienced = SKILLCOST_INCREMENT_MAJOR diff --git a/code/modules/mob/characteristics/skills/security.dm b/code/modules/mob/characteristics/skills/security.dm new file mode 100644 index 00000000000..ff6e146f2b4 --- /dev/null +++ b/code/modules/mob/characteristics/skills/security.dm @@ -0,0 +1,41 @@ +/datum/characteristic_skill/security + abstract_type = /datum/characteristic_skill/security + category = "Security" + +/** + * Ranged + * + * Implementation status: Not started + */ +/datum/characteristic_skill/security/ranged + id = "ranged" + name = "Weapons Expertise" + desc = "How skilled you are with assorted weaponry." + desc_untrained = "You know how to hold a gun. Not well, though. That's it." + desc_novice = "You have had some firearms safety. You can reflexively disable safeties when trying to aim and aiming is a bit easier for you. You know how to handle recoil more naturally now." + desc_trained = "You have been using firearms for a while or it is part of your daily job. Your stability has further increased." + desc_experienced = "Using a firearm is second nature to you. Your stability is further increased. You can use some alien weaponry by just studying it." + desc_professional = "You might have a career as an armorer or gunsmith, or just use guns daily. You have no penalties and can wield weapons with minimal recoil." + cost_novice = SKILLCOST_INCREMENT_MINOR + cost_trained = SKILLCOST_INCREMENT_MINOR + cost_experienced = SKILLCOST_INCREMENT_MAJOR + cost_professional = SKILLCOST_INCREMENT_MAJOR + +/** + * Forensics + * + * Implementation status: Not started + */ +/datum/characteristic_skill/security/forensics + id = "forensics" + name = "Forensics" + desc = "How skilled you are at forensic examinations and evidence collection." + desc_untrained = "You have no experience doing forensics whatsoever. You can probably use a scanner to gather some data with guided evidence, but that's it." + desc_novice = "You have been doing forensics for a while. Things are faster for you than before and you can use manual collection methods without a scanner." + desc_trained = "You are trained in forensics. You can efficiently gather data from crime scenes, with or without technological assistance." + desc_experienced = "You have a career in forensics. You can efficiently determine some sources of evidence with just a glance." + desc_professional = "You are a master of forensics. A mere glance is enough to tell you about many kinds of data about something, whether it be be at people or objects around you." + cost_novice = SKILLCOST_INCREMENT_MINOR + cost_trained = SKILLCOST_INCREMENT_MINOR + cost_experienced = SKILLCOST_INCREMENT_MAJOR + cost_professional = SKILLCOST_INCREMENT_MAJOR diff --git a/code/modules/mob/characteristics/skills/service.dm b/code/modules/mob/characteristics/skills/service.dm new file mode 100644 index 00000000000..b7859041fdd --- /dev/null +++ b/code/modules/mob/characteristics/skills/service.dm @@ -0,0 +1,41 @@ +/datum/characteristic_skill/service + abstract_type = /datum/characteristic_skill/service + category = "Service" + +/** + * Cooking + * + * Implementation status: Not started + */ +/datum/characteristic_skill/service/cooking + id = "cooking" + name = "Cooking" + desc = "How good you are at cooking." + desc_untrained = "You will probably need a cookbook to do anything." + desc_novice = "You have had some practice cooking. Actions are inherently faster for you now." + desc_trained = "You have been cooking for a while, hobby or otherwise. You can now see some nutritional information at a glance." + desc_experienced = "You are a professionally trained chef. You now gain double outputs from some recipes at random." + desc_professional = "You now have a higher chance of getting doubled outputs." + cost_novice = SKILLCOST_INCREMENT_NEGLIGIBLE + cost_trained = SKILLCOST_INCREMENT_NEGLIGIBLE + cost_experienced = SKILLCOST_INCREMENT_MINOR + cost_professional = SKILLCOST_INCREMENT_MINOR + +/** + * Botany + * + * Implementation status: Not started + */ +/datum/characteristic_skill/service/botany + id = "botany" + name = "Botany" + desc = "How good you are at growing plants." + desc_untrained = "You have no experience growing plants." + desc_novice = "You have had some practice growing plants. Actions are inherently faster for you now, and you can see some plant stats by just looking at them." + desc_trained = "You've been growing or gardening for a while. More stats are now visible, and fertilizing/watering plants is now more efficient." + desc_experienced = "You are a professional grower, or a hydroponics worker. Plants tend to grow faster when tended to by you." + desc_professional = "You have had extensive research in hydroponics. You now sometimes gain additional yield during harvest, and can determine some plant genes with ease." + cost_novice = SKILLCOST_INCREMENT_NEGLIGIBLE + cost_trained = SKILLCOST_INCREMENT_NEGLIGIBLE + cost_experienced = SKILLCOST_INCREMENT_MINOR + cost_professional = SKILLCOST_INCREMENT_MINOR diff --git a/code/modules/mob/characteristics/skills/voidcraft.dm b/code/modules/mob/characteristics/skills/voidcraft.dm new file mode 100644 index 00000000000..1b003a3b071 --- /dev/null +++ b/code/modules/mob/characteristics/skills/voidcraft.dm @@ -0,0 +1,41 @@ +/datum/characteristic_skill/voidcraft + abstract_type = /datum/characteristic_skill/voidcraft + category = "General" + +/** + * EVA + * + * implementation status: not started + */ +/datum/characteristic_skill/voidcraft/eva + id = "eva" + name = "EVA" + desc = "How well you can perform EVA." + desc_untrained = "You don't really go into space. While you can handle it, it probably is very uneasy for you." + desc_novice = "You have had some basic EVA training. You now slip less often at high speeds, and can operate hardsuits a bit faster." + desc_trained = "You have had a decent amount of EVA training. You now move faster in magboots, and always see your jetpack gauge. Hardsuits are now faster." + desc_experienced = "You have worked in space for long periods of time. Jetpacks and oxygen supplies last longer than you. Hardsuits are now faster." + desc_professional = "Space is second nature to you. EVA equipment bonuses are maximized, and you inherently have the effects of magboots as long as there is support near you." + cost_novice = SKILLCOST_INCREMENT_MINOR + cost_trained = SKILLCOST_INCREMENT_MINOR + cost_experienced = SKILLCOST_INCREMENT_MINOR + cost_professional = SKILLCOST_INCREMENT_MAJOR + +/** + * piloting + * + * implementation status: not started + */ +/datum/characteristic_skill/voidcraft/piloting + id = "pilot" + name = "Piloting" + desc = "How well you can pilot voidcraft of various function." + desc_untrained = "You don't really fly ships. The only way you manage to pilot is through modern automation and guided instruction." + desc_novice = "You have had some practice piloting. You gain a small increase in control and a decrease in response latency." + desc_trained = "You are a trained pilot. You gain more control, and can dodge meteors at low speeds, while piloting small craft. Manual landing is now far faster." + desc_experienced = "You have been piloting for a while. You can now dodge meteors at faster speeds, or for larger craft. You gain a small boost in engine performance as well. Some ship components can be analyzed by you with a glance." + desc_professional = "You are a professional pilot. You gain more boosts in engine performance and control, and can dock ships with ease." + cost_novice = SKILLCOST_INCREMENT_MINOR + cost_trained = SKILLCOST_INCREMENT_MINOR + cost_experienced = SKILLCOST_INCREMENT_MAJOR + cost_professional = SKILLCOST_INCREMENT_MAJOR diff --git a/code/modules/mob/characteristics/stat.dm b/code/modules/mob/characteristics/stat.dm new file mode 100644 index 00000000000..80e784cf083 --- /dev/null +++ b/code/modules/mob/characteristics/stat.dm @@ -0,0 +1,62 @@ +GLOBAL_LIST_INIT(characteristics_stats, _create_characteristics_stats()) + +/proc/_create_characteristics_stats() + . = list() + for(var/datum/characteristic_stat/stat in subtypesof(/datum/characteristic_stat)) + if(is_abstract(stat)) + continue + . = new stat + if(isnull(stat.id)) + stack_trace("null id on [stat.type]") + continue + if(.[stat.id]) + stack_trace("collision on id [stat.id] between types [stat.type] and [.[stat.id]:type]") + continue + .[stat.id] = stat + +/** + * gets a stat datum + * + * use typepaths whenever possible for compile time! + */ +/proc/resolve_characteristics_stat(datum/characteristic_stat/typepath_or_id) + RETURN_TYPE(/datum/characteristic_stat) + return GLOB.characteristics_stats[ispath(typepath_or_id)? initial(typepath_or_id.id) : typepath_or_id] + +/** + * stats - basically raw skills that can theoretically hold anything + * you usually don't want players to be able to touch these or minmax them too hard + * use skills whenever possible + * + * stats are null when unset, and baseline when characteristics are disabled + */ +/datum/characteristic_stat + abstract_type = /datum/characteristic_stat + /// unique id + var/id + /// name + var/name = "ERROR" + /// description + var/desc = "An unknown stat. Someone needs to change this." + /// cateogry - just a string, no defines for now, surely no one will typo.. + var/category = "General" + /// datatype + var/datatype = CHARACTER_STAT_UNKNOWN + /// default value when characteristics are disabled + var/baseline_value + +/** + * get the greater value. this is automatic for numbers, less so for everything else. + * + * if number, default handling without a proc override is return greater + * if bool, default handling is returning TRUE if either is true + * else, returns first value. + */ +/datum/characteristic_stat/proc/greater_value(a, b) + switch(datatype) + if(CHARACTER_STAT_NUMERIC) + return a > b? a : b + if(CHARACTER_STAT_BOOL) + return a || b + else + return a diff --git a/code/modules/mob/characteristics/stats/gaming.dm b/code/modules/mob/characteristics/stats/gaming.dm new file mode 100644 index 00000000000..9755607dc53 --- /dev/null +++ b/code/modules/mob/characteristics/stats/gaming.dm @@ -0,0 +1,5 @@ +/datum/characteristic_stat/gaming + name = "Gaming" + desc = "How good you are at playing games. Higher values make arcade games go brrr." + datatype = CHARACTER_STAT_NUMERIC + baseline_value = 0 diff --git a/code/modules/mob/characteristics/talent.dm b/code/modules/mob/characteristics/talent.dm new file mode 100644 index 00000000000..519b4cd8a7a --- /dev/null +++ b/code/modules/mob/characteristics/talent.dm @@ -0,0 +1,70 @@ +GLOBAL_LIST_INIT(characteristics_talents, _create_characteristics_talents()) + +/proc/_create_characteristics_talents() + . = list() + for(var/datum/characteristic_talent/talent in subtypesof(/datum/characteristic_talent)) + if(is_abstract(talent)) + continue + . = new talent + if(isnull(talent.id)) + stack_trace("null id on [talent.type]") + continue + if(.[talent.id]) + stack_trace("collision on id [talent.id] between types [talent.type] and [.[talent.id]:type]") + continue + .[talent.id] = talent + +/** + * gets a talent datum + * + * use typepaths whenever possible for compile time! + */ +/proc/resolve_characteristics_talent(datum/characteristic_talent/typepath_or_id) + RETURN_TYPE(/datum/characteristic_talent) + return GLOB.characteristics_talents[ispath(typepath_or_id)? initial(typepath_or_id.id) : typepath_or_id] + +/** + * barotrauma-like talents + * these are **global singletons** to better do things like synchronization + * make sure to gc your stuff properly on Destroy(). + * + * talents default to not being there when characteristics are disabled + */ +/datum/characteristic_talent + abstract_type = /datum/characteristic_talent + /// unique id + var/id + /// name + var/name = "ERROR" + /// desc + var/desc = "An unknown talent. Someone needs to set this." + +/** + * called when we're put into a mind + * attach for mobs is called separately by mind + */ +/datum/characteristic_talent/proc/gain(datum/mind/M, metadata) + +/** + * called when we're yanked out of a mind + * detach for mobs is called separately by mind + */ +/datum/characteristic_talent/proc/lose(datum/mind/M, metadata) + +/** + * called when we're attaching to a mob + */ +/datum/characteristic_talent/proc/attach(mob/M, metadata) + +/** + * called when we're detaching from a mob + */ +/datum/characteristic_talent/proc/detach(mob/M, metadata) + +/** + * generates initial metadata for when we're being added to a holder + * + * @return anything that evals to true in logical expressions; defaults to TRUE if unimplemented + */ +/datum/characteristic_talent/proc/metadata(...) + return TRUE diff --git a/code/modules/mob/characteristics/talents/placeholder.dm b/code/modules/mob/characteristics/talents/placeholder.dm new file mode 100644 index 00000000000..5790b56417c --- /dev/null +++ b/code/modules/mob/characteristics/talents/placeholder.dm @@ -0,0 +1 @@ +// no talents exist yet diff --git a/code/modules/mob/characteristics/ui.dm b/code/modules/mob/characteristics/ui.dm new file mode 100644 index 00000000000..a9780c089b4 --- /dev/null +++ b/code/modules/mob/characteristics/ui.dm @@ -0,0 +1,11 @@ +/datum/characteristics_holder/ui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + +/datum/characteristics_holder/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + +/datum/characteristics_holder/ui_static_data(mob/user) + . = ..() + +/datum/characteristics_holder/ui_data(mob/user, datum/tgui/ui, datum/ui_state/state) + . = ..() + diff --git a/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm b/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm index 8f2fc6369b1..af1b89e491b 100644 --- a/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm +++ b/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm @@ -89,9 +89,9 @@ if(to_wear_id_type) var/obj/item/card/id/W = new to_wear_id_type(src) W.name = "[real_name]'s ID Card" - var/datum/job/jobdatum - for(var/jobtype in typesof(/datum/job)) - var/datum/job/J = new jobtype + var/datum/role/job/jobdatum + for(var/jobtype in typesof(/datum/role/job)) + var/datum/role/job/J = new jobtype if(J.title == to_wear_id_job) jobdatum = J break diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 3517ec2c2c4..787c91de433 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -682,23 +682,18 @@ default behaviour is: /mob/living/proc/UpdateDamageIcon() return - /mob/living/proc/Examine_OOC() set name = "Examine Meta-Info (OOC)" set category = "OOC" set src in view() - // Making it so SSD people have prefs with fallback to original style. - if(config_legacy.allow_Metadata) - if(ooc_notes) - to_chat(usr, "[src]'s Metainfo:
[ooc_notes]") - else if(client) - to_chat(usr, "[src]'s Metainfo:
[client.prefs.metadata]") - else - to_chat(usr, "[src] does not have any stored infomation!") - else - to_chat(usr, "OOC Metadata is not supported by this server!") - return + // Making it so SSD people have prefs with fallback to original style. + if(ooc_notes) + to_chat(usr, "[src]'s Metainfo:
[ooc_notes]") + else if(client) + to_chat(usr, "[src]'s Metainfo:
[client.prefs.metadata]") + else + to_chat(usr, "[src] does not have any stored infomation!") /mob/living/proc/handle_footstep(turf/T) return FALSE diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 2eec828a346..ef7007d75cb 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -504,8 +504,8 @@ // Try harder to find a key to use if(!keytouse && key) keytouse = ckey(key) - else if(!keytouse && mind?.key) - keytouse = ckey(mind.key) + else if(!keytouse && mind?.ckey) + keytouse = mind.ckey GLOB.respawn_timers[keytouse] = world.time + time diff --git a/code/modules/mob/new_player/join_menu.dm b/code/modules/mob/new_player/join_menu.dm index 5517fe5eb75..4a6f499f6eb 100644 --- a/code/modules/mob/new_player/join_menu.dm +++ b/code/modules/mob/new_player/join_menu.dm @@ -34,9 +34,9 @@ GLOBAL_DATUM_INIT(join_menu, /datum/join_menu, new) data["jobs"] = jobs // collect - var/list/datum/job/eligible = list() + var/list/datum/role/job/eligible = list() for(var/title in SSjob.name_occupations) - var/datum/job/J = SSjob.name_occupations[title] + var/datum/role/job/J = SSjob.name_occupations[title] if(!(J.join_types & JOB_LATEJOIN)) continue if(!IsJobAvailable(J, N)) @@ -44,7 +44,7 @@ GLOBAL_DATUM_INIT(join_menu, /datum/join_menu, new) eligible += J // make - for(var/datum/job/J as anything in eligible) // already type filtered + for(var/datum/role/job/J as anything in eligible) // already type filtered // faction var/list/faction if(!jobs[J.faction]) @@ -75,7 +75,7 @@ GLOBAL_DATUM_INIT(join_menu, /datum/join_menu, new) var/list/ghostroles = list() data["ghostroles"] = ghostroles for(var/id in GLOB.ghostroles) - var/datum/ghostrole/R = GLOB.ghostroles[id] + var/datum/role/ghostrole/R = GLOB.ghostroles[id] // can't afford runtime here if(!istype(R) || !IsGhostroleAvailable(R, N)) continue @@ -133,28 +133,28 @@ GLOBAL_DATUM_INIT(join_menu, /datum/join_menu, new) * checks if job is available * if not, it shouldn't even show */ -/datum/join_menu/proc/IsJobAvailable(datum/job/J, mob/new_player/N) +/datum/join_menu/proc/IsJobAvailable(datum/role/job/J, mob/new_player/N) return J.check_client_availability_one(N.client, TRUE, TRUE) == ROLE_AVAILABLE /** * checks if ghostrole is available * if not, it shouldn't even show */ -/datum/join_menu/proc/IsGhostroleAvailable(datum/ghostrole/G, mob/new_player/N) +/datum/join_menu/proc/IsGhostroleAvailable(datum/role/ghostrole/G, mob/new_player/N) return G.AllowSpawn(N.client) /** * return effective title - used for alt titles - JOBS ONLY, not ghostroles */ -/datum/join_menu/proc/EffectiveTitle(datum/job/J, mob/new_player/N) +/datum/join_menu/proc/EffectiveTitle(datum/role/job/J, mob/new_player/N) return N.client.prefs.get_job_alt_title_name(J) || J.title /** * returns effective desc - used for alt titles - JOBS ONLY, not ghostroles */ -/datum/join_menu/proc/EffectiveDesc(datum/job/J, mob/new_player/N) +/datum/join_menu/proc/EffectiveDesc(datum/role/job/J, mob/new_player/N) var/title = N.client.prefs.get_job_alt_title_name(J) - var/datum/alt_title/T = J.alt_titles?[title] + var/datum/prototype/alt_title/T = J.alt_titles?[title] return isnull(T)? J.desc : (initial(T.title_blurb) || J.desc) /datum/join_menu/proc/QueueStatus(mob/new_player/N) @@ -209,14 +209,14 @@ GLOBAL_DATUM_INIT(join_menu, /datum/join_menu, new) if(!config_legacy.enter_allowed) to_chat(usr, SPAN_NOTICE("There is an administrative lock on entering the game.")) return - var/datum/job/J = SSjob.job_by_id(id) + var/datum/role/job/J = SSjob.job_by_id(id) if(!J) to_chat(usr, SPAN_WARNING("Failed to find job [id].")) return to_chat(usr, SPAN_NOTICE("Attempting to latespawn as [id] ([J.title]).")) N.AttemptLateSpawn(J.title) // todo: remove shim if("ghostrole") - var/datum/ghostrole/R = get_ghostrole_datum(id) + var/datum/role/ghostrole/R = get_ghostrole_datum(id) if(!R) to_chat(usr, SPAN_WARNING("Failed to find ghostrole [R]")) return diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 4163b2ba68f..322a052bbfa 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -232,6 +232,12 @@ if(href_list["ready"]) if(!SSticker || SSticker.current_state <= GAME_STATE_PREGAME) // Make sure we don't ready up after the round has started + var/list/warnings = list() + client.prefs.spawn_checks(PREF_COPY_TO_FOR_ROUNDSTART, warnings = warnings) + if(length(warnings)) + to_chat(src, "

--- Character Setup Warnings---


-    [jointext(warnings, "
-    ")]
") + if(tgui_alert(src, "You do not seem to have your preferences set properly. Are you sure you wish to ready up? Check the chat panel for details.", "Spawn Checks", list("Yes", "No")) != "Yes") + return ready = text2num(href_list["ready"]) else ready = 0 @@ -468,7 +474,7 @@ if(!config_legacy.enter_allowed) to_chat(usr, "There is an administrative lock on entering the game!") return 0 - var/datum/job/J = SSjob.job_by_title(rank) + var/datum/role/job/J = SSjob.job_by_title(rank) var/reason if((reason = J.check_client_availability_one(client)) != ROLE_AVAILABLE) to_chat(src, SPAN_WARNING("[rank] is not available: [J.get_availability_reason(client, reason)]")) @@ -476,9 +482,14 @@ if(!spawn_checks_vr()) return FALSE var/list/errors = list() - if(!client.prefs.spawn_checks(PREF_COPY_TO_FOR_LATEJOIN, errors)) + var/list/warnings = list() + if(!client.prefs.spawn_checks(PREF_COPY_TO_FOR_LATEJOIN, errors, warnings)) to_chat(src, SPAN_WARNING("An error has occured while trying to spawn you in:
[errors.Join("
")]")) return FALSE + if(length(warnings)) + to_chat(src, "

--- Character Setup Warnings---


-    [jointext(warnings, "
-    ")]
") + if(tgui_alert(src, "You do not seem to have your preferences set properly. Are you sure you wish to join the game?", "Spawn Checks", list("Yes", "No")) != "Yes") + return //Find our spawning point. var/list/join_props = SSjob.LateSpawn(client, rank) @@ -558,6 +569,7 @@ if(!spawn_checks_vr()) return FALSE var/list/errors = list() + // warnings ignored for now. if(!client.prefs.spawn_checks(PREF_COPY_TO_FOR_ROUNDSTART, errors)) to_chat(src, SPAN_WARNING("An error has occured while trying to spawn you in:
[errors.Join("
")]")) return FALSE @@ -690,16 +702,6 @@ /mob/new_player/proc/spawn_checks_vr() //Custom spawn checks. var/pass = TRUE - //No Flavor Text - if (config_legacy.require_flavor && client && client.prefs && client.prefs.flavor_texts && !client.prefs.flavor_texts["general"]) - to_chat(src,"Please set your general flavor text to give a basic description of your character. Set it using the 'Set Flavor text' button on the 'General' tab in character setup, and choosing 'General' category.") - pass = FALSE - - //No OOC notes - if (config_legacy.allow_Metadata && client && client.prefs && (isnull(client.prefs.metadata) || length(client.prefs.metadata) < 15)) - to_chat(src,"Please set informative OOC notes related to ERP preferences. Set them using the 'OOC Notes' button on the 'General' tab in character setup.") - pass = FALSE - //Are they on the VERBOTEN LIST? if (prevent_respawns.Find(client.prefs.real_name)) to_chat(src,"You've already quit the round as this character. You can't go back now that you've free'd your job slot. Play another character, or wait for the next round.") diff --git a/code/modules/mob/new_player/skill.dm b/code/modules/mob/new_player/skill.dm index c076d22bf2e..91addb4739b 100644 --- a/code/modules/mob/new_player/skill.dm +++ b/code/modules/mob/new_player/skill.dm @@ -5,12 +5,12 @@ var/global/const SKILL_EXPERT = 3 SKILL_PROF = 4 -/datum/skill/var - ID = "none" // ID of the skill, used in code - name = "None" // Name of the skill - desc = "Placeholder skill" // Detailed description of the skill - field = "Misc" // The field under which the skill will be listed - secondary = 0 // Secondary skills only have two levels and cost significantly less +/datum/skill + var/ID = "none" // ID of the skill, used in code + var/name = "None" // Name of the skill + var/desc = "Placeholder skill" // Detailed description of the skill + var/field = "Misc" // The field under which the skill will be listed + var/secondary = 0 // Secondary skills only have two levels and cost significantly less var/global/list/SKILLS = null var/list/SKILL_ENGINEER = list("field" = "Engineering", "EVA" = SKILL_BASIC, "construction" = SKILL_ADEPT, "electrical" = SKILL_BASIC, "engines" = SKILL_ADEPT) @@ -24,18 +24,6 @@ var/global/list/SKILL_PRE = list("Engineer" = SKILL_ENGINEER, "Roboticist" = SKI name = "Command" desc = "Your ability to manage and commandeer other crew members." -/datum/skill/combat - ID = "combat" - name = "Close Combat" - desc = "This skill describes your training in hand-to-hand combat or melee weapon usage. While expertise in this area is rare in the era of firearms, experts still exist among athletes." - field = "Security" - -/datum/skill/weapons - ID = "weapons" - name = "Weapons Expertise" - desc = "This skill describes your expertise with and knowledge of weapons. A low level in this skill implies knowledge of simple weapons, for example tazers and flashes. A high level in this skill implies knowledge of complex weapons, such as grenades, riot shields, pulse rifles or bombs. A low level in this skill is typical for security officers, a high level of this skill is typical for special agents and soldiers." - field = "Security" - /datum/skill/EVA ID = "EVA" name = "Extra-vehicular activity" @@ -43,12 +31,6 @@ var/global/list/SKILL_PRE = list("Engineer" = SKILL_ENGINEER, "Roboticist" = SKI field = "Engineering" secondary = 1 -/datum/skill/forensics - ID = "forensics" - name = "Forensics" - desc = "Describes your skill at performing forensic examinations and identifying vital evidence. Does not cover analytical abilities, and as such isn't the only indicator for your investigation skill. Note that in order to perform autopsy, the surgery skill is also required." - field = "Security" - /datum/skill/construction ID = "construction" name = "Construction" diff --git a/code/modules/mob/skillset.dm b/code/modules/mob/skillset.dm deleted file mode 100644 index c43f866edfd..00000000000 --- a/code/modules/mob/skillset.dm +++ /dev/null @@ -1,11 +0,0 @@ -// We don't actually have a skills system, so return max skill for everything. -/mob/proc/get_skill_value(skill_path) - return SKILL_EXPERT - -// A generic way of modifying success probabilities via skill values. Higher factor means skills have more effect. fail_chance is the chance at SKILL_NONE. -/mob/proc/skill_fail_chance(skill_path, fail_chance, no_more_fail = SKILL_EXPERT, factor = 1) - var/points = get_skill_value(skill_path) - if(points >= no_more_fail) - return 0 - else - return fail_chance * 2 ** (factor*(SKILL_BASIC - points)) diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 60c484374fe..8b05661d4fe 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -81,7 +81,7 @@ O.add_language(LANGUAGE_ROOTLOCAL, 1) if(move) - var/obj/landmark/spawnpoint/S = SSjob.get_latejoin_spawnpoint(job_path = /datum/job/station/ai) + var/obj/landmark/spawnpoint/S = SSjob.get_latejoin_spawnpoint(job_path = /datum/role/job/station/ai) O.forceMove(S.GetSpawnLoc()) S.OnSpawn(O) diff --git a/code/modules/modular_computers/file_system/programs/command/card.dm b/code/modules/modular_computers/file_system/programs/command/card.dm index 25119cd0af0..23c045fce43 100644 --- a/code/modules/modular_computers/file_system/programs/command/card.dm +++ b/code/modules/modular_computers/file_system/programs/command/card.dm @@ -194,9 +194,9 @@ if(module.is_centcom) access = get_centcom_access(t1) else - var/datum/job/jobdatum - for(var/jobtype in typesof(/datum/job)) - var/datum/job/J = new jobtype + var/datum/role/job/jobdatum + for(var/jobtype in typesof(/datum/role/job)) + var/datum/role/job/J = new jobtype if(ckey(J.title) == ckey(t1)) jobdatum = J break diff --git a/code/modules/organs/internal/brain.dm b/code/modules/organs/internal/brain.dm index 987f2e5adde..f07473590cc 100644 --- a/code/modules/organs/internal/brain.dm +++ b/code/modules/organs/internal/brain.dm @@ -133,7 +133,7 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain) if(brainmob.mind) brainmob.mind.transfer_to(target) else - target.key = brainmob.key + target.ckey = brainmob.ckey ..() /obj/item/organ/internal/brain/proc/get_control_efficiency() @@ -223,7 +223,7 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain) return FALSE /// Somebody is using that mind. if(clonemind.active) - if(ckey(clonemind.key) != R.ckey) + if(clonemind.ckey != R.ckey) return FALSE else for(var/mob/observer/dead/G in GLOB.player_list) diff --git a/code/modules/overmap/disperser/disperser_console.dm b/code/modules/overmap/disperser/disperser_console.dm index bb63bcb0e36..302a4cd5826 100644 --- a/code/modules/overmap/disperser/disperser_console.dm +++ b/code/modules/overmap/disperser/disperser_console.dm @@ -150,7 +150,7 @@ data["range"] = range data["next_shot"] = round(get_next_shot_seconds()) data["nopower"] = !data["faillink"] && (!front.powered() || !middle.powered() || !back.powered()) - data["skill"] = user.get_skill_value(core_skill) > skill_offset + data["skill"] = TRUE // todo: skills var/charge = "UNKNOWN ERROR" if(get_charge_type() == OVERMAP_WEAKNESS_NONE) @@ -183,7 +183,8 @@ . = TRUE if("skill_calibration") - for(var/i = 1 to min(caldigit, usr.get_skill_value(core_skill) - skill_offset)) + // todo: skills + for(var/i in 1 to 2) calibration[i] = calexpected[i] . = TRUE diff --git a/code/modules/overmap/overmap_shuttle.dm b/code/modules/overmap/overmap_shuttle.dm index 46caf5d7938..cd2a6d70d7a 100644 --- a/code/modules/overmap/overmap_shuttle.dm +++ b/code/modules/overmap/overmap_shuttle.dm @@ -9,8 +9,6 @@ var/obj/effect/overmap/visitable/ship/landable/myship //my overmap ship object category = /datum/shuttle/autodock/overmap - var/skill_needed = SKILL_BASIC - var/operator_skill = SKILL_BASIC /datum/shuttle/autodock/overmap/New(var/_name, var/obj/effect/shuttle_landmark/start_waypoint) ..(_name, start_waypoint) @@ -52,13 +50,6 @@ /datum/shuttle/autodock/overmap/can_force() return ..() && can_go() -/datum/shuttle/autodock/overmap/process_launch() - if(prob(10*max(0, skill_needed - operator_skill))) - var/places = get_possible_destinations() - var/place = pick(places) - set_destination(places[place]) - ..() - /datum/shuttle/autodock/overmap/proc/set_destination(var/obj/effect/shuttle_landmark/A) if(A != current_location) next_location = A diff --git a/code/modules/overmap/ships/computers/helm.dm b/code/modules/overmap/ships/computers/helm.dm index 63a6c9cd761..cc3a0baddb9 100644 --- a/code/modules/overmap/ships/computers/helm.dm +++ b/code/modules/overmap/ships/computers/helm.dm @@ -83,7 +83,6 @@ GLOBAL_LIST_EMPTY(all_waypoints) // All other cases, move toward direction else if(speed + acceleration <= speedlimit) linked.accelerate(direction, accellimit) - linked.operator_skill = null // If this is on you can't dodge meteors return /obj/machinery/computer/ship/helm/ui_interact(mob/user, datum/tgui/ui) @@ -228,8 +227,6 @@ GLOBAL_LIST_EMPTY(all_waypoints) if("move") var/ndir = text2num(params["dir"]) - if(prob(usr.skill_fail_chance(/datum/skill/pilot, 50, linked.skill_needed, factor = 1))) - ndir = turn(ndir,pick(90,-90)) linked.relaymove(usr, ndir, accellimit) . = TRUE diff --git a/code/modules/overmap/ships/computers/shuttle.dm b/code/modules/overmap/ships/computers/shuttle.dm index 5a86c5cc6ef..8141287349f 100644 --- a/code/modules/overmap/ships/computers/shuttle.dm +++ b/code/modules/overmap/ships/computers/shuttle.dm @@ -34,10 +34,6 @@ to_chat(usr, "Unable to establish link with the shuttle.") return TRUE - if(ismob(usr)) - var/mob/user = usr - shuttle.operator_skill = user.get_skill_value(/datum/skill/pilot) - switch(action) if("pick") var/list/possible_d = shuttle.get_possible_destinations() diff --git a/code/modules/overmap/ships/ship.dm b/code/modules/overmap/ships/ship.dm index 2622fec68c7..7e9b357db60 100644 --- a/code/modules/overmap/ships/ship.dm +++ b/code/modules/overmap/ships/ship.dm @@ -78,7 +78,6 @@ //? todo why tf is this relaymove /obj/effect/overmap/visitable/ship/relaymove(mob/user, direction, accel_limit) accelerate(direction, accel_limit) - operator_skill = user.get_skill_value(/datum/skill/pilot) /obj/effect/overmap/visitable/ship/get_scan_data(mob/user) . = ..() @@ -285,9 +284,6 @@ if(!SSshuttle.overmap_halted) halted = 0 -/obj/effect/overmap/visitable/ship/proc/get_helm_skill() // Delete this mover operator skill to overmap obj - return operator_skill - /obj/effect/overmap/visitable/ship/populate_sector_objects() ..() for(var/obj/machinery/computer/ship/S in GLOB.machines) diff --git a/code/modules/persistence/persistence.dm b/code/modules/persistence/persistence.dm index 050348378b3..d2d343a0f8a 100644 --- a/code/modules/persistence/persistence.dm +++ b/code/modules/persistence/persistence.dm @@ -1,26 +1,3 @@ -/* -* Returns a byond list that can be passed to the "deserialize" proc -* to bring a new instance of this atom to its original state -* -* If we want to store this info, we can pass it to `json_encode` or some other -* interface that suits our fancy, to make it into an easily-handled string -*/ -/datum/proc/serialize() - var/data = list("type" = "[type]") - return data - -/* -* This is given the byond list from above, to bring this atom to the state -* described in the list. -* This will be called after `New` but before `initialize`, so linking and stuff -* would probably be handled in `initialize` -* -* Also, this should only be called by `list_to_object` in persistence.dm - at least -* with current plans - that way it can actually initialize the type from the list -*/ -/datum/proc/deserialize(var/list/data) - return - /atom // This var isn't actually used for anything, but is present so that // DM's map reader doesn't forfeit on reading a JSON-serialized map diff --git a/code/modules/preferences/apply.dm b/code/modules/preferences/apply.dm index 1644093aed7..3da0f38acf3 100644 --- a/code/modules/preferences/apply.dm +++ b/code/modules/preferences/apply.dm @@ -1,7 +1,7 @@ -/datum/preferences/proc/spawn_checks(flags, list/errors) +/datum/preferences/proc/spawn_checks(flags, list/errors, list/warnings) . = TRUE for(var/datum/category_group/player_setup_category/category in player_setup.categories) - if(!category.spawn_checks(src, flags, errors)) + if(!category.spawn_checks(src, flags, errors, warnings)) . = FALSE // todo: at some point we should support nonhuman copy to's better. diff --git a/code/modules/preferences/migration.dm b/code/modules/preferences/migration.dm index 6552f07937d..935ccc4e9fd 100644 --- a/code/modules/preferences/migration.dm +++ b/code/modules/preferences/migration.dm @@ -63,7 +63,7 @@ var/list/assembled_titles = list() if(!islist(player_alt_titles)) player_alt_titles = list() - for(var/datum/job/J as anything in SSjob.occupations) + for(var/datum/role/job/J as anything in SSjob.occupations) switch(J.department_flag) if(CIVILIAN) if(job_civilian_high & J.flag) diff --git a/code/modules/preferences/preference_setup/background/_background.dm b/code/modules/preferences/preference_setup/background/_background.dm index 9577363a912..8698b50120e 100644 --- a/code/modules/preferences/preference_setup/background/_background.dm +++ b/code/modules/preferences/preference_setup/background/_background.dm @@ -16,26 +16,25 @@ sanitize_preference(/datum/category_item/player_setup_item/background/religion) // do language last sanitize_preference(/datum/category_item/player_setup_item/background/language) + // lastly, do general job titles after + sanitize_preference(/datum/category_item/player_setup_item/occupation/alt_titles) -/datum/preferences/proc/get_background_lore_datums() +/datum/preferences/proc/all_background_datums() + return list( + lore_faction_datum(), + lore_citizenship_datum(), + lore_origin_datum(), + lore_religion_datum(), + ) + +/datum/preferences/proc/all_background_ids() . = list() - var/datum/lore/character_background/bglore - bglore = SScharacters.resolve_citizenship(get_preference(/datum/category_item/player_setup_item/background/citizenship)) - if(bglore) - . += bglore - bglore = SScharacters.resolve_faction(get_preference(/datum/category_item/player_setup_item/background/faction)) - if(bglore) - . += bglore - bglore = SScharacters.resolve_origin(get_preference(/datum/category_item/player_setup_item/background/origin)) - if(bglore) - . += bglore - bglore = SScharacters.resolve_religion(get_preference(/datum/category_item/player_setup_item/background/religion)) - if(bglore) - . += bglore + for(var/datum/lore/character_background/bg as anything in all_background_datums()) + . += bg.id /datum/preferences/proc/tally_background_economic_factor() . = 1 - for(var/datum/lore/character_background/bglore as anything in get_background_lore_datums()) + for(var/datum/lore/character_background/bglore as anything in all_background_datums()) . *= bglore.economy_payscale // todo: character species when *necessary* var/datum/species/S = real_species_datum() diff --git a/code/modules/preferences/preference_setup/background/citizenship.dm b/code/modules/preferences/preference_setup/background/citizenship.dm index ba6dc6624a7..f7794bdace0 100644 --- a/code/modules/preferences/preference_setup/background/citizenship.dm +++ b/code/modules/preferences/preference_setup/background/citizenship.dm @@ -6,9 +6,17 @@ /datum/category_item/player_setup_item/background/citizenship/content(datum/preferences/prefs, mob/user, data) . = list() var/list/datum/lore/character_background/citizenship/available = SScharacters.available_citizenships(prefs.character_species_id()) + var/list/categories = list() + for(var/datum/lore/character_background/citizenship/O as anything in available) + LAZYADD(categories[O.category], O) var/datum/lore/character_background/citizenship/current = SScharacters.resolve_citizenship(data) . += "
" . += "Citizenship
" + if(length(categories) > 1) + for(var/category in categories) + . += (category == current.category)? "[category] " : href_simple(prefs, "category", "[category]", category) + . += " " + . += "
" for(var/datum/lore/character_background/citizenship/O in available) if(O == current) . += "[O.name]" @@ -33,6 +41,16 @@ write(prefs, id) prefs.sanitize_background_lore() // update return PREFERENCES_REFRESH + if("category") + var/cat = params["category"] + var/list/datum/lore/character_background/citizenship/citizenships = SScharacters.available_citizenships(prefs.character_species_id(), cat) + if(!length(citizenships)) + to_chat(user, SPAN_WARNING("No citizenships in that category have been found; this might be an error.")) + return PREFERENCES_NOACTION + var/datum/lore/character_background/citizenship/first = citizenships[1] + write(prefs, first.id) + prefs.sanitize_background_lore() // update + return PREFERENCES_REFRESH return ..() /datum/category_item/player_setup_item/background/citizenship/filter_data(datum/preferences/prefs, data, list/errors) @@ -48,7 +66,7 @@ M.add_language(id) return TRUE -/datum/category_item/player_setup_item/background/citizenship/spawn_checks(datum/preferences/prefs, data, flags, list/errors) +/datum/category_item/player_setup_item/background/citizenship/spawn_checks(datum/preferences/prefs, data, flags, list/errors, list/warnings) var/datum/lore/character_background/citizenship/current = SScharacters.resolve_citizenship(data) if(!current?.check_species_id(prefs.character_species_id())) errors?.Add("Invalid citizenship for your current species.") @@ -68,4 +86,5 @@ return get_character_data(CHARACTER_DATA_CITIZENSHIP) /datum/preferences/proc/lore_citizenship_datum() + RETURN_TYPE(/datum/lore/character_background/citizenship) return SScharacters.resolve_citizenship(lore_citizenship_id()) diff --git a/code/modules/preferences/preference_setup/background/faction.dm b/code/modules/preferences/preference_setup/background/faction.dm index 7125559f2ce..9ab719397a3 100644 --- a/code/modules/preferences/preference_setup/background/faction.dm +++ b/code/modules/preferences/preference_setup/background/faction.dm @@ -7,9 +7,17 @@ /datum/category_item/player_setup_item/background/faction/content(datum/preferences/prefs, mob/user, data) . = list() var/list/datum/lore/character_background/faction/available = SScharacters.available_factions(prefs.character_species_id(), prefs.lore_origin_id(), prefs.lore_citizenship_id()) + var/list/categories = list() + for(var/datum/lore/character_background/faction/O as anything in available) + LAZYADD(categories[O.category], O) var/datum/lore/character_background/faction/current = SScharacters.resolve_faction(data) . += "
" . += "Faction
" + if(length(categories) > 1) + for(var/category in categories) + . += (category == current.category)? "[category] " : href_simple(prefs, "category", "[category]", category) + . += " " + . += "
" for(var/datum/lore/character_background/faction/O in available) if(O == current) . += "[O.name]" @@ -32,8 +40,19 @@ to_chat(user, SPAN_WARNING("[prefs.character_species_name()] cannot pick this faction.")) return PREFERENCES_NOACTION write(prefs, id) + prefs.sanitize_background_lore() // update GLOB.join_menu?.update_static_data(user) return PREFERENCES_REFRESH_UPDATE_PREVIEW + if("category") + var/cat = params["category"] + var/list/datum/lore/character_background/faction/factions = SScharacters.available_factions(prefs.character_species_id(), category = cat) + if(!length(factions)) + to_chat(user, SPAN_WARNING("No factions in that category have been found; this might be an error.")) + return PREFERENCES_NOACTION + var/datum/lore/character_background/faction/first = factions[1] + write(prefs, first.id) + prefs.sanitize_background_lore() // update + return PREFERENCES_REFRESH return ..() /datum/category_item/player_setup_item/background/faction/filter_data(datum/preferences/prefs, data, list/errors) @@ -56,7 +75,7 @@ M.add_language(id) return TRUE -/datum/category_item/player_setup_item/background/faction/spawn_checks(datum/preferences/prefs, data, flags, list/errors) +/datum/category_item/player_setup_item/background/faction/spawn_checks(datum/preferences/prefs, data, flags, list/errors, list/warnings) var/datum/lore/character_background/faction/current = SScharacters.resolve_faction(data) if(!current?.check_species_id(prefs.character_species_id())) errors?.Add("Invalid faction for your current species.") @@ -85,7 +104,8 @@ return get_character_data(CHARACTER_DATA_FACTION) /datum/preferences/proc/lore_faction_datum() - return get_character_data(CHARACTER_DATA_FACTION) + RETURN_TYPE(/datum/lore/character_background/faction) + return SScharacters.resolve_faction(get_character_data(CHARACTER_DATA_FACTION)) -/datum/preferences/proc/lore_faction_job_check(datum/job/J) - return SScharacters.resolve_faction(get_character_data(CHARACTER_DATA_FACTION))?.check_job_id(J.id) +/datum/preferences/proc/lore_faction_job_check(datum/role/job/J) + return lore_faction_datum()?.check_job_id(J.id) diff --git a/code/modules/preferences/preference_setup/background/language.dm b/code/modules/preferences/preference_setup/background/language.dm index 2a9ca48c579..aebe9ad0d5f 100644 --- a/code/modules/preferences/preference_setup/background/language.dm +++ b/code/modules/preferences/preference_setup/background/language.dm @@ -58,7 +58,7 @@ for(var/id in data) H.add_language(id) -/datum/category_item/player_setup_item/background/language/spawn_checks(datum/preferences/prefs, data, flags, list/errors) +/datum/category_item/player_setup_item/background/language/spawn_checks(datum/preferences/prefs, data, flags, list/errors, list/warnings) if(length(data) > prefs.extraneous_languages_max()) errors?.Add(SPAN_WARNING("You have selected too many extra languages for your species and culture.")) return FALSE diff --git a/code/modules/preferences/preference_setup/background/origin.dm b/code/modules/preferences/preference_setup/background/origin.dm index 6f431e50d40..4def82ff72c 100644 --- a/code/modules/preferences/preference_setup/background/origin.dm +++ b/code/modules/preferences/preference_setup/background/origin.dm @@ -12,10 +12,11 @@ var/datum/lore/character_background/origin/current = SScharacters.resolve_origin(data) . += "
" . += "Origin
" - for(var/category in categories) - . += (category == current.category)? "[category] " : href_simple(prefs, "category", "[category]", category) - . += " " - . += "
" + if(length(categories) > 1) + for(var/category in categories) + . += (category == current.category)? "[category] " : href_simple(prefs, "category", "[category]", category) + . += " " + . += "
" for(var/datum/lore/character_background/origin/O in categories[current.category]) if(O == current) . += "[O.name]" @@ -38,6 +39,7 @@ to_chat(user, SPAN_WARNING("[prefs.character_species_name()] cannot pick this origin.")) return PREFERENCES_NOACTION write(prefs, id) + prefs.sanitize_background_lore() // update return PREFERENCES_REFRESH if("category") var/cat = params["category"] @@ -64,7 +66,7 @@ M.add_language(id) return TRUE -/datum/category_item/player_setup_item/background/origin/spawn_checks(datum/preferences/prefs, data, flags, list/errors) +/datum/category_item/player_setup_item/background/origin/spawn_checks(datum/preferences/prefs, data, flags, list/errors, list/warnings) var/datum/lore/character_background/origin/current = SScharacters.resolve_origin(data) if(!current?.check_species_id(prefs.character_species_id())) errors?.Add("Invalid origin for your current species.") @@ -84,4 +86,5 @@ return get_character_data(CHARACTER_DATA_ORIGIN) /datum/preferences/proc/lore_origin_datum() + RETURN_TYPE(/datum/lore/character_background/origin) return SScharacters.resolve_origin(lore_origin_id()) diff --git a/code/modules/preferences/preference_setup/background/religion.dm b/code/modules/preferences/preference_setup/background/religion.dm index 4d75fe4dbfa..c790a8b6585 100644 --- a/code/modules/preferences/preference_setup/background/religion.dm +++ b/code/modules/preferences/preference_setup/background/religion.dm @@ -6,9 +6,17 @@ /datum/category_item/player_setup_item/background/religion/content(datum/preferences/prefs, mob/user, data) . = list() var/list/datum/lore/character_background/religion/available = SScharacters.available_religions(prefs.character_species_id()) + var/list/categories = list() + for(var/datum/lore/character_background/religion/O as anything in available) + LAZYADD(categories[O.category], O) var/datum/lore/character_background/religion/current = SScharacters.resolve_religion(data) . += "
" . += "Religion
" + if(length(categories) > 1) + for(var/category in categories) + . += (category == current.category)? "[category] " : href_simple(prefs, "category", "[category]", category) + . += " " + . += "
" for(var/datum/lore/character_background/religion/O in available) if(O == current) . += "[O.name]" @@ -31,6 +39,17 @@ to_chat(user, SPAN_WARNING("[prefs.character_species_name()] cannot pick this religion.")) return PREFERENCES_NOACTION write(prefs, id) + prefs.sanitize_background_lore() // update + return PREFERENCES_REFRESH + if("category") + var/cat = params["category"] + var/list/datum/lore/character_background/religion/religions = SScharacters.available_religions(prefs.character_species_id(), cat) + if(!length(religions)) + to_chat(user, SPAN_WARNING("No religions in that category have been found; this might be an error.")) + return PREFERENCES_NOACTION + var/datum/lore/character_background/religion/first = religions[1] + write(prefs, first.id) + prefs.sanitize_background_lore() // update return PREFERENCES_REFRESH return ..() @@ -47,7 +66,7 @@ M.add_language(id) return TRUE -/datum/category_item/player_setup_item/background/religion/spawn_checks(datum/preferences/prefs, data, flags, list/errors) +/datum/category_item/player_setup_item/background/religion/spawn_checks(datum/preferences/prefs, data, flags, list/errors, list/warnings) var/datum/lore/character_background/religion/current = SScharacters.resolve_religion(data) if(!current?.check_species_id(prefs.character_species_id())) errors?.Add("Invalid religion for your current species.") @@ -67,4 +86,6 @@ return get_character_data(CHARACTER_DATA_RELIGION) /datum/preferences/proc/lore_religion_datum() + RETURN_TYPE(/datum/lore/character_background/religion) return SScharacters.resolve_religion(lore_religion_id()) + diff --git a/code/modules/preferences/preference_setup/background/species.dm b/code/modules/preferences/preference_setup/background/species.dm index 340a9c0f99e..ff853fe6b60 100644 --- a/code/modules/preferences/preference_setup/background/species.dm +++ b/code/modules/preferences/preference_setup/background/species.dm @@ -24,7 +24,7 @@ . += "[CS.desc]" . += "" -/datum/category_item/player_setup_item/background/char_species/spawn_checks(datum/preferences/prefs, data, flags, list/errors) +/datum/category_item/player_setup_item/background/char_species/spawn_checks(datum/preferences/prefs, data, flags, list/errors, list/warnings) var/datum/character_species/CS = SScharacters.resolve_character_species(data) if((CS.species_spawn_flags & SPECIES_SPAWN_RESTRICTED) && !(flags & PREF_COPY_TO_NO_CHECK_SPECIES)) errors?.Add(SPAN_WARNING("[CS.name] is a restricted species. You cannot join as this as most normal roles.")) @@ -113,5 +113,5 @@ /datum/preferences/proc/real_species_name() return SScharacters.resolve_species_id(get_character_data(CHARACTER_DATA_REAL_SPECIES)).name -/datum/preferences/proc/character_species_job_check(datum/job/J) +/datum/preferences/proc/character_species_job_check(datum/role/job/J) return TRUE // todo diff --git a/code/modules/preferences/preference_setup/general/01_basic.dm b/code/modules/preferences/preference_setup/general/01_basic.dm index e81a27e5e96..683f6d92d48 100644 --- a/code/modules/preferences/preference_setup/general/01_basic.dm +++ b/code/modules/preferences/preference_setup/general/01_basic.dm @@ -81,9 +81,8 @@ . += "Pronouns: [gender2text(pref.identifying_gender)]
" . += "Age: [pref.age]
" . += "Spawn Point: [pref.spawnpoint]
" - if(config_legacy.allow_Metadata) - . += "OOC Notes: Edit
" - . = jointext(.,null) + . += "OOC Notes: Edit
" + . = jointext(., null) /datum/category_item/player_setup_item/general/basic/OnTopic(var/href,var/list/href_list, var/mob/user) if(href_list["rename"]) @@ -146,13 +145,18 @@ return PREFERENCES_REFRESH else if(href_list["metadata"]) - var/new_metadata = sanitize(input(user, "Enter any information you'd like others to see, such as Roleplay-preferences:", "Game Preference" , html_decode(pref.metadata)) as message, extra = 0) + var/new_metadata = sanitize(input(user, "Enter any information you'd like others to see in terms of roleplay preferences (including any ERP consent / preference information). This information is considered OOC, unlike 'Flavor Text'.", "OOC Notes" , html_decode(pref.metadata)) as message, extra = 0) if(new_metadata && CanUseTopic(user)) pref.metadata = new_metadata return PREFERENCES_REFRESH return ..() +/datum/category_item/player_setup_item/general/basic/spawn_checks(datum/preferences/prefs, data, flags, list/errors, list/warnings) + . = ..() + if(!length(prefs.metadata)) + warnings += "Missing OOC Notes - See Character Setup for information." + /datum/category_item/player_setup_item/general/basic/proc/get_genders() var/datum/species/S = pref.real_species_datum() var/list/possible_genders = S.genders diff --git a/code/modules/preferences/preference_setup/general/06_flavor.dm b/code/modules/preferences/preference_setup/general/06_flavor.dm index 6b615844c36..123a5f02bad 100644 --- a/code/modules/preferences/preference_setup/general/06_flavor.dm +++ b/code/modules/preferences/preference_setup/general/06_flavor.dm @@ -64,11 +64,11 @@ switch(href_list["flavor_text"]) if("open") if("general") - var/msg = sanitize(input(usr,"Give a general description of your character. This will be shown regardless of clothings.","Flavor Text",html_decode(pref.flavor_texts[href_list["flavor_text"]])) as message, extra = 0, max_length = 8192) + var/msg = sanitize(input(usr,"Give a general description of your character. This will be shown regardless of clothings. Flavor text is what someone can see IC with a glance, please do not include OOC things like personality / backstory!","Flavor Text",html_decode(pref.flavor_texts[href_list["flavor_text"]])) as message, extra = 0, max_length = 8192) if(CanUseTopic(user)) pref.flavor_texts[href_list["flavor_text"]] = msg else - var/msg = sanitize(input(usr,"Set the flavor text for your [href_list["flavor_text"]].","Flavor Text",html_decode(pref.flavor_texts[href_list["flavor_text"]])) as message, extra = 0, max_length = 8192) + var/msg = sanitize(input(usr,"Set the flavor text for your [href_list["flavor_text"]]. Flavor text is what someone can see IC with a glance, please do not include OOC things like personality / backstory!","Flavor Text",html_decode(pref.flavor_texts[href_list["flavor_text"]])) as message, extra = 0, max_length = 8192) if(CanUseTopic(user)) pref.flavor_texts[href_list["flavor_text"]] = msg SetFlavorText(user) @@ -78,11 +78,11 @@ switch(href_list["flavour_text_robot"]) if("open") if("Default") - var/msg = sanitize(input(usr,"Set the default flavour text for your robot. It will be used for any module without individual setting.","Flavour Text",html_decode(pref.flavour_texts_robot["Default"])) as message, extra = 0, max_length = 8192) + var/msg = sanitize(input(usr,"Set the default flavour text for your robot. It will be used for any module without individual setting. Flavor text is what someone can see IC with a glance, please do not include OOC things like personality / backstory!","Flavour Text",html_decode(pref.flavour_texts_robot["Default"])) as message, extra = 0, max_length = 8192) if(CanUseTopic(user)) pref.flavour_texts_robot[href_list["flavour_text_robot"]] = msg else - var/msg = sanitize(input(usr,"Set the flavour text for your robot with [href_list["flavour_text_robot"]] module. If you leave this empty, default flavour text will be used for this module.","Flavour Text",html_decode(pref.flavour_texts_robot[href_list["flavour_text_robot"]])) as message, extra = 0, max_length = 8192) + var/msg = sanitize(input(usr,"Set the flavour text for your robot with [href_list["flavour_text_robot"]] module. If you leave this empty, default flavour text will be used for this module. Flavor text is what someone can see IC with a glance, please do not include OOC things like personality / backstory!","Flavour Text",html_decode(pref.flavour_texts_robot[href_list["flavour_text_robot"]])) as message, extra = 0, max_length = 8192) if(CanUseTopic(user)) pref.flavour_texts_robot[href_list["flavour_text_robot"]] = msg SetFlavourTextRobot(user) @@ -90,6 +90,11 @@ return ..() +/datum/category_item/player_setup_item/general/flavor/spawn_checks(datum/preferences/prefs, data, flags, list/errors, list/warnings) + . = ..() + if(!length(prefs.flavor_texts["general"])) + warnings += "Missing general flavor text - See Character Setup for information." + /datum/category_item/player_setup_item/general/flavor/proc/SetFlavorText(mob/user) var/HTML = "" HTML += "
" diff --git a/code/modules/preferences/preference_setup/occupation/occupation.dm b/code/modules/preferences/preference_setup/occupation/occupation.dm index 103a9f7bc0f..7d23babbdc3 100644 --- a/code/modules/preferences/preference_setup/occupation/occupation.dm +++ b/code/modules/preferences/preference_setup/occupation/occupation.dm @@ -6,6 +6,7 @@ /datum/category_item/player_setup_item/occupation is_global = FALSE + load_order = PREFERENCE_LOAD_ORDER_OCCUPATIONS /** * save format: list(job id = priority) @@ -18,7 +19,7 @@ var/list/jobs = sanitize_islist(data) var/highest for(var/id in jobs) - var/datum/job/J = SSjob.job_by_id(id) + var/datum/role/job/J = SSjob.job_by_id(id) if(!J) jobs -= id continue @@ -97,7 +98,7 @@ #undef END_COLUMN #undef START_COLUMN -/datum/category_item/player_setup_item/occupation/jobs/proc/render_job(datum/preferences/prefs, datum/job/J, current_priority, assistant_selected) +/datum/category_item/player_setup_item/occupation/jobs/proc/render_job(datum/preferences/prefs, datum/role/job/J, current_priority, assistant_selected) . = list() . += "" // left side @@ -147,7 +148,7 @@ /** * return null if allowed, otherwise return error to display */ -/datum/category_item/player_setup_item/occupation/jobs/proc/check_job(datum/preferences/prefs, datum/job/J, current_priority) +/datum/category_item/player_setup_item/occupation/jobs/proc/check_job(datum/preferences/prefs, datum/role/job/J, current_priority) var/client/C = pref.client if(!C) return null @@ -164,20 +165,20 @@ prefs.set_job_priority(job_id, level) return PREFERENCES_REFRESH_UPDATE_PREVIEW if("title") - var/datum/job/J = SSjob.job_by_id(params["title"]) + var/datum/role/job/J = SSjob.job_by_id(params["title"]) if(!J) return PREFERENCES_NOACTION - var/title = input(user, "Choose a title for [J.title].", "Choose Title", prefs.get_job_alt_title_name(J)) as null|anything in (J.alt_titles | J.title) + var/title = input(user, "Choose a title for [J.title].", "Choose Title", prefs.get_job_alt_title_name(J)) as null|anything in prefs.available_alt_titles(J) if(!title) return PREFERENCES_NOACTION prefs.set_job_title(params["title"], title) return PREFERENCES_REFRESH_UPDATE_PREVIEW if("help") - var/datum/job/J = SSjob.job_by_id(params["help"]) + var/datum/role/job/J = SSjob.job_by_id(params["help"]) var/list/built = list("
") built += "

[J.title]

" built += "Purpose: [J.desc]" - built += "Alternative titles: [english_list(J.alt_titles)]" + built += "Alternative titles (faction): [english_list(prefs.available_alt_titles(J))]" if(J.supervisors) built += "You answer to [J.supervisors], normally." if(J.departments) @@ -205,6 +206,13 @@ /datum/category_item/player_setup_item/occupation/jobs/default_value(randomizing) return list() +/datum/preferences/proc/available_alt_titles(datum/role/job/J) + RETURN_TYPE(/list) + return J.alt_title_query(all_background_datums()) + +/datum/preferences/proc/check_alt_title(datum/role/job/J, alt_title) + return J.alt_title_check(alt_title, all_background_datums()) + /** * display is done by jobs; this datum only handles data filtering * @@ -216,15 +224,21 @@ /datum/category_item/player_setup_item/occupation/alt_titles/filter_data(datum/preferences/prefs, data, list/errors) var/list/jobs = sanitize_islist(data) + // check the ones we have to ensure compliance for(var/id in jobs) - var/datum/job/J = SSjob.job_by_id(id) + var/datum/role/job/J = SSjob.job_by_id(id) if(!J) jobs -= id continue var/title = jobs[id] - if(!J.alt_titles[title]) + if(!prefs.check_alt_title(J, title)) jobs -= id + // check the ones we don't and are strict titles + for(var/datum/role/job/J as anything in SSjob.all_jobs()) + if(!J.strict_titles || !isnull(jobs[J.id])) continue + // this will always have atleast one + jobs[J.id] = prefs.available_alt_titles(J)[1] return jobs /datum/category_item/player_setup_item/occupation/alt_titles/default_value(randomizing) @@ -250,12 +264,12 @@ ) return sanitize_inlist(data, static_list, JOB_ALTERNATIVE_BE_ASSISTANT) -/datum/preferences/proc/get_job_priority(datum/job/J) +/datum/preferences/proc/get_job_priority(datum/role/job/J) var/list/jobs = get_character_data(CHARACTER_DATA_JOBS) return jobs[J.id] -/datum/preferences/proc/get_job_alt_title_name(datum/job/J) - RETURN_TYPE(/datum/alt_title) +/datum/preferences/proc/get_job_alt_title_name(datum/role/job/J) + RETURN_TYPE(/datum/prototype/alt_title) var/list/titles = get_character_data(CHARACTER_DATA_ALT_TITLES) return titles[J.id] || J.title @@ -277,7 +291,7 @@ continue .[id] = priorities[id] -/datum/preferences/proc/effective_job_priority(datum/job/J) +/datum/preferences/proc/effective_job_priority(datum/role/job/J) if(!lore_faction_job_check(J)) return JOB_PRIORITY_NEVER var/list/jobs = get_character_data(CHARACTER_DATA_JOBS) @@ -287,7 +301,7 @@ * gets effective job priority of a job for current slot; used for * roundstart procs. returns JOB_PRIORITY_NEVER if we can't be said job. */ -/client/proc/effective_job_priority(datum/job/J) +/client/proc/effective_job_priority(datum/role/job/J) if(J.check_client_availability_one(src) != ROLE_AVAILABLE) return JOB_PRIORITY_NEVER return prefs?.effective_job_priority(J) @@ -302,7 +316,7 @@ RETURN_TYPE(/list) . = list() var/list/priorities = sanitize_islist(prefs.get_character_data(CHARACTER_DATA_JOBS)) - for(var/datum/job/J as anything in SSjob.all_jobs()) + for(var/datum/role/job/J as anything in SSjob.all_jobs()) if(J.check_client_availability_one(src) != ROLE_AVAILABLE) continue var/id = J.id @@ -332,7 +346,7 @@ return get_character_data(CHARACTER_DATA_OVERFLOW_MODE) /datum/preferences/proc/set_job_priority(id, priority) - var/datum/job/J = SSjob.job_by_id(id) + var/datum/role/job/J = SSjob.job_by_id(id) if(!J) return if(priority < JOB_PRIORITY_NEVER || priority > JOB_PRIORITY_HIGH) @@ -345,7 +359,7 @@ set_character_data(CHARACTER_DATA_JOBS, current) /datum/preferences/proc/set_job_title(id, title) - var/datum/job/J = SSjob.job_by_id(id) + var/datum/role/job/J = SSjob.job_by_id(id) if(!J) return var/list/current = get_character_data(CHARACTER_DATA_ALT_TITLES) @@ -353,7 +367,7 @@ // reset current -= id else - if(!J.alt_titles[title]) + if(!J.alt_titles?[title]) return current[id] = title set_character_data(CHARACTER_DATA_ALT_TITLES, current) diff --git a/code/modules/preferences/preference_setup/preference_category_new.dm b/code/modules/preferences/preference_setup/preference_category_new.dm index 2015a233a3f..d1174acb4e7 100644 --- a/code/modules/preferences/preference_setup/preference_category_new.dm +++ b/code/modules/preferences/preference_setup/preference_category_new.dm @@ -1,9 +1,9 @@ /datum/category_group/player_setup_category -/datum/category_group/player_setup_category/proc/spawn_checks(datum/preferences/prefs, flags, list/errors) +/datum/category_group/player_setup_category/proc/spawn_checks(datum/preferences/prefs, flags, list/errors, list/warnings) . = TRUE for(var/datum/category_item/player_setup_item/preference in items) - if(!preference.spawn_checks(prefs, prefs.get_character_data(preference.save_key), flags, errors)) + if(!preference.spawn_checks(prefs, prefs.get_character_data(preference.save_key), flags, errors, warnings)) . = FALSE // todo: multi stage random character generation diff --git a/code/modules/preferences/preference_setup/preference_item_new.dm b/code/modules/preferences/preference_setup/preference_item_new.dm index 9d39263394e..92e2cf4d898 100644 --- a/code/modules/preferences/preference_setup/preference_item_new.dm +++ b/code/modules/preferences/preference_setup/preference_item_new.dm @@ -33,9 +33,16 @@ * called to check for errors; if non null, players get showed this while spawning and the * spawn is blocked. * - * put reasons into errors + * @params + * * prefs - preferences datum of spawning mob + * * data - current effective data + * * flags - preferences copy/apply to flags + * * errors - put error reasons to show to user + * * warnings - put warnings to show to user; if these exist AND they can spawn, they'll be warned but allowed to spawn if they confirm. + * + * @return TRUE/FALSE if we should be allowd to spawn */ -/datum/category_item/player_setup_item/proc/spawn_checks(datum/preferences/prefs, data, flags, list/errors) +/datum/category_item/player_setup_item/proc/spawn_checks(datum/preferences/prefs, data, flags, list/errors, list/warnings) return TRUE /** diff --git a/code/modules/preferences/preference_setup/skills/skills.dm b/code/modules/preferences/preference_setup/skills/skills.dm index 992c97d762e..cd0b36a3286 100644 --- a/code/modules/preferences/preference_setup/skills/skills.dm +++ b/code/modules/preferences/preference_setup/skills/skills.dm @@ -1,8 +1,39 @@ -// This file has been UNTICKED on purpose, as it is not in use. +// TODO: this file is still commented out, because we will not even *SHOW* it until skills implementation is near critical mass. + +/datum/category_group/player_setup_category/skills + name = "Skills" + sort_order = 3.5 + category_item_type = /datum/category_item/player_setup_item/skills /datum/category_item/player_setup_item/skills name = "Skills" sort_order = 1 + save_key = CHARACTER_DATA_SKILLS + is_global = FALSE + +/datum/category_item/player_setup_item/skills/content(datum/preferences/prefs, mob/user, data) + . = ..() + +/datum/category_item/player_setup_item/skills/act(datum/preferences/prefs, mob/user, action, list/params) + switch(action) + if("set") + + if("reset") + + if("preset") + + if("details") + + return ..() + +/datum/category_item/player_setup_item/skills/filter_data(datum/preferences/prefs, data, list/errors) + var/list/skill_data = sanitize_islist(data) + + +/datum/category_item/player_setup_item/skills/copy_to_mob(datum/preferences/prefs, mob/M, data, flags) + . = ..() + +#warn impl above /datum/category_item/player_setup_item/skills/load_character(var/savefile/S) S["skills"] >> pref.skills diff --git a/code/modules/preferences/preference_setup/vore/08_traits.dm b/code/modules/preferences/preference_setup/vore/08_traits.dm index eb51170b1c4..20e790067e6 100644 --- a/code/modules/preferences/preference_setup/vore/08_traits.dm +++ b/code/modules/preferences/preference_setup/vore/08_traits.dm @@ -119,7 +119,7 @@ S.blood_color = pref.blood_color if(pref.real_species_id() == SPECIES_ID_CUSTOM) - if(flags & PREF_COPY_TO_IS_SPAWNING) + if(PREF_COPYING_TO_CHECK_IS_SPAWNING(flags)) //Statistics for this would be nice var/english_traits = english_list(S.traits, and_text = ";", comma_text = ";") log_game("TRAITS [pref.client_ckey]/([character]) with: [english_traits]") //Terrible 'fake' key_name()... but they aren't in the same entity yet diff --git a/code/modules/preferences/preferences_setup.dm b/code/modules/preferences/preferences_setup.dm index 1165733c127..a549cd7a7a4 100644 --- a/code/modules/preferences/preferences_setup.dm +++ b/code/modules/preferences/preferences_setup.dm @@ -197,9 +197,9 @@ if(!equip_preview_mob) return - var/datum/job/previewJob = SSjob.job_by_id(preview_job_id()) + var/datum/role/job/previewJob = SSjob.job_by_id(preview_job_id()) - if((equip_preview_mob & EQUIP_PREVIEW_LOADOUT) && !(previewJob && (equip_preview_mob & EQUIP_PREVIEW_JOB) && (previewJob.type == /datum/job/station/ai || previewJob.type == /datum/job/station/cyborg))) + if((equip_preview_mob & EQUIP_PREVIEW_LOADOUT) && !(previewJob && (equip_preview_mob & EQUIP_PREVIEW_JOB) && (previewJob.type == /datum/role/job/station/ai || previewJob.type == /datum/role/job/station/cyborg))) var/list/equipped_slots = list() for(var/thing in gear) var/datum/gear/G = gear_datums[thing] diff --git a/code/modules/resleeving/infocore_records.dm b/code/modules/resleeving/infocore_records.dm index db79d51f4b6..05579a117ad 100644 --- a/code/modules/resleeving/infocore_records.dm +++ b/code/modules/resleeving/infocore_records.dm @@ -39,7 +39,7 @@ //The mind! mind_ref = mind mindname = mind.name - ckey = ckey(mind.key) + ckey = mind.ckey cryo_at = 0 diff --git a/code/modules/resleeving/machines.dm b/code/modules/resleeving/machines.dm index bd529a0b1f4..2fc654096ef 100644 --- a/code/modules/resleeving/machines.dm +++ b/code/modules/resleeving/machines.dm @@ -585,7 +585,7 @@ occupant.confused = max(occupant.confused, confuse_amount) occupant.eye_blurry = max(occupant.eye_blurry, blur_amount) - if(occupant.mind && occupant.original_player && ckey(occupant.mind.key) != occupant.original_player) + if(occupant.mind && occupant.original_player && occupant.mind.ckey != occupant.original_player) log_and_message_admins("is now a cross-sleeved character. Body originally belonged to [occupant.real_name]. Mind is now [occupant.mind.name].",occupant) if(original_occupant) diff --git a/code/modules/roles/role.dm b/code/modules/roles/role.dm new file mode 100644 index 00000000000..af9a40bc7f8 --- /dev/null +++ b/code/modules/roles/role.dm @@ -0,0 +1,6 @@ +/** + * WIP + * TODO: unified role system + */ +/datum/role + abstract_type = /datum/role diff --git a/code/modules/tgui/modules/ntos-only/cardmod.dm b/code/modules/tgui/modules/ntos-only/cardmod.dm index 31ee07e01ac..60c3ad015cb 100644 --- a/code/modules/tgui/modules/ntos-only/cardmod.dm +++ b/code/modules/tgui/modules/ntos-only/cardmod.dm @@ -202,9 +202,9 @@ if(is_centcom) access = get_centcom_access(t1) else - var/datum/job/jobdatum - for(var/jobtype in typesof(/datum/job)) - var/datum/job/J = new jobtype + var/datum/role/job/jobdatum + for(var/jobtype in typesof(/datum/role/job)) + var/datum/role/job/J = new jobtype if(ckey(J.title) == ckey(t1)) jobdatum = J break diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index ae3ba1edf6f..c4e5c7832eb 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -103,6 +103,7 @@ // #include "pills.dm" // #include "plantgrowth_tests.dm" // #include "projectiles.dm" +#include "prototypes.dm" // #include "reagent_id_typos.dm" // #include "reagent_mod_expose.dm" // #include "reagent_mod_procs.dm" diff --git a/code/modules/unit_tests/mob/_mob.dm b/code/modules/unit_tests/mob/_mob.dm index 4221cf340e1..250eab27bed 100644 --- a/code/modules/unit_tests/mob/_mob.dm +++ b/code/modules/unit_tests/mob/_mob.dm @@ -1,2 +1,3 @@ +#include "characteristics.dm" #include "inventory.dm" #include "sprite_accessories.dm" diff --git a/code/modules/unit_tests/mob/characteristics.dm b/code/modules/unit_tests/mob/characteristics.dm new file mode 100644 index 00000000000..e547a4dee69 --- /dev/null +++ b/code/modules/unit_tests/mob/characteristics.dm @@ -0,0 +1,2 @@ +/datum/unit_test/characteristics/Run() + // todo: uniqueness on ids, but not yet diff --git a/code/modules/unit_tests/prototypes.dm b/code/modules/unit_tests/prototypes.dm new file mode 100644 index 00000000000..193a6af2bf0 --- /dev/null +++ b/code/modules/unit_tests/prototypes.dm @@ -0,0 +1,18 @@ +/datum/unit_test/prototypes/Run() + var/list/id_cache = list() + var/list/type_cache = list() + for(var/datum/prototype/instance as anything in subtypesof(/datum/prototype)) + if(initial(instance.abstract_type) == instance) + continue + // lazy is ignored + instance = new instance + if(instance.anonymous && instance.identifier) + Fail("[instance.type]: has identifier but is marked anonymous") + type_cache[instance] = instance + if(!instance.uid) + Fail("[instance.type]: no uid") + else if(id_cache[instance.uid]) + Fail("[instance.type]: collides on uid [instance.uid] with [id_cache[instance.uid]:type].") + else + id_cache[instance.uid] = instance + diff --git a/config/entries/skills.txt b/config/entries/skills.txt new file mode 100644 index 00000000000..2a9b2206c61 --- /dev/null +++ b/config/entries/skills.txt @@ -0,0 +1,5 @@ +## Do we have the characteristics system at all? +CHARACTERISTICS_ENABLED + +## Are skills in use? +# CHARACTERISTICS_ACTIVE diff --git a/maps/~map_system/maps.dm b/maps/~map_system/maps.dm index b644dea06c9..4e15f9507a8 100644 --- a/maps/~map_system/maps.dm +++ b/maps/~map_system/maps.dm @@ -137,7 +137,7 @@ var/list/all_maps = list() if(!map_levels) map_levels = station_levels.Copy() if(!allowed_jobs || !allowed_jobs.len) - allowed_jobs = subtypesof(/datum/job) + allowed_jobs = subtypesof(/datum/role/job) // Gets the current time on a current zlevel, and returns a time datum /datum/map/proc/get_zlevel_time(var/z)