mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-06-20 05:34:10 +01:00
Merge branch 'Skyrat-SS13:master' into master
This commit is contained in:
@@ -2,22 +2,36 @@ Any time you make a change to the schema files, remember to increment the databa
|
||||
|
||||
Make sure to also update `DB_MAJOR_VERSION` and `DB_MINOR_VERSION`, which can be found in `code/__DEFINES/subsystem.dm`.
|
||||
|
||||
The latest database version is 5.24 (5.22 for /tg/); The query to update the schema revision table is:
|
||||
The latest database version is 5.25 (5.23 for /tg/); The query to update the schema revision table is:
|
||||
|
||||
INSERT INTO `schema_revision` (`major`, `minor`) VALUES (5, 24);
|
||||
INSERT INTO `schema_revision` (`major`, `minor`) VALUES (5, 25);
|
||||
or
|
||||
INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (5, 24);
|
||||
INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (5, 25);
|
||||
|
||||
In any query remember to add a prefix to the table names if you use one.
|
||||
|
||||
-----------------------------------------------------
|
||||
Version 5.25, 28 December 2022, by Mothblocks
|
||||
Added `tutorial_completions` to mark what ckeys have completed contextual tutorials.
|
||||
|
||||
```
|
||||
CREATE TABLE `tutorial_completions` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`ckey` VARCHAR(32) NOT NULL,
|
||||
`tutorial_key` VARCHAR(64) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `ckey_tutorial_unique` (`ckey`, `tutorial_key`));
|
||||
```
|
||||
|
||||
-----------------------------------------------------
|
||||
Version 5.24, 22 December 2021, by Mothblocks
|
||||
Fixes a bug in `telemetry_connections` that limited the range of IPs.
|
||||
|
||||
```
|
||||
ALTER TABLE `telemetry_connections` MODIFY COLUMN `address` INT(10) UNSIGNED NOT NULL;
|
||||
```
|
||||
-----------------------------------------------------
|
||||
|
||||
-----------------------------------------------------
|
||||
Version 5.23, 15 December 2021, by Mothblocks
|
||||
Adds `telemetry_connections` table for tracking tgui telemetry.
|
||||
|
||||
|
||||
@@ -716,6 +716,14 @@ CREATE TABLE `telemetry_connections` (
|
||||
UNIQUE INDEX `unique_constraints` (`ckey` , `telemetry_ckey` , `address` , `computer_id`)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS `tutorial_completions`;
|
||||
CREATE TABLE `tutorial_completions` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`ckey` VARCHAR(32) NOT NULL,
|
||||
`tutorial_key` VARCHAR(64) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `ckey_tutorial_unique` (`ckey`, `tutorial_key`));
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||
|
||||
@@ -700,6 +700,14 @@ CREATE TABLE `SS13_telemetry_connections` (
|
||||
UNIQUE INDEX `unique_constraints` (`ckey` , `telemetry_ckey` , `address` , `computer_id`)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS `SS13_tutorial_completions`;
|
||||
CREATE TABLE `SS13_tutorial_completions` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`ckey` VARCHAR(32) NOT NULL,
|
||||
`tutorial_key` VARCHAR(64) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `ckey_tutorial_unique` (`ckey`, `tutorial_key`));
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#define MEDAL_VOID_ASCENSION "Void"
|
||||
#define MEDAL_BLADE_ASCENSION "Blade"
|
||||
#define MEDAL_TOOLBOX_SOUL "Toolsoul"
|
||||
#define MEDAL_CHEM_TUT "Beginner Chemist"
|
||||
#define MEDAL_CHEM_TUT "Beginner Chemist"
|
||||
#define MEDAL_HOT_DAMN "Hot Damn!"
|
||||
#define MEDAL_CAYENNE_DISK "Very Important Piscis"
|
||||
#define MEDAL_TRAM_SURFER "Tram Surfer"
|
||||
@@ -69,24 +69,23 @@
|
||||
|
||||
//Mafia medal hub IDs (misc stuff)
|
||||
#define MAFIA_MEDAL_HATED "Universally Hated"
|
||||
#define MAFIA_MEDAL_CHARISMATIC "Charismatic"
|
||||
#define MAFIA_MEDAL_VIP "VIP"
|
||||
|
||||
//Boss medals
|
||||
|
||||
// Medal hub IDs for boss medals (Pre-fixes)
|
||||
#define BOSS_MEDAL_ANY "Boss Killer"
|
||||
#define BOSS_MEDAL_MINER "Blood-drunk Miner Killer"
|
||||
#define BOSS_MEDAL_ANY "Boss Killer"
|
||||
|
||||
#define BOSS_MEDAL_MINER "Blood-drunk Miner Killer"
|
||||
#define BOSS_MEDAL_FROSTMINER "Demonic-frost Miner Killer"
|
||||
#define BOSS_MEDAL_BUBBLEGUM "Bubblegum Killer"
|
||||
#define BOSS_MEDAL_COLOSSUS "Colossus Killer"
|
||||
#define BOSS_MEDAL_DRAKE "Drake Killer"
|
||||
#define BOSS_MEDAL_BUBBLEGUM "Bubblegum Killer"
|
||||
#define BOSS_MEDAL_COLOSSUS "Colossus Killer"
|
||||
#define BOSS_MEDAL_DRAKE "Drake Killer"
|
||||
#define BOSS_MEDAL_HIEROPHANT "Hierophant Killer"
|
||||
#define BOSS_MEDAL_LEGION "Legion Killer"
|
||||
#define BOSS_MEDAL_TENDRIL "Tendril Exterminator"
|
||||
#define BOSS_MEDAL_SWARMERS "Swarmer Beacon Killer"
|
||||
#define BOSS_MEDAL_WENDIGO "Wendigo Killer"
|
||||
#define BOSS_MEDAL_KINGGOAT "King Goat Killer"
|
||||
#define BOSS_MEDAL_LEGION "Legion Killer"
|
||||
#define BOSS_MEDAL_TENDRIL "Tendril Exterminator"
|
||||
#define BOSS_MEDAL_SWARMERS "Swarmer Beacon Killer"
|
||||
#define BOSS_MEDAL_WENDIGO "Wendigo Killer"
|
||||
#define BOSS_MEDAL_KINGGOAT "King Goat Killer"
|
||||
|
||||
#define BOSS_MEDAL_MINER_CRUSHER "Blood-drunk Miner Crusher"
|
||||
#define BOSS_MEDAL_FROSTMINER_CRUSHER "Demonic-frost Miner Crusher"
|
||||
@@ -100,18 +99,18 @@
|
||||
#define BOSS_MEDAL_KINGGOAT_CRUSHER "King Goat Crusher"
|
||||
|
||||
// Medal hub IDs for boss-kill scores
|
||||
#define BOSS_SCORE "Bosses Killed"
|
||||
#define MINER_SCORE "BDMs Killed"
|
||||
#define FROST_MINER_SCORE "DFMs Killed"
|
||||
#define BUBBLEGUM_SCORE "Bubblegum Killed"
|
||||
#define COLOSSUS_SCORE "Colossus Killed"
|
||||
#define DRAKE_SCORE "Drakes Killed"
|
||||
#define HIEROPHANT_SCORE "Hierophants Killed"
|
||||
#define LEGION_SCORE "Legion Killed"
|
||||
#define BOSS_SCORE "Bosses Killed"
|
||||
#define MINER_SCORE "BDMs Killed"
|
||||
#define FROST_MINER_SCORE "DFMs Killed"
|
||||
#define BUBBLEGUM_SCORE "Bubblegum Killed"
|
||||
#define COLOSSUS_SCORE "Colossus Killed"
|
||||
#define DRAKE_SCORE "Drakes Killed"
|
||||
#define HIEROPHANT_SCORE "Hierophants Killed"
|
||||
#define LEGION_SCORE "Legion Killed"
|
||||
#define SWARMER_BEACON_SCORE "Swarmer Beacs Killed"
|
||||
#define WENDIGO_SCORE "Wendigos Killed"
|
||||
#define KINGGOAT_SCORE "King Goat Killed"
|
||||
#define TENDRIL_CLEAR_SCORE "Tendrils Killed"
|
||||
#define WENDIGO_SCORE "Wendigos Killed"
|
||||
#define KINGGOAT_SCORE "King Goat Killed"
|
||||
#define TENDRIL_CLEAR_SCORE "Tendrils Killed"
|
||||
|
||||
// DB ID for hardcore random mode
|
||||
#define HARDCORE_RANDOM_SCORE "Hardcore Random Score"
|
||||
|
||||
+10
-12
@@ -27,26 +27,24 @@
|
||||
#define DIAG_MECH_HUD "11"
|
||||
/// Bot HUDs
|
||||
#define DIAG_BOT_HUD "12"
|
||||
/// Circuit assembly health bar
|
||||
#define DIAG_CIRCUIT_HUD "13"
|
||||
/// Mech/Silicon tracking beacon, Circutry long range icon
|
||||
#define DIAG_TRACK_HUD "14"
|
||||
#define DIAG_TRACK_HUD "13"
|
||||
/// Airlock shock overlay
|
||||
#define DIAG_AIRLOCK_HUD "15"
|
||||
#define DIAG_AIRLOCK_HUD "14"
|
||||
/// Bot path indicators
|
||||
#define DIAG_PATH_HUD "16"
|
||||
#define DIAG_PATH_HUD "15"
|
||||
/// Gland indicators for abductors
|
||||
#define GLAND_HUD "17"
|
||||
#define SENTIENT_DISEASE_HUD "18"
|
||||
#define AI_DETECT_HUD "19"
|
||||
#define GLAND_HUD "16"
|
||||
#define SENTIENT_DISEASE_HUD "17"
|
||||
#define AI_DETECT_HUD "18"
|
||||
/// Displays launchpads' targeting reticle
|
||||
#define DIAG_LAUNCHPAD_HUD "22"
|
||||
#define DIAG_LAUNCHPAD_HUD "19"
|
||||
//for antag huds. these are used at the /mob level
|
||||
#define ANTAG_HUD "23"
|
||||
#define ANTAG_HUD "20"
|
||||
// for fans to identify pins
|
||||
#define FAN_HUD "24"
|
||||
#define FAN_HUD "21"
|
||||
/// Mech camera HUD
|
||||
#define DIAG_CAMERA_HUD "25"
|
||||
#define DIAG_CAMERA_HUD "22"
|
||||
|
||||
// SKYRAT EDIT ADDITION BEGIN - gun permits
|
||||
/// ammo of guns
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
/// Minimum alpha of footprints
|
||||
#define BLOODY_FOOTPRINT_BASE_ALPHA 20
|
||||
/// How much blood a regular blood splatter contains
|
||||
#define BLOOD_AMOUNT_PER_DECAL 50
|
||||
#define BLOOD_AMOUNT_PER_DECAL 50
|
||||
/// How much blood an item can have stuck on it
|
||||
#define BLOOD_ITEM_MAX 200
|
||||
#define BLOOD_ITEM_MAX 200
|
||||
/// How much blood a blood decal can contain
|
||||
#define BLOOD_POOL_MAX 300
|
||||
#define BLOOD_POOL_MAX 300
|
||||
/// How much blood a footprint need to at least contain
|
||||
#define BLOOD_FOOTPRINTS_MIN 5
|
||||
#define BLOOD_FOOTPRINTS_MIN 5
|
||||
|
||||
//Bloody shoe blood states
|
||||
/// Red blood
|
||||
|
||||
+24
-23
@@ -28,8 +28,9 @@
|
||||
#define COLOR_ALMOST_BLACK "#333333"
|
||||
#define COLOR_FULL_TONER_BLACK "#101010"
|
||||
#define COLOR_PRISONER_BLACK "#292929"
|
||||
#define COLOR_NEARLY_ALL_BLACK "#111111"
|
||||
#define COLOR_BLACK "#000000"
|
||||
#define COLOR_HALF_TRANSPARENT_BLACK "#0000007A"
|
||||
#define COLOR_HALF_TRANSPARENT_BLACK "#0000007A"
|
||||
|
||||
#define COLOR_RED "#FF0000"
|
||||
#define COLOR_SYNDIE_RED "#F10303"
|
||||
@@ -120,30 +121,30 @@
|
||||
#define COLOR_SOAPSTONE_GOLD "#FFD900"
|
||||
#define COLOR_SOAPSTONE_DIAMOND "#00ffee"
|
||||
|
||||
#define COLOR_GREEN_GRAY "#99BB76"
|
||||
#define COLOR_RED_GRAY "#B4696A"
|
||||
#define COLOR_PALE_BLUE_GRAY "#98C5DF"
|
||||
#define COLOR_PALE_GREEN_GRAY "#B7D993"
|
||||
#define COLOR_PALE_RED_GRAY "#D59998"
|
||||
#define COLOR_GREEN_GRAY "#99BB76"
|
||||
#define COLOR_RED_GRAY "#B4696A"
|
||||
#define COLOR_PALE_BLUE_GRAY "#98C5DF"
|
||||
#define COLOR_PALE_GREEN_GRAY "#B7D993"
|
||||
#define COLOR_PALE_RED_GRAY "#D59998"
|
||||
#define COLOR_PALE_PURPLE_GRAY "#CBB1CA"
|
||||
#define COLOR_PURPLE_GRAY "#AE8CA8"
|
||||
#define COLOR_PURPLE_GRAY "#AE8CA8"
|
||||
|
||||
//Color defines used by the assembly detailer.
|
||||
#define COLOR_ASSEMBLY_BLACK "#545454"
|
||||
#define COLOR_ASSEMBLY_BGRAY "#9497AB"
|
||||
#define COLOR_ASSEMBLY_WHITE "#E2E2E2"
|
||||
#define COLOR_ASSEMBLY_RED "#CC4242"
|
||||
#define COLOR_ASSEMBLY_ORANGE "#E39751"
|
||||
#define COLOR_ASSEMBLY_BEIGE "#AF9366"
|
||||
#define COLOR_ASSEMBLY_BROWN "#97670E"
|
||||
#define COLOR_ASSEMBLY_GOLD "#AA9100"
|
||||
#define COLOR_ASSEMBLY_YELLOW "#CECA2B"
|
||||
#define COLOR_ASSEMBLY_GURKHA "#999875"
|
||||
#define COLOR_ASSEMBLY_LGREEN "#789876"
|
||||
#define COLOR_ASSEMBLY_GREEN "#44843C"
|
||||
#define COLOR_ASSEMBLY_LBLUE "#5D99BE"
|
||||
#define COLOR_ASSEMBLY_BLUE "#38559E"
|
||||
#define COLOR_ASSEMBLY_PURPLE "#6F6192"
|
||||
#define COLOR_ASSEMBLY_BLACK "#545454"
|
||||
#define COLOR_ASSEMBLY_BGRAY "#9497AB"
|
||||
#define COLOR_ASSEMBLY_WHITE "#E2E2E2"
|
||||
#define COLOR_ASSEMBLY_RED "#CC4242"
|
||||
#define COLOR_ASSEMBLY_ORANGE "#E39751"
|
||||
#define COLOR_ASSEMBLY_BEIGE "#AF9366"
|
||||
#define COLOR_ASSEMBLY_BROWN "#97670E"
|
||||
#define COLOR_ASSEMBLY_GOLD "#AA9100"
|
||||
#define COLOR_ASSEMBLY_YELLOW "#CECA2B"
|
||||
#define COLOR_ASSEMBLY_GURKHA "#999875"
|
||||
#define COLOR_ASSEMBLY_LGREEN "#789876"
|
||||
#define COLOR_ASSEMBLY_GREEN "#44843C"
|
||||
#define COLOR_ASSEMBLY_LBLUE "#5D99BE"
|
||||
#define COLOR_ASSEMBLY_BLUE "#38559E"
|
||||
#define COLOR_ASSEMBLY_PURPLE "#6F6192"
|
||||
|
||||
///Colors for grayscale tools
|
||||
#define COLOR_TOOL_BLUE "#1861d5"
|
||||
@@ -303,4 +304,4 @@ GLOBAL_LIST_INIT(cable_colors, list(
|
||||
CABLE_COLOR_WHITE = CABLE_HEX_COLOR_WHITE,
|
||||
CABLE_COLOR_YELLOW = CABLE_HEX_COLOR_YELLOW,
|
||||
CABLE_COLOR_BROWN = CABLE_HEX_COLOR_BROWN
|
||||
))
|
||||
))
|
||||
|
||||
@@ -56,9 +56,9 @@
|
||||
#define FIRELOSS (1<<1)
|
||||
#define TOXLOSS (1<<2)
|
||||
#define OXYLOSS (1<<3)
|
||||
#define SHAME (1<<4)
|
||||
#define SHAME (1<<4)
|
||||
#define MANUAL_SUICIDE (1<<5) //suicide_act will do the actual killing.
|
||||
#define MANUAL_SUICIDE_NONLETHAL (1<<6) //when the suicide is conditionally lethal
|
||||
#define MANUAL_SUICIDE_NONLETHAL (1<<6) //when the suicide is conditionally lethal
|
||||
|
||||
#define EFFECT_STUN "stun"
|
||||
#define EFFECT_KNOCKDOWN "knockdown"
|
||||
|
||||
@@ -11,3 +11,5 @@
|
||||
/// When returned on a signal hooked to [COMSIG_ATOM_EXPLODE], [COMSIG_ATOM_INTERNAL_EXPLOSION], or [COMSIG_AREA_INTERNAL_EXPLOSION] it prevents the explosion from being propagated further.
|
||||
#define COMSIG_CANCEL_EXPLOSION (1<<0)
|
||||
|
||||
/// from [/atom/movable/proc/set_explosion_resistance] : (old_block, new_block)
|
||||
#define COMSIG_MOVABLE_EXPLOSION_BLOCK_CHANGED "explosion_block_changed"
|
||||
|
||||
@@ -133,5 +133,9 @@
|
||||
|
||||
/// From /mob/living/befriend() : (mob/living/new_friend)
|
||||
#define COMSIG_LIVING_BEFRIENDED "living_befriended"
|
||||
|
||||
/// From /obj/item/proc/pickup(): (/obj/item/picked_up_item)
|
||||
#define COMSIG_LIVING_PICKED_UP_ITEM "living_picked_up_item"
|
||||
|
||||
/// From /mob/living/unfriend() : (mob/living/old_friend)
|
||||
#define COMSIG_LIVING_UNFRIENDED "living_unfriended"
|
||||
|
||||
@@ -116,9 +116,12 @@
|
||||
#define MOB_DEADSAY_SIGNAL_INTERCEPT (1<<0)
|
||||
///from /mob/living/emote(): ()
|
||||
#define COMSIG_MOB_EMOTE "mob_emote"
|
||||
///from base of mob/swap_hand(): (obj/item)
|
||||
#define COMSIG_MOB_SWAP_HANDS "mob_swap_hands"
|
||||
///from base of mob/swap_hand(): (obj/item/currently_held_item)
|
||||
#define COMSIG_MOB_SWAPPING_HANDS "mob_swapping_hands"
|
||||
#define COMPONENT_BLOCK_SWAP (1<<0)
|
||||
/// from base of mob/swap_hand(): ()
|
||||
/// Performed after the hands are swapped.
|
||||
#define COMSIG_MOB_SWAP_HANDS "mob_swap_hands"
|
||||
///from base of /mob/verb/pointed: (atom/A)
|
||||
#define COMSIG_MOB_POINTED "mob_pointed"
|
||||
///Mob is trying to open the wires of a target [/atom], from /datum/wires/interactable(): (atom/target)
|
||||
@@ -171,5 +174,9 @@
|
||||
|
||||
///from living/flash_act(), when a mob is successfully flashed.
|
||||
#define COMSIG_MOB_FLASHED "mob_flashed"
|
||||
|
||||
/// from mob/get_status_tab_items(): (list/items)
|
||||
#define COMSIG_MOB_GET_STATUS_TAB_ITEMS "mob_get_status_tab_items"
|
||||
|
||||
/// from mob/proc/dropItemToGround()
|
||||
#define COMSIG_MOB_DROPPING_ITEM "mob_dropping_item"
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
/// Gibtonite will now explode
|
||||
#define GIBTONITE_DETONATE 3
|
||||
|
||||
/// For object explosion block calculation
|
||||
#define EXPLOSION_BLOCK_PROC -1
|
||||
|
||||
/// A wrapper for [/atom/proc/ex_act] to ensure that the explosion propagation and attendant signal are always handled.
|
||||
#define EX_ACT(target, args...)\
|
||||
if(!(target.flags_1 & PREVENT_CONTENTS_EXPLOSION_1)) { \
|
||||
|
||||
@@ -12,13 +12,5 @@
|
||||
/// Font used when signing on paper.
|
||||
#define SIGNATURE_FONT "Segoe Script"
|
||||
|
||||
//pda fonts
|
||||
#define MONO "Monospaced"
|
||||
#define VT "VT323"
|
||||
#define ORBITRON "Orbitron"
|
||||
#define SHARE "Share Tech Mono"
|
||||
|
||||
GLOBAL_LIST_INIT(pda_styles, sort_list(list(MONO, VT, ORBITRON, SHARE)))
|
||||
|
||||
/// Emoji icon set
|
||||
#define EMOJI_SET 'modular_skyrat/master_files/icons/emoji.dmi' // SKYRAT EDIT - ORIGINAL: 'icons/ui_icons/emoji/emoji.dmi'
|
||||
|
||||
@@ -117,7 +117,7 @@ DEFINE_BITFIELD(food_flags, list(
|
||||
///Amount of reagents you start with on crafted food excluding the used parts
|
||||
#define CRAFTED_FOOD_BASE_REAGENT_MODIFIER 0.7
|
||||
///Modifier of reagents you get when crafting food from the parts used
|
||||
#define CRAFTED_FOOD_INGREDIENT_REAGENT_MODIFIER 0.5
|
||||
#define CRAFTED_FOOD_INGREDIENT_REAGENT_MODIFIER 0.5
|
||||
|
||||
#define IS_EDIBLE(O) (O.GetComponent(/datum/component/edible))
|
||||
|
||||
|
||||
@@ -135,8 +135,8 @@
|
||||
#define ui_borg_lamp "CENTER-3:16, SOUTH:5"
|
||||
#define ui_borg_tablet "CENTER-4:16, SOUTH:5"
|
||||
#define ui_inv1 "CENTER-2:16,SOUTH:5"
|
||||
#define ui_inv2 "CENTER-1 :16,SOUTH:5"
|
||||
#define ui_inv3 "CENTER :16,SOUTH:5"
|
||||
#define ui_inv2 "CENTER-1 :16,SOUTH:5"
|
||||
#define ui_inv3 "CENTER :16,SOUTH:5"
|
||||
#define ui_borg_module "CENTER+1:16,SOUTH:5"
|
||||
#define ui_borg_store "CENTER+2:16,SOUTH:5"
|
||||
#define ui_borg_camera "CENTER+3:21,SOUTH:5"
|
||||
|
||||
@@ -146,8 +146,8 @@ DEFINE_BITFIELD(smoothing_flags, list(
|
||||
#define SMOOTH_GROUP_WINDOW_FULLTILE_PLASTITANIUM S_OBJ(24) ///turf/closed/indestructible/opsglass, /obj/structure/window/reinforced/plasma/plastitanium
|
||||
#define SMOOTH_GROUP_WINDOW_FULLTILE_SHUTTLE S_OBJ(25) ///obj/structure/window/reinforced/shuttle
|
||||
|
||||
#define SMOOTH_GROUP_LATTICE S_OBJ(31) ///obj/structure/lattice
|
||||
#define SMOOTH_GROUP_CATWALK S_OBJ(32) ///obj/structure/lattice/catwalk
|
||||
#define SMOOTH_GROUP_LATTICE S_OBJ(31) ///obj/structure/lattice
|
||||
#define SMOOTH_GROUP_CATWALK S_OBJ(32) ///obj/structure/lattice/catwalk
|
||||
|
||||
#define SMOOTH_GROUP_AIRLOCK S_OBJ(41) ///obj/machinery/door/airlock
|
||||
|
||||
|
||||
@@ -279,3 +279,4 @@ GLOBAL_LIST_INIT(book_types, typecacheof(list(
|
||||
#define is_unassigned_job(job_type) (istype(job_type, /datum/job/unassigned))
|
||||
|
||||
#define isprojectilespell(thing) (istype(thing, /datum/action/cooldown/spell/pointed/projectile))
|
||||
#define is_multi_tile_object(atom) (atom.bound_width > world.icon_size || atom.bound_height > world.icon_size)
|
||||
|
||||
@@ -240,6 +240,9 @@
|
||||
///Layer for screentips
|
||||
#define SCREENTIP_LAYER 4
|
||||
|
||||
/// Layer for tutorial instructions
|
||||
#define TUTORIAL_INSTRUCTIONS_LAYER 5
|
||||
|
||||
|
||||
#define LOBBY_BACKGROUND_LAYER 3
|
||||
#define LOBBY_BUTTON_LAYER 4
|
||||
|
||||
@@ -12,18 +12,18 @@
|
||||
|
||||
//Bay lighting engine shit, not in /code/modules/lighting because BYOND is being shit about it
|
||||
/// frequency, in 1/10ths of a second, of the lighting process
|
||||
#define LIGHTING_INTERVAL 5
|
||||
#define LIGHTING_INTERVAL 5
|
||||
|
||||
#define MINIMUM_USEFUL_LIGHT_RANGE 1.4
|
||||
|
||||
/// type of falloff to use for lighting; 1 for circular, 2 for square
|
||||
#define LIGHTING_FALLOFF 1
|
||||
#define LIGHTING_FALLOFF 1
|
||||
/// use lambertian shading for light sources
|
||||
#define LIGHTING_LAMBERTIAN 0
|
||||
#define LIGHTING_LAMBERTIAN 0
|
||||
/// height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone
|
||||
#define LIGHTING_HEIGHT 1
|
||||
#define LIGHTING_HEIGHT 1
|
||||
/// Value used to round lumcounts, values smaller than 1/129 don't matter (if they do, thanks sinking points), greater values will make lighting less precise, but in turn increase performance, VERY SLIGHTLY.
|
||||
#define LIGHTING_ROUND_VALUE (1 / 64)
|
||||
#define LIGHTING_ROUND_VALUE (1 / 64)
|
||||
|
||||
/// icon used for lighting shading effects
|
||||
#define LIGHTING_ICON 'icons/effects/lighting_object.dmi'
|
||||
@@ -32,17 +32,6 @@
|
||||
/// Set to zero to disable soft lighting. Luminosity changes then work if it's lit at all.
|
||||
#define LIGHTING_SOFT_THRESHOLD 0
|
||||
|
||||
/// If I were you I'd leave this alone.
|
||||
#define LIGHTING_BASE_MATRIX \
|
||||
list \
|
||||
( \
|
||||
1, 1, 1, 0, \
|
||||
1, 1, 1, 0, \
|
||||
1, 1, 1, 0, \
|
||||
1, 1, 1, 0, \
|
||||
0, 0, 0, 1 \
|
||||
) \
|
||||
|
||||
///How many tiles standard fires glow.
|
||||
#define LIGHT_RANGE_FIRE 3
|
||||
|
||||
|
||||
@@ -237,5 +237,9 @@
|
||||
|
||||
#define GET_TRUE_DIST(a, b) (a == null || b == null) ? -1 : max(abs(a.x -b.x), abs(a.y-b.y), abs(a.z-b.z))
|
||||
|
||||
//We used to use linear regression to approximate the answer, but Mloc realized this was actually faster.
|
||||
//And lo and behold, it is, and it's more accurate to boot.
|
||||
#define CHEAP_HYPOTENUSE(Ax, Ay, Bx, By) (sqrt(abs(Ax - Bx) ** 2 + abs(Ay - By) ** 2)) //A squared + B squared = C squared
|
||||
|
||||
/// The number of cells in a taxicab circle (rasterized diamond) of radius X.
|
||||
#define DIAMOND_AREA(X) (1 + 2*(X)*((X)+1))
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
/// Helper macro for compile time translation
|
||||
/// Helper macro for creating a matrix at the given offsets.
|
||||
/// Works at compile time.
|
||||
#define TRANSLATE_MATRIX(offset_x, offset_y) matrix(1, 0, (offset_x), 0, 1, (offset_y))
|
||||
|
||||
+12
-12
@@ -8,7 +8,7 @@
|
||||
|
||||
//movement intent defines for the m_intent var
|
||||
#define MOVE_INTENT_WALK "walk"
|
||||
#define MOVE_INTENT_RUN "run"
|
||||
#define MOVE_INTENT_RUN "run"
|
||||
|
||||
//Blood levels
|
||||
#define BLOOD_VOLUME_MAX_LETHAL 2150
|
||||
@@ -35,8 +35,8 @@
|
||||
#define MOB_SIZE_HUGE 4 // Use this for things you don't want bluespace body-bagged
|
||||
|
||||
//Ventcrawling defines
|
||||
#define VENTCRAWLER_NONE 0
|
||||
#define VENTCRAWLER_NUDE 1
|
||||
#define VENTCRAWLER_NONE 0
|
||||
#define VENTCRAWLER_NUDE 1
|
||||
#define VENTCRAWLER_ALWAYS 2
|
||||
|
||||
//Mob bio-types flags
|
||||
@@ -183,12 +183,12 @@
|
||||
#define BRAIN_TRAUMA_SPECIAL /datum/brain_trauma/special
|
||||
#define BRAIN_TRAUMA_MAGIC /datum/brain_trauma/magic
|
||||
|
||||
#define TRAUMA_RESILIENCE_BASIC 1 //Curable with chems
|
||||
#define TRAUMA_RESILIENCE_SURGERY 2 //Curable with brain surgery
|
||||
#define TRAUMA_RESILIENCE_LOBOTOMY 3 //Curable with lobotomy
|
||||
#define TRAUMA_RESILIENCE_WOUND 4 //Curable by healing the head wound
|
||||
#define TRAUMA_RESILIENCE_MAGIC 5 //Curable only with magic
|
||||
#define TRAUMA_RESILIENCE_ABSOLUTE 6 //This is here to stay
|
||||
#define TRAUMA_RESILIENCE_BASIC 1 //Curable with chems
|
||||
#define TRAUMA_RESILIENCE_SURGERY 2 //Curable with brain surgery
|
||||
#define TRAUMA_RESILIENCE_LOBOTOMY 3 //Curable with lobotomy
|
||||
#define TRAUMA_RESILIENCE_WOUND 4 //Curable by healing the head wound
|
||||
#define TRAUMA_RESILIENCE_MAGIC 5 //Curable only with magic
|
||||
#define TRAUMA_RESILIENCE_ABSOLUTE 6 //This is here to stay
|
||||
|
||||
//Limit of traumas for each resilience tier
|
||||
#define TRAUMA_LIMIT_BASIC 3
|
||||
@@ -349,7 +349,7 @@
|
||||
//determines if a mob can smash through it
|
||||
#define ENVIRONMENT_SMASH_NONE 0
|
||||
#define ENVIRONMENT_SMASH_STRUCTURES 1 //crates, lockers, ect
|
||||
#define ENVIRONMENT_SMASH_WALLS 2 //walls
|
||||
#define ENVIRONMENT_SMASH_WALLS 2 //walls
|
||||
#define ENVIRONMENT_SMASH_RWALLS 3 //rwalls
|
||||
|
||||
#define NO_SLIP_WHEN_WALKING (1<<0)
|
||||
@@ -420,12 +420,12 @@
|
||||
//#define AGE_MIN 17 //youngest a character can be //ORIGINAL
|
||||
#define AGE_MIN 18 //youngest a character can be //SKYRAT EDIT CHANGE - age
|
||||
#define AGE_MAX 85 //oldest a character can be
|
||||
#define AGE_MINOR 20 //legal age of space drinking and smoking
|
||||
#define AGE_MINOR 20 //legal age of space drinking and smoking
|
||||
#define WIZARD_AGE_MIN 30 //youngest a wizard can be
|
||||
#define APPRENTICE_AGE_MIN 29 //youngest an apprentice can be
|
||||
|
||||
#define SHOES_SLOWDOWN 0 //How much shoes slow you down by default. Negative values speed you up
|
||||
#define SHOES_SPEED_SLIGHT SHOES_SLOWDOWN - 1 // slightest speed boost to movement
|
||||
#define SHOES_SPEED_SLIGHT SHOES_SLOWDOWN - 1 // slightest speed boost to movement
|
||||
#define POCKET_STRIP_DELAY (4 SECONDS) //time taken to search somebody's pockets
|
||||
#define DOOR_CRUSH_DAMAGE 15 //the amount of damage that airlocks deal when they crush you
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#define PROGRAM_CATEGORY_CREW "Crew"
|
||||
#define PROGRAM_CATEGORY_ENGI "Engineering"
|
||||
#define PROGRAM_CATEGORY_SUPL "Supply"
|
||||
#define PROGRAM_CATEGORY_SCI "Science"
|
||||
#define PROGRAM_CATEGORY_SCI "Science"
|
||||
#define PROGRAM_CATEGORY_MISC "Other"
|
||||
|
||||
#define DETOMATIX_RESIST_MINOR 1
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#define MONKEY_SYRINGE_RETALIATION_PROB 20
|
||||
|
||||
// Probability per Life tick that the monkey will:
|
||||
/// probability that monkey aggro against the mob pulling it
|
||||
/// probability that monkey aggro against the mob pulling it
|
||||
#define MONKEY_PULL_AGGRO_PROB 5
|
||||
/// probability that monkey will get into mischief, i.e. finding/stealing items
|
||||
#define MONKEY_SHENANIGAN_PROB 20
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
#define NETWORK_PORT_UPDATE(LIST) if(LIST) { LIST["_updated"] = TRUE }
|
||||
#define NETWORK_PORT_CLEAR_UPDATE(LIST) if(LIST) { LIST["_updated"] = FALSE }
|
||||
#define NETWORK_PORT_SET_UPDATE(LIST) if(LIST) { LIST["_updated"] = TRUE }
|
||||
#define NETWORK_PORT_DISCONNECT(LIST) if(LIST) { LIST["_disconnected"] = TRUE }
|
||||
#define NETWORK_PORT_DISCONNECT(LIST) if(LIST) { LIST["_disconnected"] = TRUE }
|
||||
|
||||
/// Error codes
|
||||
#define NETWORK_ERROR_OK null
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
#define MACHINERY_LAYER_1 1
|
||||
|
||||
#define SOLAR_TRACK_OFF 0
|
||||
#define SOLAR_TRACK_TIMED 1
|
||||
#define SOLAR_TRACK_AUTO 2
|
||||
#define SOLAR_TRACK_OFF 0
|
||||
#define SOLAR_TRACK_TIMED 1
|
||||
#define SOLAR_TRACK_AUTO 2
|
||||
|
||||
///conversion ratio from joules to watts
|
||||
#define WATTS / 0.002
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#define CHAT_GHOSTWHISPER (1<<7)
|
||||
#define CHAT_GHOSTPDA (1<<8)
|
||||
#define CHAT_GHOSTRADIO (1<<9)
|
||||
#define CHAT_BANKCARD (1<<10)
|
||||
#define CHAT_BANKCARD (1<<10)
|
||||
#define CHAT_GHOSTLAWS (1<<11)
|
||||
#define CHAT_LOGIN_LOGOUT (1<<12)
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ Ask Mothblocks if they're around
|
||||
#define RAD_NO_INSULATION 1.0 // For things that shouldn't become irradiated for whatever reason
|
||||
#define RAD_VERY_LIGHT_INSULATION 0.9 // What girders have
|
||||
#define RAD_LIGHT_INSULATION 0.8
|
||||
#define RAD_MEDIUM_INSULATION 0.7 // What common walls have
|
||||
#define RAD_MEDIUM_INSULATION 0.7 // What common walls have
|
||||
#define RAD_HEAVY_INSULATION 0.6 // What reinforced walls have
|
||||
#define RAD_EXTREME_INSULATION 0.5 // What rad collectors have
|
||||
#define RAD_FULL_INSULATION 0 // Completely stops radiation from coming through
|
||||
|
||||
+20
-20
@@ -60,19 +60,19 @@
|
||||
// Frequencies are always odd numbers and range from 1201 to 1599.
|
||||
|
||||
#define FREQ_UPLINK 1211 // Dummy loopback frequency, used for radio uplink. Not seen in game.
|
||||
#define FREQ_SYNDICATE 1213 // Nuke op comms frequency, dark brown
|
||||
#define FREQ_CTF_RED 1215 // CTF red team comms frequency, red
|
||||
#define FREQ_CTF_BLUE 1217 // CTF blue team comms frequency, blue
|
||||
#define FREQ_CTF_GREEN 1219 // CTF green team comms frequency, green
|
||||
#define FREQ_CTF_YELLOW 1221 // CTF yellow team comms frequency, yellow
|
||||
#define FREQ_CENTCOM 1337 // CentCom comms frequency, gray
|
||||
#define FREQ_SUPPLY 1347 // Supply comms frequency, light brown
|
||||
#define FREQ_SERVICE 1349 // Service comms frequency, green
|
||||
#define FREQ_SCIENCE 1351 // Science comms frequency, plum
|
||||
#define FREQ_COMMAND 1353 // Command comms frequency, gold
|
||||
#define FREQ_MEDICAL 1355 // Medical comms frequency, soft blue
|
||||
#define FREQ_ENGINEERING 1357 // Engineering comms frequency, orange
|
||||
#define FREQ_SECURITY 1359 // Security comms frequency, red
|
||||
#define FREQ_SYNDICATE 1213 // Nuke op comms frequency, dark brown
|
||||
#define FREQ_CTF_RED 1215 // CTF red team comms frequency, red
|
||||
#define FREQ_CTF_BLUE 1217 // CTF blue team comms frequency, blue
|
||||
#define FREQ_CTF_GREEN 1219 // CTF green team comms frequency, green
|
||||
#define FREQ_CTF_YELLOW 1221 // CTF yellow team comms frequency, yellow
|
||||
#define FREQ_CENTCOM 1337 // CentCom comms frequency, gray
|
||||
#define FREQ_SUPPLY 1347 // Supply comms frequency, light brown
|
||||
#define FREQ_SERVICE 1349 // Service comms frequency, green
|
||||
#define FREQ_SCIENCE 1351 // Science comms frequency, plum
|
||||
#define FREQ_COMMAND 1353 // Command comms frequency, gold
|
||||
#define FREQ_MEDICAL 1355 // Medical comms frequency, soft blue
|
||||
#define FREQ_ENGINEERING 1357 // Engineering comms frequency, orange
|
||||
#define FREQ_SECURITY 1359 // Security comms frequency, red
|
||||
|
||||
#define FREQ_HOLOGRID_SOLUTION 1433
|
||||
#define FREQ_STATUS_DISPLAYS 1435
|
||||
@@ -82,23 +82,23 @@
|
||||
// This represents 1/8th of the available spectrum.
|
||||
|
||||
#define FREQ_NAV_BEACON 1445
|
||||
#define FREQ_AI_PRIVATE 1447 // AI private comms frequency, magenta
|
||||
#define FREQ_AI_PRIVATE 1447 // AI private comms frequency, magenta
|
||||
#define FREQ_PRESSURE_PLATE 1447
|
||||
#define FREQ_ELECTROPACK 1449
|
||||
#define FREQ_MAGNETS 1449
|
||||
#define FREQ_LOCATOR_IMPLANT 1451
|
||||
#define FREQ_SIGNALER 1457 // the default for new signalers
|
||||
#define FREQ_COMMON 1459 // Common comms frequency, dark green
|
||||
#define FREQ_SIGNALER 1457 // the default for new signalers
|
||||
#define FREQ_COMMON 1459 // Common comms frequency, dark green
|
||||
|
||||
#define MAX_FREQ 1489 // ------------------------------------------------------
|
||||
|
||||
#define MAX_FREE_FREQ 1599 // -------------------------------------------------
|
||||
|
||||
// Transmission types.
|
||||
#define TRANSMISSION_WIRE 0 // some sort of wired connection, not used
|
||||
#define TRANSMISSION_RADIO 1 // electromagnetic radiation (default)
|
||||
#define TRANSMISSION_SUBSPACE 2 // subspace transmission (headsets only)
|
||||
#define TRANSMISSION_SUPERSPACE 3 // reaches independent (CentCom) radios only
|
||||
#define TRANSMISSION_WIRE 0 // some sort of wired connection, not used
|
||||
#define TRANSMISSION_RADIO 1 // electromagnetic radiation (default)
|
||||
#define TRANSMISSION_SUBSPACE 2 // subspace transmission (headsets only)
|
||||
#define TRANSMISSION_SUPERSPACE 3 // reaches independent (CentCom) radios only
|
||||
|
||||
// Filter types, used as an optimization to avoid unnecessary proc calls.
|
||||
#define RADIO_SIGNALER "signaler"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#define RESONATOR_MODE_AUTO 1
|
||||
#define RESONATOR_MODE_AUTO 1
|
||||
#define RESONATOR_MODE_MANUAL 2
|
||||
#define RESONATOR_MODE_MATRIX 3
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*
|
||||
* make sure you add an update to the schema_version stable in the db changelog
|
||||
*/
|
||||
#define DB_MINOR_VERSION 24
|
||||
#define DB_MINOR_VERSION 25
|
||||
|
||||
|
||||
//! ## Timing subsystem
|
||||
|
||||
@@ -510,6 +510,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_PARALYSIS "paralysis"
|
||||
/// Used for limbs.
|
||||
#define TRAIT_DISABLED_BY_WOUND "disabled-by-wound"
|
||||
/// This movable atom has the explosive block element
|
||||
#define TRAIT_BLOCKING_EXPLOSIVES "blocking_explosives"
|
||||
|
||||
/// Mobs with this trait can't send the mining shuttle console when used outside the station itself
|
||||
#define TRAIT_FORBID_MINING_SHUTTLE_CONSOLE_OUTSIDE_STATION "forbid_mining_shuttle_console_outside_station"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#define RECT_TURFS(H_RADIUS, V_RADIUS, CENTER) \
|
||||
block( \
|
||||
locate(max(CENTER.x-(H_RADIUS),1), max(CENTER.y-(V_RADIUS),1), CENTER.z), \
|
||||
locate(max(CENTER.x-(H_RADIUS),1), max(CENTER.y-(V_RADIUS),1), CENTER.z), \
|
||||
locate(min(CENTER.x+(H_RADIUS),world.maxx), min(CENTER.y+(V_RADIUS),world.maxy), CENTER.z) \
|
||||
)
|
||||
|
||||
|
||||
@@ -11,12 +11,6 @@
|
||||
return null
|
||||
return format_text ? format_text(checked_area.name) : checked_area.name
|
||||
|
||||
//We used to use linear regression to approximate the answer, but Mloc realized this was actually faster.
|
||||
//And lo and behold, it is, and it's more accurate to boot.
|
||||
///Calculate the hypotenuse cheaply (this should be in maths.dm)
|
||||
/proc/cheap_hypotenuse(Ax, Ay, Bx, By)
|
||||
return sqrt(abs(Ax - Bx) ** 2 + abs(Ay - By) ** 2) //A squared + B squared = C squared
|
||||
|
||||
/** toggle_organ_decay
|
||||
* inputs: first_object (object to start with)
|
||||
* outputs:
|
||||
|
||||
@@ -18,14 +18,26 @@
|
||||
y += view_size[2]
|
||||
if(findtext(screen_loc, "SOUTH"))
|
||||
y += world.icon_size
|
||||
// Cut out everything we just parsed
|
||||
screen_loc = cut_relative_direction(screen_loc)
|
||||
|
||||
var/list/x_and_y = splittext(screen_loc, ",")
|
||||
|
||||
var/list/x_pack = splittext(x_and_y[1], ":")
|
||||
var/list/y_pack = splittext(x_and_y[2], ":")
|
||||
x += text2num(x_pack[1]) * world.icon_size
|
||||
y += text2num(y_pack[1]) * world.icon_size
|
||||
|
||||
var/x_coord = x_pack[1]
|
||||
var/y_coord = y_pack[1]
|
||||
|
||||
if (findtext(x_coord, "CENTER"))
|
||||
x += view_size[1] / 2
|
||||
|
||||
if (findtext(y_coord, "CENTER"))
|
||||
y += view_size[2] / 2
|
||||
|
||||
x_coord = text2num(cut_relative_direction(x_coord))
|
||||
y_coord = text2num(cut_relative_direction(y_coord))
|
||||
|
||||
x += x_coord * world.icon_size
|
||||
y += y_coord * world.icon_size
|
||||
|
||||
if(length(x_pack) > 1)
|
||||
x += text2num(x_pack[2])
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
/atom/movable/screen/ghost/minigames_menu
|
||||
name ="Minigames"
|
||||
icon_state = "minigames"
|
||||
|
||||
|
||||
/atom/movable/screen/ghost/minigames_menu/Click()
|
||||
var/mob/dead/observer/observer = usr
|
||||
observer.open_minigames_menu()
|
||||
@@ -88,7 +88,7 @@
|
||||
static_inventory += using
|
||||
|
||||
using = new /atom/movable/screen/language_menu
|
||||
using.screen_loc = ui_ghost_language_menu
|
||||
using.screen_loc = ui_ghost_language_menu
|
||||
using.icon = ui_style
|
||||
using.hud = src
|
||||
static_inventory += using
|
||||
|
||||
@@ -59,7 +59,15 @@
|
||||
if (after_attack_secondary_result == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN || after_attack_secondary_result == SECONDARY_ATTACK_CONTINUE_CHAIN)
|
||||
return TRUE
|
||||
|
||||
return afterattack(target, user, TRUE, params) == TRUE
|
||||
var/afterattack_result = afterattack(target, user, TRUE, params)
|
||||
|
||||
if (!(afterattack_result & AFTERATTACK_PROCESSED_ITEM) && isitem(target))
|
||||
if (isnull(user.get_inactive_held_item()))
|
||||
SStutorials.suggest_tutorial(user, /datum/tutorial/switch_hands, params2list(params))
|
||||
else
|
||||
SStutorials.suggest_tutorial(user, /datum/tutorial/drop, params2list(params))
|
||||
|
||||
return afterattack_result & TRUE //this is really stupid but its needed because afterattack can return TRUE | FLAGS.
|
||||
|
||||
/// Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown.
|
||||
/obj/item/proc/attack_self(mob/user, modifiers)
|
||||
|
||||
@@ -414,3 +414,4 @@
|
||||
|
||||
/datum/config_entry/flag/disallow_circuit_sounds
|
||||
|
||||
/datum/config_entry/flag/give_tutorials_without_db
|
||||
|
||||
@@ -649,3 +649,5 @@
|
||||
default = 50
|
||||
|
||||
/datum/config_entry/string/morgue_cadaver_override_species
|
||||
|
||||
/datum/config_entry/flag/toast_notification_on_init
|
||||
|
||||
@@ -267,6 +267,9 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
log_world(msg)
|
||||
|
||||
|
||||
if(world.system_type == MS_WINDOWS && CONFIG_GET(flag/toast_notification_on_init) && !length(GLOB.clients))
|
||||
world.shelleo("start /min powershell -ExecutionPolicy Bypass -File tools/initToast/initToast.ps1 -name \"[world.name]\" -icon %CD%\\icons\\ui_icons\\common\\tg_16.png -port [world.port]")
|
||||
|
||||
// Set world options.
|
||||
world.change_fps(CONFIG_GET(number/fps))
|
||||
var/initialized_tod = REALTIMEOFDAY
|
||||
|
||||
@@ -119,30 +119,31 @@ SUBSYSTEM_DEF(explosions)
|
||||
var/x0 = epicenter.x
|
||||
var/y0 = epicenter.y
|
||||
var/list/wipe_colours = list()
|
||||
for(var/turf/T in spiral_range_turfs(max_range, epicenter))
|
||||
wipe_colours += T
|
||||
var/dist = cheap_hypotenuse(T.x, T.y, x0, y0)
|
||||
var/list/cached_exp_block = list()
|
||||
for(var/turf/explode in prepare_explosion_turfs(max_range, epicenter))
|
||||
wipe_colours += explode
|
||||
var/our_x = explode.x
|
||||
var/our_y = explode.y
|
||||
var/dist = CHEAP_HYPOTENUSE(our_x, our_y, x0, y0)
|
||||
|
||||
if(newmode == "Yes")
|
||||
var/turf/TT = T
|
||||
while(TT != epicenter)
|
||||
TT = get_step_towards(TT,epicenter)
|
||||
if(TT.density)
|
||||
dist += TT.explosion_block
|
||||
|
||||
for(var/obj/O in T)
|
||||
var/the_block = O.explosion_block
|
||||
dist += the_block == EXPLOSION_BLOCK_PROC ? O.GetExplosionBlock() : the_block
|
||||
if(explode != epicenter)
|
||||
var/our_block = cached_exp_block[get_step_towards(explode, epicenter)]
|
||||
dist += our_block
|
||||
cached_exp_block[explode] = our_block + explode.explosive_resistance
|
||||
else
|
||||
cached_exp_block[explode] = explode.explosive_resistance
|
||||
|
||||
dist = round(dist, 0.01)
|
||||
if(dist < dev)
|
||||
T.color = "red"
|
||||
T.maptext = MAPTEXT("Dev")
|
||||
explode.color = "red"
|
||||
explode.maptext = MAPTEXT("[dist]")
|
||||
else if (dist < heavy)
|
||||
T.color = "yellow"
|
||||
T.maptext = MAPTEXT("Heavy")
|
||||
explode.color = "yellow"
|
||||
explode.maptext = MAPTEXT("[dist]")
|
||||
else if (dist < light)
|
||||
T.color = "blue"
|
||||
T.maptext = MAPTEXT("Light")
|
||||
explode.color = "blue"
|
||||
explode.maptext = MAPTEXT("[dist]")
|
||||
else
|
||||
continue
|
||||
|
||||
@@ -398,84 +399,82 @@ SUBSYSTEM_DEF(explosions)
|
||||
for(var/mob/living/L in viewers(flash_range, epicenter))
|
||||
L.flash_act()
|
||||
|
||||
var/list/affected_turfs = GatherSpiralTurfs(max_range, epicenter)
|
||||
var/list/affected_turfs = prepare_explosion_turfs(max_range, epicenter)
|
||||
|
||||
var/reactionary = CONFIG_GET(flag/reactionary_explosions)
|
||||
var/list/cached_exp_block
|
||||
|
||||
if(reactionary)
|
||||
cached_exp_block = CaculateExplosionBlock(affected_turfs)
|
||||
// this list is setup in the form position -> block for that position
|
||||
// we assert that turfs will be processed closed to farthest, so we can build this as we go along
|
||||
// This is gonna be an array, index'd by turfs
|
||||
var/list/cached_exp_block = list()
|
||||
|
||||
//lists are guaranteed to contain at least 1 turf at this point
|
||||
//we presuppose that we'll be iterating away from the epicenter
|
||||
for(var/turf/explode as anything in affected_turfs)
|
||||
var/our_x = explode.x
|
||||
var/our_y = explode.y
|
||||
var/dist = CHEAP_HYPOTENUSE(our_x, our_y, x0, y0)
|
||||
|
||||
for(var/TI in affected_turfs)
|
||||
var/turf/T = TI
|
||||
var/init_dist = cheap_hypotenuse(T.x, T.y, x0, y0)
|
||||
var/dist = init_dist
|
||||
|
||||
// Using this pattern, block will flow out from blocking turfs, essentially caching the recursion
|
||||
// This is safe because if get_step_towards is ever anything but caridnally off, it'll do a diagonal move
|
||||
// So we always sample from a "loop" closer
|
||||
// It's kind of behaviorly unimpressive that that's a problem for the future
|
||||
if(reactionary)
|
||||
var/turf/Trajectory = T
|
||||
while(Trajectory != epicenter)
|
||||
Trajectory = get_step_towards(Trajectory, epicenter)
|
||||
dist += cached_exp_block[Trajectory]
|
||||
if(explode == epicenter)
|
||||
cached_exp_block[explode] = explode.explosive_resistance
|
||||
else
|
||||
var/our_block = cached_exp_block[get_step_towards(explode, epicenter)]
|
||||
dist += our_block
|
||||
cached_exp_block[explode] = our_block + explode.explosive_resistance
|
||||
|
||||
var/flame_dist = dist < flame_range
|
||||
var/throw_dist = dist
|
||||
|
||||
var/severity = EXPLODE_NONE
|
||||
if(dist < devastation_range)
|
||||
dist = EXPLODE_DEVASTATE
|
||||
severity = EXPLODE_DEVASTATE
|
||||
else if(dist < heavy_impact_range)
|
||||
dist = EXPLODE_HEAVY
|
||||
severity = EXPLODE_HEAVY
|
||||
else if(dist < light_impact_range)
|
||||
dist = EXPLODE_LIGHT
|
||||
else
|
||||
dist = EXPLODE_NONE
|
||||
severity = EXPLODE_LIGHT
|
||||
|
||||
if(T == epicenter) // Ensures explosives detonating from bags trigger other explosives in that bag
|
||||
if(explode == epicenter) // Ensures explosives detonating from bags trigger other explosives in that bag
|
||||
var/list/items = list()
|
||||
for(var/I in T)
|
||||
var/atom/A = I
|
||||
if (length(A.contents) && !(A.flags_1 & PREVENT_CONTENTS_EXPLOSION_1)) //The atom/contents_explosion() proc returns null if the contents ex_acting has been handled by the atom, and TRUE if it hasn't.
|
||||
items += A.get_all_contents(ignore_flag_1 = PREVENT_CONTENTS_EXPLOSION_1)
|
||||
if(isliving(A))
|
||||
items -= A //Stops mobs from taking double damage from explosions originating from them/their turf, such as from projectiles
|
||||
for(var/thing in items)
|
||||
var/atom/movable/movable_thing = thing
|
||||
if(QDELETED(movable_thing))
|
||||
continue
|
||||
switch(dist)
|
||||
if(EXPLODE_DEVASTATE)
|
||||
SSexplosions.high_mov_atom += movable_thing
|
||||
if(EXPLODE_HEAVY)
|
||||
SSexplosions.med_mov_atom += movable_thing
|
||||
if(EXPLODE_LIGHT)
|
||||
SSexplosions.low_mov_atom += movable_thing
|
||||
switch(dist)
|
||||
for(var/atom/holder as anything in explode)
|
||||
if (length(holder.contents) && !(holder.flags_1 & PREVENT_CONTENTS_EXPLOSION_1)) //The atom/contents_explosion() proc returns null if the contents ex_acting has been handled by the atom, and TRUE if it hasn't.
|
||||
items += holder.get_all_contents(ignore_flag_1 = PREVENT_CONTENTS_EXPLOSION_1)
|
||||
if(isliving(holder))
|
||||
items -= holder //Stops mobs from taking double damage from explosions originating from them/their turf, such as from projectiles
|
||||
switch(severity)
|
||||
if(EXPLODE_DEVASTATE)
|
||||
SSexplosions.high_mov_atom += items
|
||||
if(EXPLODE_HEAVY)
|
||||
SSexplosions.med_mov_atom += items
|
||||
if(EXPLODE_LIGHT)
|
||||
SSexplosions.low_mov_atom += items
|
||||
switch(severity)
|
||||
if(EXPLODE_DEVASTATE)
|
||||
SSexplosions.highturf += T
|
||||
SSexplosions.highturf += explode
|
||||
if(EXPLODE_HEAVY)
|
||||
SSexplosions.medturf += T
|
||||
SSexplosions.medturf += explode
|
||||
if(EXPLODE_LIGHT)
|
||||
SSexplosions.lowturf += T
|
||||
SSexplosions.lowturf += explode
|
||||
|
||||
//SKYRAT EDIT ADDITION
|
||||
for(var/obj/machinery/light/iterating_light in T)
|
||||
for(var/obj/machinery/light/iterating_light in explode)
|
||||
iterating_light.start_flickering()
|
||||
//SKYRAT EDIT END
|
||||
if(flame_dist && prob(40) && !isspaceturf(T) && !T.density)
|
||||
flameturf += T
|
||||
|
||||
if(prob(40) && dist < flame_range && !isspaceturf(explode) && !explode.density)
|
||||
flameturf += explode
|
||||
|
||||
//--- THROW ITEMS AROUND ---
|
||||
var/throw_dir = get_dir(epicenter,T)
|
||||
var/throw_range = max_range-throw_dist
|
||||
var/list/throwingturf = T.explosion_throw_details
|
||||
if (throwingturf)
|
||||
if (throwingturf[1] < throw_range)
|
||||
throwingturf[1] = throw_range
|
||||
throwingturf[2] = throw_dir
|
||||
if (explode.explosion_throw_details)
|
||||
var/list/throwingturf = explode.explosion_throw_details
|
||||
if (throwingturf[1] < max_range - dist)
|
||||
throwingturf[1] = max_range - dist
|
||||
throwingturf[2] = get_dir(epicenter, explode)
|
||||
throwingturf[3] = max_range
|
||||
else
|
||||
T.explosion_throw_details = list(throw_range, throw_dir, max_range)
|
||||
throwturf += T
|
||||
explode.explosion_throw_details = list(max_range - dist, get_dir(epicenter, explode), max_range)
|
||||
throwturf += explode
|
||||
|
||||
|
||||
var/took = (REALTIMEOFDAY - started_at) / 10
|
||||
@@ -593,68 +592,40 @@ SUBSYSTEM_DEF(explosions)
|
||||
#undef FREQ_UPPER
|
||||
#undef FREQ_LOWER
|
||||
|
||||
/datum/controller/subsystem/explosions/proc/GatherSpiralTurfs(range, turf/epicenter)
|
||||
/// Returns a list of turfs in X range from the epicenter
|
||||
/// Returns in a unique order, spiraling outwards
|
||||
/// This is done to ensure our progressive cache of blast resistance is always valid
|
||||
/// This is quite fast
|
||||
/proc/prepare_explosion_turfs(range, turf/epicenter)
|
||||
var/list/outlist = list()
|
||||
var/center = epicenter
|
||||
var/dist = range
|
||||
if(!dist)
|
||||
outlist += center
|
||||
return outlist
|
||||
// Add in the center
|
||||
outlist += epicenter
|
||||
|
||||
var/turf/t_center = get_turf(center)
|
||||
if(!t_center)
|
||||
return outlist
|
||||
var/our_x = epicenter.x
|
||||
var/our_y = epicenter.y
|
||||
var/our_z = epicenter.z
|
||||
|
||||
var/list/L = outlist
|
||||
var/turf/T
|
||||
var/y
|
||||
var/x
|
||||
var/c_dist = 1
|
||||
L += t_center
|
||||
var/max_x = world.maxx
|
||||
var/max_y = world.maxy
|
||||
for(var/i in 1 to range)
|
||||
var/lowest_x = our_x - i
|
||||
var/lowest_y = our_y - i
|
||||
var/highest_x = our_x + i
|
||||
var/highest_y = our_y + i
|
||||
// top left to one before top right
|
||||
if(highest_y <= max_y)
|
||||
outlist += block(locate(max(lowest_x, 1), highest_y, our_z), locate(min(highest_x - 1, max_x), highest_y, our_z))
|
||||
// top right to one before bottom right
|
||||
if(highest_x <= max_x)
|
||||
outlist += block(locate(highest_x, min(highest_y, max_y), our_z), locate(highest_x, max(lowest_y + 1, 1), our_z))
|
||||
// bottom right to one before bottom left
|
||||
if(lowest_y >= 1)
|
||||
outlist += block(locate(min(highest_x, max_x), lowest_y, our_z), locate(max(lowest_x + 1, 1), lowest_y, our_z))
|
||||
// bottom left to one before top left
|
||||
if(lowest_x >= 1)
|
||||
outlist += block(locate(lowest_x, max(lowest_y, 1), our_z), locate(lowest_x, min(highest_y - 1, max_y), our_z))
|
||||
|
||||
while( c_dist <= dist )
|
||||
y = t_center.y + c_dist
|
||||
x = t_center.x - c_dist + 1
|
||||
for(x in x to t_center.x+c_dist)
|
||||
T = locate(x,y,t_center.z)
|
||||
if(T)
|
||||
L += T
|
||||
|
||||
y = t_center.y + c_dist - 1
|
||||
x = t_center.x + c_dist
|
||||
for(y in t_center.y-c_dist to y)
|
||||
T = locate(x,y,t_center.z)
|
||||
if(T)
|
||||
L += T
|
||||
|
||||
y = t_center.y - c_dist
|
||||
x = t_center.x + c_dist - 1
|
||||
for(x in t_center.x-c_dist to x)
|
||||
T = locate(x,y,t_center.z)
|
||||
if(T)
|
||||
L += T
|
||||
|
||||
y = t_center.y - c_dist + 1
|
||||
x = t_center.x - c_dist
|
||||
for(y in y to t_center.y+c_dist)
|
||||
T = locate(x,y,t_center.z)
|
||||
if(T)
|
||||
L += T
|
||||
c_dist++
|
||||
. = L
|
||||
|
||||
/datum/controller/subsystem/explosions/proc/CaculateExplosionBlock(list/affected_turfs)
|
||||
. = list()
|
||||
var/I
|
||||
for(I in 1 to affected_turfs.len) // we cache the explosion block rating of every turf in the explosion area
|
||||
var/turf/T = affected_turfs[I]
|
||||
var/current_exp_block = T.density ? T.explosion_block : 0
|
||||
|
||||
for(var/obj/O in T)
|
||||
var/the_block = O.explosion_block
|
||||
current_exp_block += the_block == EXPLOSION_BLOCK_PROC ? O.GetExplosionBlock() : the_block
|
||||
|
||||
.[T] = current_exp_block
|
||||
return outlist
|
||||
|
||||
/datum/controller/subsystem/explosions/fire(resumed = 0)
|
||||
if (!is_exploding())
|
||||
@@ -743,15 +714,15 @@ SUBSYSTEM_DEF(explosions)
|
||||
for (var/thing in throw_turf)
|
||||
if (!thing)
|
||||
continue
|
||||
var/turf/T = thing
|
||||
var/list/L = T.explosion_throw_details
|
||||
T.explosion_throw_details = null
|
||||
if (length(L) != 3)
|
||||
var/turf/explode = thing
|
||||
var/list/details = explode.explosion_throw_details
|
||||
explode.explosion_throw_details = null
|
||||
if (length(details) != 3)
|
||||
continue
|
||||
var/throw_range = L[1]
|
||||
var/throw_dir = L[2]
|
||||
var/max_range = L[3]
|
||||
for(var/atom/movable/A in T)
|
||||
var/throw_range = details[1]
|
||||
var/throw_dir = details[2]
|
||||
var/max_range = details[3]
|
||||
for(var/atom/movable/A in explode)
|
||||
if(QDELETED(A))
|
||||
continue
|
||||
if(!A.anchored && A.move_resist != INFINITY)
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/// Namespace for housing code relating to giving contextual tutorials to users.
|
||||
SUBSYSTEM_DEF(tutorials)
|
||||
name = "Tutorials"
|
||||
flags = SS_NO_FIRE
|
||||
|
||||
/// A mapping of /datum/tutorial type to their manager singleton.
|
||||
/// You probably shouldn't be indexing this directly.
|
||||
var/list/datum/tutorial_manager/tutorial_managers = list()
|
||||
|
||||
VAR_PRIVATE/list/datum/tutorial_manager/tutorial_managers_by_key = list()
|
||||
|
||||
/datum/controller/subsystem/tutorials/Initialize()
|
||||
init_tutorial_managers()
|
||||
load_initial_tutorial_completions()
|
||||
RegisterSignal(SSdcs, COMSIG_GLOB_CLIENT_CONNECT, PROC_REF(on_client_connect))
|
||||
|
||||
return SS_INIT_SUCCESS
|
||||
|
||||
/// Will suggest the passed tutorial type to the user.
|
||||
/// Will check that they should actually see it, e.g. hasn't completed it yet, etc.
|
||||
/// Then, calls `/datum/tutorial/subtype/perform` with the extra arguments passed in.
|
||||
/datum/controller/subsystem/tutorials/proc/suggest_tutorial(mob/user, datum/tutorial/tutorial_type, ...)
|
||||
var/datum/tutorial_manager/tutorial_manager = tutorial_managers[tutorial_type]
|
||||
if (isnull(tutorial_manager))
|
||||
CRASH("[tutorial_type] is not a valid tutorial type")
|
||||
|
||||
if (!tutorial_manager.should_run(user))
|
||||
return
|
||||
|
||||
INVOKE_ASYNC(tutorial_manager, TYPE_PROC_REF(/datum/tutorial_manager, try_perform), user, args.Copy(3))
|
||||
|
||||
/datum/controller/subsystem/tutorials/proc/init_tutorial_managers()
|
||||
PRIVATE_PROC(TRUE)
|
||||
|
||||
for (var/datum/tutorial/tutorial_type as anything in subtypesof(/datum/tutorial))
|
||||
var/datum/tutorial_manager/tutorial_manager = new /datum/tutorial_manager(tutorial_type)
|
||||
tutorial_managers[tutorial_type] = tutorial_manager
|
||||
tutorial_managers_by_key[tutorial_manager.get_key()] = tutorial_manager
|
||||
|
||||
/datum/controller/subsystem/tutorials/proc/load_initial_tutorial_completions()
|
||||
PRIVATE_PROC(TRUE)
|
||||
set waitfor = FALSE // There's no reason to halt init for this
|
||||
|
||||
var/list/ckey_options = list()
|
||||
var/list/ckeys = list()
|
||||
|
||||
for (var/client/client as anything in GLOB.clients)
|
||||
var/ckey = client?.ckey
|
||||
if (!ckey)
|
||||
continue // client shenanigans, never trust
|
||||
|
||||
var/index = ckeys.len + 1
|
||||
ckey_options += ":ckey[index]"
|
||||
ckeys["ckey[index]"] = ckey
|
||||
|
||||
if (ckey_options.len == 0)
|
||||
return
|
||||
|
||||
var/datum/db_query/select_all_query = SSdbcore.NewQuery(
|
||||
"SELECT ckey, tutorial_key FROM [format_table_name("tutorial_completions")] WHERE ckey in ([ckey_options.Join(", ")])",
|
||||
ckeys,
|
||||
)
|
||||
|
||||
if (!select_all_query.Execute())
|
||||
qdel(select_all_query)
|
||||
return
|
||||
|
||||
while (select_all_query.NextRow())
|
||||
var/ckey = select_all_query.item[1]
|
||||
var/tutorial_key = select_all_query.item[2]
|
||||
|
||||
mark_ckey_completed_tutorial(ckey, tutorial_key)
|
||||
|
||||
qdel(select_all_query)
|
||||
|
||||
/datum/controller/subsystem/tutorials/proc/on_client_connect(datum/source, client/client)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/ckey = client.ckey
|
||||
if (!ckey)
|
||||
return
|
||||
|
||||
INVOKE_ASYNC(src, PROC_REF(check_completed_tutorials_for_ckey), ckey)
|
||||
|
||||
/datum/controller/subsystem/tutorials/proc/check_completed_tutorials_for_ckey(ckey)
|
||||
if (!SSdbcore.IsConnected())
|
||||
return
|
||||
|
||||
var/datum/db_query/select_tutorials_for_ckey = SSdbcore.NewQuery(
|
||||
"SELECT tutorial_key FROM [format_table_name("tutorial_completions")] WHERE ckey = :ckey",
|
||||
list("ckey" = ckey)
|
||||
)
|
||||
|
||||
if (!select_tutorials_for_ckey.Execute())
|
||||
return
|
||||
|
||||
while (select_tutorials_for_ckey.NextRow())
|
||||
var/tutorial_key = select_tutorials_for_ckey.item[1]
|
||||
|
||||
mark_ckey_completed_tutorial(ckey, tutorial_key)
|
||||
|
||||
qdel(select_tutorials_for_ckey)
|
||||
|
||||
/datum/controller/subsystem/tutorials/proc/mark_ckey_completed_tutorial(ckey, tutorial_key)
|
||||
var/datum/tutorial_manager/tutorial_manager = tutorial_managers_by_key[tutorial_key]
|
||||
if (isnull(tutorial_manager))
|
||||
// Not necessarily a bug.
|
||||
// Could be an outdated server or a removed tutorial.
|
||||
return
|
||||
|
||||
tutorial_manager.mark_as_completed(ckey)
|
||||
@@ -127,6 +127,7 @@
|
||||
/datum/component/drift/proc/loop_death(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
drifting_loop = null
|
||||
UnregisterSignal(parent, COMSIG_MOVABLE_NEWTONIAN_MOVE) // We won't block a component from replacing us anymore
|
||||
|
||||
/datum/component/drift/proc/handle_move(datum/source, old_loc)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
return // blocked wield from item
|
||||
wielded = TRUE
|
||||
ADD_TRAIT(parent, TRAIT_WIELDED, REF(src))
|
||||
RegisterSignal(user, COMSIG_MOB_SWAP_HANDS, PROC_REF(on_swap_hands))
|
||||
RegisterSignal(user, COMSIG_MOB_SWAPPING_HANDS, PROC_REF(on_swapping_hands))
|
||||
wield_callback?.Invoke(parent, user)
|
||||
|
||||
// update item stats and name
|
||||
@@ -307,7 +307,7 @@
|
||||
/**
|
||||
* on_swap_hands Triggers on swapping hands, blocks swap if the other hand is busy
|
||||
*/
|
||||
/datum/component/two_handed/proc/on_swap_hands(mob/user, obj/item/held_item)
|
||||
/datum/component/two_handed/proc/on_swapping_hands(mob/user, obj/item/held_item)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!held_item)
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/// Apply this element to a movable atom when you want it to block explosions
|
||||
/// It will mirror the blocking down to that movable's turf, keeping explosion work cheap
|
||||
/datum/element/blocks_explosives
|
||||
|
||||
/datum/element/blocks_explosives/Attach(datum/target)
|
||||
if(!ismovable(target))
|
||||
return
|
||||
. = ..()
|
||||
ADD_TRAIT(target, TRAIT_BLOCKING_EXPLOSIVES, TRAIT_GENERIC)
|
||||
var/atom/movable/moving_target = target
|
||||
RegisterSignal(moving_target, COMSIG_MOVABLE_MOVED, PROC_REF(blocker_moved))
|
||||
RegisterSignal(moving_target, COMSIG_MOVABLE_EXPLOSION_BLOCK_CHANGED, PROC_REF(blocking_changed))
|
||||
moving_target.explosive_resistance = moving_target.explosion_block
|
||||
|
||||
if(length(moving_target.locs) > 1)
|
||||
for(var/atom/location as anything in moving_target.locs)
|
||||
block_loc(location, moving_target.explosion_block)
|
||||
else if(moving_target.loc)
|
||||
block_loc(moving_target.loc, moving_target.explosion_block)
|
||||
|
||||
/datum/element/blocks_explosives/Detach(datum/source)
|
||||
. = ..()
|
||||
REMOVE_TRAIT(source, TRAIT_BLOCKING_EXPLOSIVES, TRAIT_GENERIC)
|
||||
|
||||
/// Call this when our blocking well, changes. we'll update our turf(s) with the details
|
||||
/datum/element/blocks_explosives/proc/blocking_changed(atom/movable/target, old_block, new_block)
|
||||
if(length(target.locs) > 1)
|
||||
for(var/atom/location as anything in target.locs)
|
||||
unblock_loc(location, old_block)
|
||||
block_loc(location, new_block)
|
||||
else if(target.loc)
|
||||
unblock_loc(target.loc, old_block)
|
||||
block_loc(target.loc, new_block)
|
||||
|
||||
/// Applies a block amount to a turf. proc for convenince
|
||||
/datum/element/blocks_explosives/proc/block_loc(atom/location, block_amount)
|
||||
location.explosive_resistance += block_amount
|
||||
|
||||
/// Removes a block amount from a turf. proc for convenince
|
||||
/datum/element/blocks_explosives/proc/unblock_loc(atom/location, block_amount)
|
||||
location.explosive_resistance -= block_amount
|
||||
|
||||
/// Essentially just blocking_changed except we remove from the old loc, and add to the new one
|
||||
/datum/element/blocks_explosives/proc/blocker_moved(atom/movable/target, atom/old_loc, dir, forced, list/old_locs)
|
||||
if(length(old_locs) > 1)
|
||||
for(var/atom/location as anything in old_locs)
|
||||
unblock_loc(location, target.explosion_block)
|
||||
else if(old_loc)
|
||||
unblock_loc(old_loc, target.explosion_block)
|
||||
|
||||
if(length(target.locs) > 1)
|
||||
for(var/atom/location as anything in target.locs)
|
||||
block_loc(location, target.explosion_block)
|
||||
else if(target.loc)
|
||||
block_loc(target.loc, target.explosion_block)
|
||||
|
||||
@@ -76,6 +76,9 @@
|
||||
if(available - the_stack.amount < 0)
|
||||
return FALSE
|
||||
|
||||
else if(istype(to_insert, /obj/item/circuitboard/machine) || istype(to_insert, /obj/item/circuitboard/computer))
|
||||
return TRUE
|
||||
|
||||
//check normal insertion of other stock parts
|
||||
else if(!to_insert.get_part_rating())
|
||||
return FALSE
|
||||
|
||||
+6
-2
@@ -39,8 +39,8 @@
|
||||
///HUD images that this atom can provide.
|
||||
var/list/hud_possible
|
||||
|
||||
///Value used to increment ex_act() if reactionary_explosions is on
|
||||
var/explosion_block = 0
|
||||
///How much this atom resists explosions by, in the end
|
||||
var/explosive_resistance = 0
|
||||
|
||||
/**
|
||||
* used to store the different colors on an atom
|
||||
@@ -1879,6 +1879,10 @@
|
||||
|
||||
pixel_y = pixel_y + base_pixel_y - .
|
||||
|
||||
// Not a valid operation, turfs and movables handle block differently
|
||||
/atom/proc/set_explosion_block(explosion_block)
|
||||
return
|
||||
|
||||
/**
|
||||
* Returns true if this atom has gravity for the passed in turf
|
||||
*
|
||||
|
||||
@@ -96,6 +96,10 @@
|
||||
|
||||
/// Whether a user will face atoms on entering them with a mouse. Despite being a mob variable, it is here for performances //SKYRAT EDIT ADDITION
|
||||
var/face_mouse = FALSE //SKYRAT EDIT ADDITION
|
||||
/// Value used to increment ex_act() if reactionary_explosions is on
|
||||
/// How much we as a source block explosions by
|
||||
/// Will not automatically apply to the turf below you, you need to apply /datum/element/block_explosives in conjunction with this
|
||||
var/explosion_block = 0
|
||||
|
||||
/mutable_appearance/emissive_blocker
|
||||
|
||||
@@ -107,6 +111,11 @@
|
||||
|
||||
/atom/movable/Initialize(mapload)
|
||||
. = ..()
|
||||
#ifdef UNIT_TESTS
|
||||
if(explosion_block && !HAS_TRAIT(src, TRAIT_BLOCKING_EXPLOSIVES))
|
||||
stack_trace("[type] blocks explosives, but does not have the managing element applied")
|
||||
#endif
|
||||
|
||||
switch(blocks_emissive)
|
||||
if(EMISSIVE_BLOCK_GENERIC)
|
||||
var/static/mutable_appearance/emissive_blocker/blocker = new()
|
||||
@@ -518,7 +527,7 @@
|
||||
if(set_dir_on_move && dir != direction && !face_mouse) // SKYRAT EDIT CHANGE
|
||||
setDir(direction)
|
||||
|
||||
var/is_multi_tile_object = bound_width > 32 || bound_height > 32
|
||||
var/is_multi_tile_object = is_multi_tile_object(src)
|
||||
|
||||
var/list/old_locs
|
||||
if(is_multi_tile_object && isturf(loc))
|
||||
@@ -1135,6 +1144,13 @@
|
||||
|
||||
return TRUE
|
||||
|
||||
/atom/movable/set_explosion_block(explosion_block)
|
||||
var/old_block = src.explosion_block
|
||||
explosive_resistance -= old_block
|
||||
src.explosion_block = explosion_block
|
||||
explosive_resistance += explosion_block
|
||||
SEND_SIGNAL(src, COMSIG_MOVABLE_EXPLOSION_BLOCK_CHANGED, old_block, explosion_block)
|
||||
|
||||
/atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
set waitfor = FALSE
|
||||
var/hitpush = TRUE
|
||||
|
||||
@@ -55,10 +55,10 @@
|
||||
/datum/atom_hud/data/diagnostic
|
||||
|
||||
/datum/atom_hud/data/diagnostic/basic
|
||||
hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_CIRCUIT_HUD, DIAG_TRACK_HUD, DIAG_CAMERA_HUD, DIAG_AIRLOCK_HUD, DIAG_LAUNCHPAD_HUD)
|
||||
hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_TRACK_HUD, DIAG_CAMERA_HUD, DIAG_AIRLOCK_HUD, DIAG_LAUNCHPAD_HUD)
|
||||
|
||||
/datum/atom_hud/data/diagnostic/advanced
|
||||
hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_CIRCUIT_HUD, DIAG_TRACK_HUD, DIAG_CAMERA_HUD, DIAG_AIRLOCK_HUD, DIAG_LAUNCHPAD_HUD, DIAG_PATH_HUD)
|
||||
hud_icons = list(DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD, DIAG_TRACK_HUD, DIAG_CAMERA_HUD, DIAG_AIRLOCK_HUD, DIAG_LAUNCHPAD_HUD, DIAG_PATH_HUD)
|
||||
|
||||
/datum/atom_hud/data/bot_path
|
||||
// This hud exists so the bot can see itself, that's all
|
||||
|
||||
@@ -101,6 +101,37 @@
|
||||
amt += req_components[path]
|
||||
return amt
|
||||
|
||||
/**
|
||||
* install the circuitboard in this frame
|
||||
* * board - the machine circuitboard to install
|
||||
* * user - the player
|
||||
* * by_hand - is the player installing the board by hand or from the RPED. Used to decide how to transfer the board into the frame
|
||||
*/
|
||||
/obj/structure/frame/machine/proc/install_board(obj/item/circuitboard/machine/board, mob/user, by_hand)
|
||||
if(!board.build_path)
|
||||
to_chat(user, span_warning("This circuitboard seems to be broken."))
|
||||
return
|
||||
if(!anchored && board.needs_anchored)
|
||||
to_chat(user, span_warning("The frame needs to be secured first!"))
|
||||
return
|
||||
if(by_hand && !user.transferItemToLoc(board, src))
|
||||
return
|
||||
else if(!board.forceMove(src))
|
||||
return
|
||||
|
||||
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, TRUE)
|
||||
to_chat(user, span_notice("You add the circuit board to the frame."))
|
||||
circuit = board
|
||||
icon_state = "box_2"
|
||||
state = 3
|
||||
components = list()
|
||||
//add circuit board as the first component to the list of components
|
||||
//required for part_replacer to locate it while exchanging parts so it does not early return in /obj/machinery/proc/exchange_parts
|
||||
components += circuit
|
||||
req_components = board.req_components.Copy()
|
||||
update_namelist(board.specific_parts)
|
||||
return TRUE
|
||||
|
||||
/obj/structure/frame/machine/attackby(obj/item/P, mob/living/user, params)
|
||||
switch(state)
|
||||
if(1)
|
||||
@@ -152,27 +183,35 @@
|
||||
set_anchored(!anchored)
|
||||
return
|
||||
|
||||
if(istype(P, /obj/item/storage/part_replacer) && P.contents.len)
|
||||
var/obj/item/storage/part_replacer/replacer = P
|
||||
// map of circuitboard names to the board
|
||||
var/list/circuit_boards = list()
|
||||
for(var/obj/item/circuitboard/machine/board in replacer.contents)
|
||||
circuit_boards[board.name] = board
|
||||
if(!length(circuit_boards))
|
||||
return
|
||||
//if there is only one board directly install it else pick from list
|
||||
var/obj/item/circuitboard/machine/target_board
|
||||
if(circuit_boards.len == 1)
|
||||
for(var/board_name in circuit_boards)
|
||||
target_board = circuit_boards[board_name]
|
||||
else
|
||||
var/option = tgui_input_list(user, "Select Circuitboard To Install"," Available Boards", circuit_boards)
|
||||
target_board = circuit_boards[option]
|
||||
if(!target_board)
|
||||
return
|
||||
//install board
|
||||
if(install_board(target_board, user, FALSE))
|
||||
user.Beam(src, icon_state = "rped_upgrade", time = 5)
|
||||
replacer.play_rped_sound()
|
||||
//attack this frame again with the rped so it can install stock parts since its now in state 3
|
||||
attackby(replacer, user, params)
|
||||
return
|
||||
|
||||
if(istype(P, /obj/item/circuitboard/machine))
|
||||
var/obj/item/circuitboard/machine/board = P
|
||||
if(!board.build_path)
|
||||
to_chat(user, span_warning("This circuitboard seems to be broken."))
|
||||
return
|
||||
if(!anchored && board.needs_anchored)
|
||||
to_chat(user, span_warning("The frame needs to be secured first!"))
|
||||
return
|
||||
if(!user.transferItemToLoc(board, src))
|
||||
return
|
||||
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, TRUE)
|
||||
to_chat(user, span_notice("You add the circuit board to the frame."))
|
||||
circuit = board
|
||||
icon_state = "box_2"
|
||||
state = 3
|
||||
components = list()
|
||||
//add circuit board as the first component to the list of components
|
||||
//required for part_replacer to locate it while exchanging parts so it does not early return in /obj/machinery/proc/exchange_parts
|
||||
components += circuit
|
||||
req_components = board.req_components.Copy()
|
||||
update_namelist(board.specific_parts)
|
||||
var/obj/item/circuitboard/machine/machine_board = P
|
||||
install_board(machine_board, user, TRUE)
|
||||
return
|
||||
|
||||
else if(istype(P, /obj/item/circuitboard))
|
||||
@@ -251,7 +290,14 @@
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(istype(P, /obj/item/storage/part_replacer) && P.contents.len && get_req_components_amt())
|
||||
if(istype(P, /obj/item/storage/part_replacer))
|
||||
/**
|
||||
* more efficient return so no if conditions after this are executed.
|
||||
* Required when the rped is re attacking the frame after installing circuitboard so it returns quickly
|
||||
*/
|
||||
if(!P.contents.len || !get_req_components_amt())
|
||||
return
|
||||
|
||||
var/obj/item/storage/part_replacer/replacer = P
|
||||
var/list/added_components = list()
|
||||
var/list/part_list = replacer.get_sorted_parts() //parts sorted in order of tier
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
acid = 70
|
||||
|
||||
/obj/machinery/door/Initialize(mapload)
|
||||
AddElement(/datum/element/blocks_explosives)
|
||||
. = ..()
|
||||
set_init_door_layer()
|
||||
update_freelook_sight()
|
||||
@@ -70,7 +71,7 @@
|
||||
|
||||
//doors only block while dense though so we have to use the proc
|
||||
real_explosion_block = explosion_block
|
||||
explosion_block = EXPLOSION_BLOCK_PROC
|
||||
update_explosive_block()
|
||||
RegisterSignal(SSsecurity_level, COMSIG_SECURITY_LEVEL_CHANGED, PROC_REF(check_security_level))
|
||||
|
||||
var/static/list/loc_connections = list(
|
||||
@@ -501,9 +502,6 @@
|
||||
//if it blows up a wall it should blow up a door
|
||||
return ..(severity ? min(EXPLODE_DEVASTATE, severity + 1) : EXPLODE_NONE, target)
|
||||
|
||||
/obj/machinery/door/GetExplosionBlock()
|
||||
return density ? real_explosion_block : 0
|
||||
|
||||
/obj/machinery/door/power_change()
|
||||
. = ..()
|
||||
if(. && !(machine_stat & NOPOWER))
|
||||
@@ -519,4 +517,19 @@
|
||||
|
||||
INVOKE_ASYNC(src, PROC_REF(open))
|
||||
|
||||
/obj/machinery/door/set_density(new_value)
|
||||
. = ..()
|
||||
update_explosive_block()
|
||||
|
||||
/obj/machinery/door/proc/update_explosive_block()
|
||||
set_explosion_block(real_explosion_block)
|
||||
|
||||
// Kinda roundabout, essentially if we're dense, we respect real_explosion_block
|
||||
// Otherwise, we block nothing
|
||||
/obj/machinery/door/set_explosion_block(explosion_block)
|
||||
real_explosion_block = explosion_block
|
||||
if(density)
|
||||
return ..()
|
||||
return ..(0)
|
||||
|
||||
#undef DOOR_CLOSE_WAIT
|
||||
|
||||
@@ -678,6 +678,7 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
/obj/item/proc/pickup(mob/user)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
SEND_SIGNAL(src, COMSIG_ITEM_PICKUP, user)
|
||||
SEND_SIGNAL(user, COMSIG_LIVING_PICKED_UP_ITEM, src)
|
||||
item_flags |= IN_INVENTORY
|
||||
|
||||
/// called when "found" in pockets and storage items. Returns 1 if the search should end.
|
||||
|
||||
@@ -1054,7 +1054,7 @@ GLOBAL_VAR_INIT(icon_holographic_window, init_holographic_window())
|
||||
if(istype(O))
|
||||
var/x0 = O.x
|
||||
var/y0 = O.y
|
||||
var/contender = cheap_hypotenuse(start.x, start.y, x0, y0)
|
||||
var/contender = CHEAP_HYPOTENUSE(start.x, start.y, x0, y0)
|
||||
if(!winner)
|
||||
winner = O
|
||||
winning_dist = contender
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
name = "retro identification card"
|
||||
desc = "A card used to provide ID and determine access across the station."
|
||||
icon_state = "card_grey"
|
||||
worn_icon_state = "card_retro"
|
||||
inhand_icon_state = "card-id"
|
||||
worn_icon_state = "nothing"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi'
|
||||
slot_flags = ITEM_SLOT_ID
|
||||
@@ -897,7 +897,6 @@
|
||||
name = "identification card"
|
||||
desc = "A card used to provide ID and determine access across the station. Has an integrated digital display and advanced microchips."
|
||||
icon_state = "card_grey"
|
||||
worn_icon_state = "card_grey"
|
||||
|
||||
wildcard_slots = WILDCARD_LIMIT_GREY
|
||||
flags_1 = UNPAINTABLE_1
|
||||
@@ -1059,13 +1058,11 @@
|
||||
name = "rainbow identification card"
|
||||
desc = "A rainbow card, promoting fun in a 'business proper' sense!"
|
||||
icon_state = "card_rainbow"
|
||||
worn_icon_state = "card_rainbow"
|
||||
|
||||
/obj/item/card/id/advanced/silver
|
||||
name = "silver identification card"
|
||||
desc = "A silver card which shows honour and dedication."
|
||||
icon_state = "card_silver"
|
||||
worn_icon_state = "card_silver"
|
||||
inhand_icon_state = "silver_id"
|
||||
assigned_icon_state = "assigned_silver"
|
||||
wildcard_slots = WILDCARD_LIMIT_SILVER
|
||||
@@ -1084,7 +1081,6 @@
|
||||
name = "gold identification card"
|
||||
desc = "A golden card which shows power and might."
|
||||
icon_state = "card_gold"
|
||||
worn_icon_state = "card_gold"
|
||||
inhand_icon_state = "gold_id"
|
||||
assigned_icon_state = "assigned_gold"
|
||||
wildcard_slots = WILDCARD_LIMIT_GOLD
|
||||
@@ -1119,7 +1115,6 @@
|
||||
name = "\improper CentCom ID"
|
||||
desc = "An ID straight from Central Command."
|
||||
icon_state = "card_centcom"
|
||||
worn_icon_state = "card_centcom"
|
||||
assigned_icon_state = "assigned_centcom"
|
||||
registered_name = JOB_CENTCOM
|
||||
registered_age = null
|
||||
@@ -1165,7 +1160,6 @@
|
||||
name = "black identification card"
|
||||
desc = "This card is telling you one thing and one thing alone. The person holding this card is an utter badass."
|
||||
icon_state = "card_black"
|
||||
worn_icon_state = "card_black"
|
||||
assigned_icon_state = "assigned_syndicate"
|
||||
wildcard_slots = WILDCARD_LIMIT_GOLD
|
||||
|
||||
@@ -1219,7 +1213,6 @@
|
||||
name = "\improper Debug ID"
|
||||
desc = "A debug ID card. Has ALL the all access, you really shouldn't have this."
|
||||
icon_state = "card_centcom"
|
||||
worn_icon_state = "card_centcom"
|
||||
assigned_icon_state = "assigned_centcom"
|
||||
trim = /datum/id_trim/admin
|
||||
wildcard_slots = WILDCARD_LIMIT_ADMIN
|
||||
@@ -1236,7 +1229,6 @@
|
||||
name = "prisoner ID card"
|
||||
desc = "You are a number, you are not a free man."
|
||||
icon_state = "card_prisoner"
|
||||
worn_icon_state = "card_prisoner"
|
||||
inhand_icon_state = "orange-id"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi'
|
||||
@@ -1353,7 +1345,6 @@
|
||||
registered_name = "Highlander"
|
||||
desc = "There can be only one!"
|
||||
icon_state = "card_black"
|
||||
worn_icon_state = "card_black"
|
||||
assigned_icon_state = "assigned_syndicate"
|
||||
trim = /datum/id_trim/highlander
|
||||
wildcard_slots = WILDCARD_LIMIT_ADMIN
|
||||
@@ -1664,7 +1655,6 @@
|
||||
/// A special variant of the classic chameleon ID card which accepts all access.
|
||||
/obj/item/card/id/advanced/chameleon/black
|
||||
icon_state = "card_black"
|
||||
worn_icon_state = "card_black"
|
||||
assigned_icon_state = "assigned_syndicate"
|
||||
wildcard_slots = WILDCARD_LIMIT_GOLD
|
||||
|
||||
|
||||
@@ -204,6 +204,7 @@
|
||||
desc = "A hand-held long-range environmental scanner which reports current gas levels."
|
||||
name = "long-range gas analyzer"
|
||||
icon_state = "analyzerranged"
|
||||
worn_icon_state = "analyzer"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
custom_materials = list(/datum/material/iron = 100, /datum/material/glass = 20, /datum/material/gold = 300, /datum/material/bluespace=200)
|
||||
grind_results = list(/datum/reagent/mercury = 5, /datum/reagent/iron = 5, /datum/reagent/silicon = 5)
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
desc = "An ominous card that contains the location of the station, and when applied to a communications console, \
|
||||
the ability to long-distance contact the Syndicate fleet."
|
||||
icon_state = "battlecruisercaller"
|
||||
worn_icon_state = "battlecruisercaller"
|
||||
worn_icon_state = "emag"
|
||||
///whether we have called the battlecruiser
|
||||
var/used = FALSE
|
||||
/// The battlecruiser team that the battlecruiser will get added to
|
||||
|
||||
@@ -240,6 +240,7 @@
|
||||
acid = 100
|
||||
|
||||
/obj/structure/light_puzzle/Initialize(mapload)
|
||||
AddElement(/datum/element/blocks_explosives)
|
||||
. = ..()
|
||||
var/generated_board = -1
|
||||
while(generated_board in banned_combinations)
|
||||
|
||||
@@ -272,6 +272,7 @@
|
||||
name = "Crusader's Hood"
|
||||
desc = "A brownish hood."
|
||||
icon = 'icons/obj/clothing/head/chaplain.dmi'
|
||||
worn_icon = 'icons/mob/clothing/head/chaplain.dmi'
|
||||
icon_state = "crusader"
|
||||
inhand_icon_state = null
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
@@ -300,6 +301,7 @@
|
||||
name = "Prophet's Hat"
|
||||
desc = "A religious-looking hat."
|
||||
icon_state = null
|
||||
worn_icon = 'icons/mob/clothing/head/helmet.dmi'
|
||||
inhand_icon_state = null
|
||||
flags_1 = 0
|
||||
armor_type = /datum/armor/crusader_prophet
|
||||
|
||||
@@ -208,7 +208,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/item/storage/secure/safe, 32)
|
||||
name = "captain's spare ID safe"
|
||||
desc = "In case of emergency, do not break glass. All Captains and Acting Captains are provided with codes to access this safe. \
|
||||
It is made out of the same material as the station's Black Box and is designed to resist all conventional weaponry. \
|
||||
There appears to be a small amount of surface corrosion. It doesn't look like it could withstand much of an explosion."
|
||||
There appears to be a small amount of surface corrosion. It doesn't look like it could withstand much of an explosion.\
|
||||
It remains quite flush against the wall, and there only seems to be enough room to fit something as slim as an ID card."
|
||||
can_hack_open = FALSE
|
||||
armor_type = /datum/armor/safe_caps_spare
|
||||
max_integrity = 300
|
||||
@@ -227,6 +228,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/item/storage/secure/safe/caps_spare, 32)
|
||||
|
||||
/obj/item/storage/secure/safe/caps_spare/Initialize(mapload)
|
||||
. = ..()
|
||||
atom_storage.set_holdable(can_hold_list = list(/obj/item/card/id))
|
||||
lock_code = SSid_access.spare_id_safe_code
|
||||
lock_set = TRUE
|
||||
atom_storage.locked = TRUE
|
||||
|
||||
@@ -154,6 +154,7 @@
|
||||
|
||||
/obj/item/storage/wallet/random
|
||||
icon_state = "random_wallet" // for mapping purposes
|
||||
worn_icon_state = "wallet"
|
||||
|
||||
/obj/item/storage/wallet/random/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
@@ -335,6 +335,7 @@ LINEN BINS
|
||||
name = "random bedsheet"
|
||||
desc = "If you're reading this description ingame, something has gone wrong! Honk!"
|
||||
bedsheet_type = BEDSHEET_ABSTRACT
|
||||
item_flags = ABSTRACT
|
||||
var/static/list/bedsheet_list
|
||||
var/spawn_type = BEDSHEET_SINGLE
|
||||
|
||||
@@ -360,6 +361,7 @@ LINEN BINS
|
||||
name = "random dorms bedsheet"
|
||||
desc = "If you're reading this description ingame, something has gone wrong! Honk!"
|
||||
bedsheet_type = BEDSHEET_DOUBLE
|
||||
item_flags = ABSTRACT
|
||||
slot_flags = null
|
||||
|
||||
/obj/item/bedsheet/dorms/Initialize(mapload)
|
||||
@@ -541,6 +543,7 @@ LINEN BINS
|
||||
|
||||
/obj/item/bedsheet/dorms_double
|
||||
icon_state = "random_bedsheet"
|
||||
item_flags = ABSTRACT
|
||||
bedsheet_type = BEDSHEET_ABSTRACT
|
||||
|
||||
/obj/item/bedsheet/dorms_double/Initialize(mapload)
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
acid = 100
|
||||
|
||||
/obj/structure/window/Initialize(mapload, direct)
|
||||
AddElement(/datum/element/blocks_explosives)
|
||||
. = ..()
|
||||
if(direct)
|
||||
setDir(direct)
|
||||
@@ -55,9 +56,9 @@
|
||||
setDir()
|
||||
AddElement(/datum/element/can_barricade)
|
||||
|
||||
//windows only block while reinforced and fulltile, so we'll use the proc
|
||||
real_explosion_block = explosion_block
|
||||
explosion_block = EXPLOSION_BLOCK_PROC
|
||||
//windows only block while reinforced and fulltile
|
||||
if(!reinf || !fulltile)
|
||||
set_explosion_block(0)
|
||||
|
||||
flags_1 |= ALLOW_DARK_PAINTS_1
|
||||
RegisterSignal(src, COMSIG_OBJ_PAINTED, PROC_REF(on_painted))
|
||||
@@ -424,9 +425,6 @@
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/structure/window/GetExplosionBlock()
|
||||
return reinf && fulltile ? real_explosion_block : 0
|
||||
|
||||
/obj/structure/window/spawner/east
|
||||
dir = EAST
|
||||
|
||||
|
||||
@@ -83,6 +83,9 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
|
||||
//SKYRAT EDIT END
|
||||
var/old_rcd_memory = rcd_memory
|
||||
var/old_always_lit = always_lit
|
||||
var/old_explosion_throw_details = explosion_throw_details
|
||||
// We get just the bits of explosive_resistance that aren't the turf
|
||||
var/old_explosive_resistance = explosive_resistance - get_explosive_block()
|
||||
var/old_lattice_underneath = lattice_underneath
|
||||
|
||||
var/old_bp = blueprint_data
|
||||
@@ -122,6 +125,8 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
|
||||
|
||||
new_turf.blueprint_data = old_bp
|
||||
new_turf.rcd_memory = old_rcd_memory
|
||||
new_turf.explosion_throw_details = old_explosion_throw_details
|
||||
new_turf.explosive_resistance += old_explosive_resistance
|
||||
|
||||
lighting_corner_NE = old_lighting_corner_NE
|
||||
lighting_corner_SE = old_lighting_corner_SE
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
name = "wall"
|
||||
desc = "Effectively impervious to conventional methods of destruction."
|
||||
icon = 'icons/turf/walls.dmi'
|
||||
explosion_block = 50
|
||||
explosive_resistance = 50
|
||||
|
||||
/turf/closed/indestructible/rust_heretic_act()
|
||||
return
|
||||
@@ -279,7 +279,7 @@ INITIALIZE_IMMEDIATE(/turf/closed/indestructible/splashscreen)
|
||||
desc = "A seemingly impenetrable wall."
|
||||
icon = 'icons/turf/walls.dmi'
|
||||
icon_state = "necro"
|
||||
explosion_block = 50
|
||||
explosive_resistance = 50
|
||||
baseturfs = /turf/closed/indestructible/necropolis
|
||||
|
||||
/turf/closed/indestructible/necropolis/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
|
||||
@@ -307,7 +307,7 @@ INITIALIZE_IMMEDIATE(/turf/closed/indestructible/splashscreen)
|
||||
smoothing_flags = SMOOTH_BITMASK
|
||||
smoothing_groups = SMOOTH_GROUP_CLOSED_TURFS + SMOOTH_GROUP_BOSS_WALLS
|
||||
canSmoothWith = SMOOTH_GROUP_BOSS_WALLS
|
||||
explosion_block = 50
|
||||
explosive_resistance = 50
|
||||
baseturfs = /turf/closed/indestructible/riveted/boss
|
||||
|
||||
/turf/closed/indestructible/riveted/boss/see_through
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
base_icon_state = "gold_wall"
|
||||
sheet_type = /obj/item/stack/sheet/mineral/gold
|
||||
hardness = 65 //gold is soft
|
||||
explosion_block = 0 //gold is a soft metal you dingus.
|
||||
explosive_resistance = 0 //gold is a soft metal you dingus.
|
||||
smoothing_groups = SMOOTH_GROUP_GOLD_WALLS + SMOOTH_GROUP_WALLS + SMOOTH_GROUP_CLOSED_TURFS
|
||||
canSmoothWith = SMOOTH_GROUP_GOLD_WALLS
|
||||
custom_materials = list(/datum/material/gold = 4000)
|
||||
@@ -42,7 +42,7 @@
|
||||
sheet_type = /obj/item/stack/sheet/mineral/diamond
|
||||
hardness = 5 //diamond is very hard
|
||||
slicing_duration = 200 //diamond wall takes twice as much time to slice
|
||||
explosion_block = 3
|
||||
explosive_resistance = 3
|
||||
smoothing_flags = SMOOTH_BITMASK
|
||||
smoothing_groups = SMOOTH_GROUP_DIAMOND_WALLS + SMOOTH_GROUP_WALLS + SMOOTH_GROUP_CLOSED_TURFS
|
||||
canSmoothWith = SMOOTH_GROUP_DIAMOND_WALLS
|
||||
@@ -72,7 +72,7 @@
|
||||
base_icon_state = "sandstone_wall"
|
||||
sheet_type = /obj/item/stack/sheet/mineral/sandstone
|
||||
hardness = 50 //moh says this is apparently 6-7 on it's scale
|
||||
explosion_block = 0
|
||||
explosive_resistance = 0
|
||||
smoothing_flags = SMOOTH_BITMASK
|
||||
smoothing_groups = SMOOTH_GROUP_SANDSTONE_WALLS + SMOOTH_GROUP_WALLS + SMOOTH_GROUP_CLOSED_TURFS
|
||||
canSmoothWith = SMOOTH_GROUP_SANDSTONE_WALLS
|
||||
@@ -158,7 +158,7 @@
|
||||
sheet_type = /obj/item/stack/sheet/mineral/wood
|
||||
hardness = 80
|
||||
turf_flags = IS_SOLID
|
||||
explosion_block = 0
|
||||
explosive_resistance = 0
|
||||
smoothing_flags = SMOOTH_BITMASK
|
||||
smoothing_groups = SMOOTH_GROUP_WOOD_WALLS + SMOOTH_GROUP_WALLS + SMOOTH_GROUP_CLOSED_TURFS
|
||||
canSmoothWith = SMOOTH_GROUP_WOOD_WALLS
|
||||
@@ -215,7 +215,7 @@
|
||||
base_icon_state = "snow_wall"
|
||||
smoothing_flags = SMOOTH_BITMASK
|
||||
hardness = 80
|
||||
explosion_block = 0
|
||||
explosive_resistance = 0
|
||||
slicing_duration = 30
|
||||
sheet_type = /obj/item/stack/sheet/mineral/snow
|
||||
canSmoothWith = null
|
||||
@@ -236,7 +236,7 @@
|
||||
sheet_type = /obj/item/stack/sheet/mineral/abductor
|
||||
hardness = 10
|
||||
slicing_duration = 200 //alien wall takes twice as much time to slice
|
||||
explosion_block = 3
|
||||
explosive_resistance = 3
|
||||
smoothing_flags = SMOOTH_BITMASK | SMOOTH_DIAGONAL_CORNERS
|
||||
smoothing_groups = SMOOTH_GROUP_ABDUCTOR_WALLS + SMOOTH_GROUP_WALLS + SMOOTH_GROUP_CLOSED_TURFS
|
||||
canSmoothWith = SMOOTH_GROUP_ABDUCTOR_WALLS
|
||||
@@ -250,7 +250,7 @@
|
||||
icon = 'icons/turf/walls/shuttle_wall.dmi'
|
||||
icon_state = "shuttle_wall-0"
|
||||
base_icon_state = "shuttle_wall"
|
||||
explosion_block = 3
|
||||
explosive_resistance = 3
|
||||
flags_1 = CAN_BE_DIRTY_1
|
||||
flags_ricochet = RICOCHET_SHINY | RICOCHET_HARD
|
||||
sheet_type = /obj/item/stack/sheet/mineral/titanium
|
||||
@@ -314,7 +314,7 @@
|
||||
icon = 'icons/turf/walls/plastitanium_wall.dmi'
|
||||
icon_state = "plastitanium_wall-0"
|
||||
base_icon_state = "plastitanium_wall"
|
||||
explosion_block = 4
|
||||
explosive_resistance = 4
|
||||
sheet_type = /obj/item/stack/sheet/mineral/plastitanium
|
||||
hardness = 25 //upgrade on titanium
|
||||
smoothing_flags = SMOOTH_BITMASK | SMOOTH_DIAGONAL_CORNERS
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
sheet_type = /obj/item/stack/sheet/plasteel
|
||||
sheet_amount = 1
|
||||
girder_type = /obj/structure/girder/reinforced
|
||||
explosion_block = 2
|
||||
explosive_resistance = 2
|
||||
rad_insulation = RAD_HEAVY_INSULATION
|
||||
heat_capacity = 312500 //a little over 5 cm thick , 312500 for 1 m by 2.5 m by 0.25 m plasteel wall. also indicates the temperature at wich the wall will melt (currently only able to melt with H/E pipes)
|
||||
///Dismantled state, related to deconstruction.
|
||||
@@ -233,7 +233,7 @@
|
||||
icon = 'icons/turf/walls/plastitanium_wall.dmi'
|
||||
icon_state = "plastitanium_wall-0"
|
||||
base_icon_state = "plastitanium_wall"
|
||||
explosion_block = 20
|
||||
explosive_resistance = 20
|
||||
sheet_type = /obj/item/stack/sheet/mineral/plastitanium
|
||||
hardness = 25 //plastitanium
|
||||
turf_flags = IS_SOLID
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
icon = 'icons/turf/walls/wall.dmi'
|
||||
icon_state = "wall-0"
|
||||
base_icon_state = "wall"
|
||||
explosion_block = 1
|
||||
explosive_resistance = 1
|
||||
|
||||
thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
|
||||
heat_capacity = 62500 //a little over 5 cm thick , 62500 for 1 m by 2.5 m by 0.25 m iron wall. also indicates the temperature at wich the wall will melt (currently only able to melt with H/E pipes)
|
||||
@@ -266,7 +266,7 @@
|
||||
return null
|
||||
|
||||
/turf/closed/wall/acid_act(acidpwr, acid_volume)
|
||||
if(explosion_block >= 2)
|
||||
if(get_explosive_block() >= 2)
|
||||
acidpwr = min(acidpwr, 50) //we reduce the power so strong walls never get melted.
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
dir = SOUTH
|
||||
baseturfs = /turf/open/space/transit
|
||||
flags_1 = NOJAUNT //This line goes out to every wizard that ever managed to escape the den. I'm sorry.
|
||||
explosion_block = INFINITY
|
||||
explosive_resistance = INFINITY
|
||||
|
||||
/turf/open/space/transit/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
|
||||
. = ..()
|
||||
|
||||
@@ -92,6 +92,12 @@ GLOBAL_LIST_EMPTY(station_turfs)
|
||||
/// Sorry for the mess
|
||||
var/area/in_contents_of
|
||||
#endif
|
||||
/// How much explosive resistance this turf is providing to itself
|
||||
/// Defaults to -1, interpreted as initial(explosive_resistance)
|
||||
/// This is an optimization to prevent turfs from needing to set these on init
|
||||
/// This would either be expensive, or impossible to manage. Let's just avoid it yes?
|
||||
/// Never directly access this, use get_explosive_block() instead
|
||||
var/inherent_explosive_resistance = -1
|
||||
|
||||
/turf/vv_edit_var(var_name, new_value)
|
||||
var/static/list/banned_edits = list(NAMEOF_STATIC(src, x), NAMEOF_STATIC(src, y), NAMEOF_STATIC(src, z))
|
||||
@@ -681,6 +687,26 @@ GLOBAL_LIST_EMPTY(station_turfs)
|
||||
continue
|
||||
movable_content.wash(clean_types)
|
||||
|
||||
/turf/set_density(new_value)
|
||||
var/old_density = density
|
||||
. = ..()
|
||||
if(old_density == density)
|
||||
return
|
||||
|
||||
if(old_density)
|
||||
explosive_resistance -= get_explosive_block()
|
||||
if(density)
|
||||
explosive_resistance += get_explosive_block()
|
||||
|
||||
/// Wrapper around inherent_explosive_resistance
|
||||
/// We assume this proc is cold, so we can move the "what is our block" into it
|
||||
/turf/proc/get_explosive_block()
|
||||
if(inherent_explosive_resistance != -1)
|
||||
return inherent_explosive_resistance
|
||||
if(explosive_resistance)
|
||||
return initial(explosive_resistance)
|
||||
return 0
|
||||
|
||||
/**
|
||||
* Returns adjacent turfs to this turf that are reachable, in all cardinal directions
|
||||
*
|
||||
@@ -710,3 +736,9 @@ GLOBAL_LIST_EMPTY(station_turfs)
|
||||
|
||||
/turf/proc/TakeTemperature(temp)
|
||||
temperature += temp
|
||||
|
||||
// I'm sorry, this is the only way that both makes sense and is cheap
|
||||
/turf/set_explosion_block(explosion_block)
|
||||
explosive_resistance -= get_explosive_block()
|
||||
inherent_explosive_resistance = explosion_block
|
||||
explosive_resistance += get_explosive_block()
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
overmind.blobstrain.on_gain()
|
||||
update_appearance()
|
||||
AddComponent(/datum/component/stationloving, FALSE, TRUE)
|
||||
AddElement(/datum/element/blocks_explosives)
|
||||
return ..()
|
||||
|
||||
/obj/structure/blob/special/core/Destroy()
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
fire = 90
|
||||
acid = 90
|
||||
|
||||
/obj/structure/blob/shield/Initialize(mapload, owner_overmind)
|
||||
AddElement(/datum/element/blocks_explosives)
|
||||
return ..()
|
||||
|
||||
/obj/structure/blob/shield/scannerreport()
|
||||
if(atmosblock)
|
||||
return "Will prevent the spread of atmospheric changes."
|
||||
|
||||
@@ -476,6 +476,7 @@
|
||||
name = "flesh mass"
|
||||
icon_state = "lingspacesuit_t"
|
||||
icon = 'icons/obj/clothing/suits/costume.dmi'
|
||||
worn_icon = 'icons/mob/clothing/suits/costume.dmi'
|
||||
desc = "A huge, bulky mass of pressure and temperature-resistant organic tissue, evolved to facilitate space travel."
|
||||
item_flags = DROPDEL
|
||||
clothing_flags = STOPSPRESSUREDAMAGE //Not THICKMATERIAL because it's organic tissue, so if somebody tries to inject something into it, it still ends up in your blood. (also balance but muh fluff)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
icon_state = "cordon"
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
explosion_block = INFINITY
|
||||
explosive_resistance = INFINITY
|
||||
rad_insulation = RAD_FULL_INSULATION
|
||||
opacity = TRUE
|
||||
density = TRUE
|
||||
|
||||
@@ -165,7 +165,6 @@
|
||||
resistance_flags = NONE
|
||||
species_exception = list(/datum/species/golem)
|
||||
|
||||
// Lemom todo: and here
|
||||
/obj/item/clothing/suit/hazardvest/worn_overlays(mutable_appearance/standing, isinhands, icon_file)
|
||||
. = ..()
|
||||
if(!isinhands)
|
||||
|
||||
@@ -33,12 +33,13 @@
|
||||
throw_range = 3
|
||||
attack_verb_continuous = list("pompfs")
|
||||
attack_verb_simple = list("pompf")
|
||||
greyscale_colors = "#000000" //only here for unit testing. overriden in initialize()
|
||||
greyscale_config = /datum/greyscale_config/flower_simple
|
||||
greyscale_config_worn = /datum/greyscale_config/flower_simple_worn
|
||||
|
||||
/obj/item/food/grown/rainbow_flower/Initialize(mapload)
|
||||
. = ..()
|
||||
if(greyscale_colors)
|
||||
if(greyscale_colors != initial(greyscale_colors))
|
||||
return
|
||||
|
||||
var/flower_color = rand(1,8)
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
var/slicing_duration = 100
|
||||
|
||||
/obj/structure/tramwall/Initialize(mapload)
|
||||
AddElement(/datum/element/blocks_explosives)
|
||||
. = ..()
|
||||
var/obj/item/stack/initialized_mineral = new mineral
|
||||
set_custom_materials(initialized_mineral.mats_per_unit, mineral_amount)
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
name = "\improper Nanotrasen space pods"
|
||||
desc = "Flex your money, AND ignore what everyone else says, all at once!"
|
||||
icon_state = "spacepods"
|
||||
worn_icon = 'icons/mob/clothing/ears.dmi'
|
||||
inhand_icon_state = null
|
||||
slot_flags = ITEM_SLOT_EARS
|
||||
strip_delay = 100 //air pods don't fall out
|
||||
|
||||
@@ -251,7 +251,7 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999))
|
||||
icon_state = "hotelwall"
|
||||
smoothing_groups = SMOOTH_GROUP_CLOSED_TURFS + SMOOTH_GROUP_HOTEL_WALLS
|
||||
canSmoothWith = SMOOTH_GROUP_HOTEL_WALLS
|
||||
explosion_block = INFINITY
|
||||
explosive_resistance = INFINITY
|
||||
|
||||
/turf/open/indestructible/hotelwood
|
||||
desc = "Stylish dark wood with extra reinforcement. Secured firmly to the floor to prevent tampering."
|
||||
@@ -271,7 +271,7 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999))
|
||||
base_icon_state = "bluespace"
|
||||
baseturfs = /turf/open/space/bluespace
|
||||
flags_1 = NOJAUNT
|
||||
explosion_block = INFINITY
|
||||
explosive_resistance = INFINITY
|
||||
var/obj/item/hilbertshotel/parentSphere
|
||||
|
||||
/turf/open/space/bluespace/Initialize(mapload)
|
||||
@@ -290,7 +290,7 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999))
|
||||
/turf/closed/indestructible/hoteldoor
|
||||
name = "Hotel Door"
|
||||
icon_state = "hoteldoor"
|
||||
explosion_block = INFINITY
|
||||
explosive_resistance = INFINITY
|
||||
var/obj/item/hilbertshotel/parentSphere
|
||||
|
||||
/turf/closed/indestructible/hoteldoor/proc/promptExit(mob/living/user)
|
||||
|
||||
@@ -280,9 +280,15 @@
|
||||
* If the item can be dropped, it will be forceMove()'d to the ground and the turf's Entered() will be called.
|
||||
*/
|
||||
/mob/proc/dropItemToGround(obj/item/I, force = FALSE, silent = FALSE, invdrop = TRUE)
|
||||
if (isnull(I))
|
||||
return TRUE
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_MOB_DROPPING_ITEM)
|
||||
. = doUnEquip(I, force, drop_location(), FALSE, invdrop = invdrop, silent = silent)
|
||||
|
||||
if(!. || !I) //ensure the item exists and that it was dropped properly.
|
||||
return
|
||||
|
||||
if(!(I.item_flags & NO_PIXEL_RANDOM_DROP))
|
||||
I.pixel_x = I.base_pixel_x + rand(-6, 6)
|
||||
I.pixel_y = I.base_pixel_y + rand(-6, 6)
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
/// Kills the rat and changes its icon state to be splatted (bloody).
|
||||
/mob/living/basic/mouse/proc/splat()
|
||||
icon_dead = "mouse_[body_color]_splat"
|
||||
adjust_health(-maxHealth)
|
||||
adjust_health(maxHealth)
|
||||
|
||||
// On revival, re-add the mouse to the ratcap, or block it if we're at it
|
||||
/mob/living/basic/mouse/revive(full_heal_flags = NONE, excess_healing = 0, force_grab_ghost = FALSE)
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
QDEL_NULL(dna)
|
||||
GLOB.carbon_list -= src
|
||||
|
||||
/mob/living/carbon/swap_hand(held_index)
|
||||
/mob/living/carbon/perform_hand_swap(held_index)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
|
||||
@@ -155,7 +155,7 @@ There are several things that need to be remembered:
|
||||
var/icon_file
|
||||
|
||||
if(!icon_exists(icon_file, RESOLVE_ICON_STATE(worn_item)))
|
||||
icon_file = 'icons/mob/simple/mob.dmi'
|
||||
icon_file = 'icons/mob/clothing/id.dmi'
|
||||
|
||||
id_overlay = wear_id.build_worn_icon(default_layer = ID_LAYER, default_icon_file = icon_file)
|
||||
|
||||
|
||||
@@ -397,7 +397,7 @@
|
||||
if(slot_num > 4) // not >3 otherwise cycling with just one item on module 3 wouldn't work
|
||||
slot_num = 1 //Wrap around.
|
||||
|
||||
/mob/living/silicon/robot/swap_hand()
|
||||
/mob/living/silicon/robot/perform_hand_swap()
|
||||
cycle_modules()
|
||||
|
||||
/mob/living/silicon/robot/can_hold_items(obj/item/I)
|
||||
|
||||
@@ -616,7 +616,7 @@
|
||||
else
|
||||
mode()
|
||||
|
||||
/mob/living/simple_animal/swap_hand(hand_index)
|
||||
/mob/living/simple_animal/perform_hand_swap(hand_index)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
|
||||
+14
-2
@@ -885,11 +885,23 @@
|
||||
|
||||
return data
|
||||
|
||||
/mob/proc/swap_hand()
|
||||
/mob/proc/swap_hand(held_index)
|
||||
SHOULD_NOT_OVERRIDE(TRUE) // Override perform_hand_swap instead
|
||||
|
||||
var/obj/item/held_item = get_active_held_item()
|
||||
if(SEND_SIGNAL(src, COMSIG_MOB_SWAP_HANDS, held_item) & COMPONENT_BLOCK_SWAP)
|
||||
if(SEND_SIGNAL(src, COMSIG_MOB_SWAPPING_HANDS, held_item) & COMPONENT_BLOCK_SWAP)
|
||||
to_chat(src, span_warning("Your other hand is too busy holding [held_item]."))
|
||||
return FALSE
|
||||
|
||||
var/result = perform_hand_swap(held_index)
|
||||
if (result)
|
||||
SEND_SIGNAL(src, COMSIG_MOB_SWAP_HANDS)
|
||||
|
||||
return result
|
||||
|
||||
/// Performs the actual ritual of swapping hands, such as setting the held index variables
|
||||
/mob/proc/perform_hand_swap(held_index)
|
||||
PROTECTED_PROC(TRUE)
|
||||
return TRUE
|
||||
|
||||
/mob/proc/activate_hand(selhand)
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
var/corpse_theme = pick_weight(list(
|
||||
"Miner" = 66,
|
||||
"Ashwalker" = 10,
|
||||
"Golem" = 10,
|
||||
"Clown" = 10,
|
||||
"Golem" = 10,
|
||||
pick(list(
|
||||
"Shadow",
|
||||
"Cultist",
|
||||
"Dame",
|
||||
"Operative",
|
||||
"Cultist",
|
||||
"Shadow",
|
||||
)) = 4,
|
||||
))
|
||||
switch(corpse_theme)
|
||||
@@ -47,16 +47,16 @@
|
||||
outfit = /datum/outfit/consumed_ashwalker
|
||||
if("Clown")
|
||||
outfit = /datum/outfit/consumed_clown
|
||||
if("Golem")
|
||||
outfit = /datum/outfit/consumed_golem
|
||||
if("Cultist")
|
||||
outfit = /datum/outfit/consumed_cultist
|
||||
if("Dame")
|
||||
outfit = /datum/outfit/consumed_dame
|
||||
if("Golem")
|
||||
outfit = /datum/outfit/consumed_golem
|
||||
if("Operative")
|
||||
outfit = /datum/outfit/syndicatecommandocorpse
|
||||
if("Shadow")
|
||||
outfit = /datum/outfit/consumed_shadowperson
|
||||
if("Cultist")
|
||||
outfit = /datum/outfit/consumed_cultist
|
||||
. = ..()
|
||||
|
||||
/datum/outfit/consumed_miner
|
||||
@@ -70,31 +70,56 @@
|
||||
if(visualsOnly)
|
||||
regular_uniform = TRUE //assume human
|
||||
else
|
||||
var/new_species_type = pick_weight(list(/datum/species/human = 70, /datum/species/lizard = 26, /datum/species/fly = 2, /datum/species/plasmaman = 2))
|
||||
var/new_species_type = pick_weight(list(
|
||||
/datum/species/human = 70,
|
||||
/datum/species/lizard = 26,
|
||||
/datum/species/fly = 2,
|
||||
/datum/species/plasmaman = 2,
|
||||
))
|
||||
miner.set_species(new_species_type)
|
||||
if(new_species_type != /datum/species/plasmaman)
|
||||
regular_uniform = TRUE
|
||||
else
|
||||
uniform = /obj/item/clothing/under/plasmaman
|
||||
head = /obj/item/clothing/head/helmet/space/plasmaman
|
||||
belt = /obj/item/tank/internals/plasmaman/belt
|
||||
head = /obj/item/clothing/head/helmet/space/plasmaman
|
||||
if(new_species_type == /datum/species/lizard)
|
||||
shoes = null //digitigrade says no
|
||||
if(regular_uniform)
|
||||
uniform = /obj/item/clothing/under/rank/cargo/miner/lavaland
|
||||
if(prob(4))
|
||||
belt = pick_weight(list(/obj/item/storage/belt/mining = 2, /obj/item/storage/belt/mining/alt = 2))
|
||||
belt = pick_weight(list(
|
||||
/obj/item/storage/belt/mining = 2,
|
||||
/obj/item/storage/belt/mining/alt = 2,
|
||||
))
|
||||
else if(prob(10))
|
||||
belt = pick_weight(list(/obj/item/pickaxe = 8, /obj/item/pickaxe/mini = 4, /obj/item/pickaxe/silver = 2, /obj/item/pickaxe/diamond = 1))
|
||||
belt = pick_weight(list(
|
||||
/obj/item/pickaxe = 8,
|
||||
/obj/item/pickaxe/mini = 4,
|
||||
/obj/item/pickaxe/silver = 2,
|
||||
/obj/item/pickaxe/diamond = 1,
|
||||
))
|
||||
else
|
||||
belt = /obj/item/tank/internals/emergency_oxygen/engi
|
||||
|
||||
if(prob(20))
|
||||
suit = pick_weight(list(/obj/item/clothing/suit/hooded/explorer = 18, /obj/item/clothing/suit/hooded/cloak/goliath = 2))
|
||||
suit = pick_weight(list(
|
||||
/obj/item/clothing/suit/hooded/explorer = 18,
|
||||
/obj/item/clothing/suit/hooded/cloak/goliath = 2,
|
||||
))
|
||||
if(prob(30))
|
||||
r_pocket = pick_weight(list(/obj/item/stack/marker_beacon = 20, /obj/item/stack/spacecash/c1000 = 7, /obj/item/reagent_containers/hypospray/medipen/survival = 2, /obj/item/borg/upgrade/modkit/damage = 1 ))
|
||||
r_pocket = pick_weight(list(
|
||||
/obj/item/stack/marker_beacon = 20,
|
||||
/obj/item/stack/spacecash/c1000 = 7,
|
||||
/obj/item/reagent_containers/hypospray/medipen/survival = 2,
|
||||
/obj/item/borg/upgrade/modkit/damage = 1,
|
||||
))
|
||||
if(prob(10))
|
||||
l_pocket = pick_weight(list(/obj/item/stack/spacecash/c1000 = 7, /obj/item/reagent_containers/hypospray/medipen/survival = 2, /obj/item/borg/upgrade/modkit/cooldown = 1 ))
|
||||
l_pocket = pick_weight(list(
|
||||
/obj/item/stack/spacecash/c1000 = 7,
|
||||
/obj/item/reagent_containers/hypospray/medipen/survival = 2,
|
||||
/obj/item/borg/upgrade/modkit/cooldown = 1,
|
||||
))
|
||||
|
||||
/datum/outfit/consumed_ashwalker
|
||||
name = "Legion-Consumed Ashwalker"
|
||||
@@ -106,17 +131,20 @@
|
||||
if(prob(95))
|
||||
head = /obj/item/clothing/head/helmet/gladiator
|
||||
else
|
||||
head = /obj/item/clothing/head/helmet/skull
|
||||
suit = /obj/item/clothing/suit/armor/bone
|
||||
gloves = /obj/item/clothing/gloves/bracer
|
||||
head = /obj/item/clothing/head/helmet/skull
|
||||
if(prob(5))
|
||||
back = pick_weight(list(/obj/item/spear/bonespear = 3, /obj/item/fireaxe/boneaxe = 2))
|
||||
back = pick_weight(list(
|
||||
/obj/item/spear/bonespear = 3,
|
||||
/obj/item/fireaxe/boneaxe = 2,
|
||||
))
|
||||
if(prob(10))
|
||||
belt = /obj/item/storage/belt/mining/primitive
|
||||
if(prob(30))
|
||||
r_pocket = /obj/item/knife/combat/bone
|
||||
if(prob(30))
|
||||
l_pocket = /obj/item/knife/combat/bone
|
||||
if(prob(30))
|
||||
r_pocket = /obj/item/knife/combat/bone
|
||||
|
||||
//takes a lot from the clown job, notably NO PDA and different backpack loot + pocket goodies
|
||||
/datum/outfit/consumed_clown
|
||||
@@ -140,7 +168,14 @@
|
||||
if(!visualsOnly)
|
||||
clown.fully_replace_character_name(clown.name, pick(GLOB.clown_names))
|
||||
if(prob(70))
|
||||
var/backpack_loot = pick(list(/obj/item/stamp/clown = 1, /obj/item/reagent_containers/spray/waterflower = 1, /obj/item/food/grown/banana = 1, /obj/item/megaphone/clown = 1, /obj/item/reagent_containers/cup/soda_cans/canned_laughter = 1, /obj/item/pneumatic_cannon/pie))
|
||||
var/backpack_loot = pick(list(
|
||||
/obj/item/food/grown/banana = 1,
|
||||
/obj/item/megaphone/clown = 1,
|
||||
/obj/item/pneumatic_cannon/pie,
|
||||
/obj/item/reagent_containers/cup/soda_cans/canned_laughter = 1,
|
||||
/obj/item/reagent_containers/spray/waterflower = 1,
|
||||
/obj/item/stamp/clown = 1,
|
||||
))
|
||||
if(backpack_loot == /obj/item/pneumatic_cannon/pie)
|
||||
drop_a_pie_cannon = TRUE
|
||||
else
|
||||
@@ -148,7 +183,10 @@
|
||||
if(prob(30))
|
||||
backpack_contents += list(/obj/item/stack/sheet/mineral/bananium = pick_weight(list( 1 = 3, 2 = 2, 3 = 1)))
|
||||
if(prob(10))
|
||||
l_pocket = pick_weight(list(/obj/item/bikehorn/golden = 3, /obj/item/bikehorn/airhorn = 1))
|
||||
l_pocket = pick_weight(list(
|
||||
/obj/item/bikehorn/golden = 3,
|
||||
/obj/item/bikehorn/airhorn = 1,
|
||||
))
|
||||
if(prob(10))
|
||||
r_pocket = /obj/item/implanter/sad_trombone
|
||||
|
||||
@@ -163,26 +201,46 @@
|
||||
|
||||
/datum/outfit/consumed_golem/pre_equip(mob/living/carbon/human/golem, visualsOnly = FALSE)
|
||||
if(!visualsOnly)
|
||||
golem.set_species(pick(/datum/species/golem/adamantine, /datum/species/golem/plasma, /datum/species/golem/diamond, /datum/species/golem/gold, /datum/species/golem/silver, /datum/species/golem/plasteel, /datum/species/golem/titanium, /datum/species/golem/plastitanium))
|
||||
golem.set_species(pick(
|
||||
/datum/species/golem/adamantine,
|
||||
/datum/species/golem/diamond,
|
||||
/datum/species/golem/gold,
|
||||
/datum/species/golem/plasma,
|
||||
/datum/species/golem/plasteel,
|
||||
/datum/species/golem/plastitanium,
|
||||
/datum/species/golem/silver,
|
||||
/datum/species/golem/titanium,
|
||||
))
|
||||
if(prob(30))
|
||||
glasses = pick_weight(list(/obj/item/clothing/glasses/meson = 2, /obj/item/clothing/glasses/hud/health = 2, /obj/item/clothing/glasses/hud/diagnostic =2, /obj/item/clothing/glasses/science = 2, /obj/item/clothing/glasses/welding = 2, /obj/item/clothing/glasses/night = 1))
|
||||
glasses = pick_weight(list(
|
||||
/obj/item/clothing/glasses/hud/diagnostic = 2,
|
||||
/obj/item/clothing/glasses/hud/health = 2,
|
||||
/obj/item/clothing/glasses/meson = 2,
|
||||
/obj/item/clothing/glasses/science = 2,
|
||||
/obj/item/clothing/glasses/welding = 2,
|
||||
/obj/item/clothing/glasses/night = 1,
|
||||
))
|
||||
if(prob(10) && !visualsOnly) //visualsonly = not a golem = can't put things in the belt slot without a jumpsuit
|
||||
belt = pick(list(/obj/item/storage/belt/mining/vendor, /obj/item/storage/belt/utility/full))
|
||||
belt = pick(list(
|
||||
/obj/item/crowbar/power,
|
||||
/obj/item/screwdriver/power,
|
||||
/obj/item/storage/belt/mining/vendor,
|
||||
/obj/item/storage/belt/utility/full,
|
||||
/obj/item/weldingtool/experimental,
|
||||
))
|
||||
if(prob(50))
|
||||
neck = /obj/item/bedsheet/rd/royal_cape
|
||||
if(prob(10) && !visualsOnly) //visualsonly = not a golem = can't put things in the pockets without a jumpsuit
|
||||
l_pocket = pick(list(/obj/item/crowbar/power, /obj/item/screwdriver/power, /obj/item/weldingtool/electric)) // SKYRAT EDIT CHANGE FROM /obj/item/weldingtool/experimental
|
||||
|
||||
//this is so pointlessly gendered but whatever bro i'm here to refactor not judge
|
||||
/datum/outfit/consumed_dame
|
||||
name = "Legion-Consumed Dame"
|
||||
uniform = /obj/item/clothing/under/costume/maid
|
||||
gloves = /obj/item/clothing/gloves/color/white
|
||||
shoes = /obj/item/clothing/shoes/laceup
|
||||
head = /obj/item/clothing/head/helmet/knight
|
||||
suit = /obj/item/clothing/suit/armor/riot/knight
|
||||
r_pocket = /obj/item/tank/internals/emergency_oxygen
|
||||
gloves = /obj/item/clothing/gloves/color/white
|
||||
head = /obj/item/clothing/head/helmet/knight
|
||||
mask = /obj/item/clothing/mask/breath
|
||||
shoes = /obj/item/clothing/shoes/laceup
|
||||
r_pocket = /obj/item/tank/internals/emergency_oxygen
|
||||
|
||||
/datum/outfit/consumed_dame/pre_equip(mob/living/carbon/human/dame, visualsOnly = FALSE)
|
||||
if(!visualsOnly)
|
||||
@@ -197,14 +255,15 @@
|
||||
|
||||
/datum/outfit/consumed_shadowperson
|
||||
name = "Legion-Consumed Shadowperson"
|
||||
r_pocket = /obj/item/reagent_containers/pill/shadowtoxin
|
||||
accessory = /obj/item/clothing/accessory/medal/plasma/nobel_science
|
||||
uniform = /obj/item/clothing/under/color/black
|
||||
shoes = /obj/item/clothing/shoes/sneakers/black
|
||||
suit = /obj/item/clothing/suit/toggle/labcoat
|
||||
glasses = /obj/item/clothing/glasses/blindfold
|
||||
back = /obj/item/tank/internals/oxygen
|
||||
glasses = /obj/item/clothing/glasses/blindfold
|
||||
mask = /obj/item/clothing/mask/breath
|
||||
shoes = /obj/item/clothing/shoes/sneakers/black
|
||||
r_pocket = /obj/item/reagent_containers/pill/shadowtoxin
|
||||
|
||||
accessory = /obj/item/clothing/accessory/medal/plasma/nobel_science
|
||||
|
||||
/datum/outfit/consumed_shadowperson/pre_equip(mob/living/carbon/human/shadowperson, visualsOnly = FALSE)
|
||||
if(visualsOnly)
|
||||
@@ -217,5 +276,10 @@
|
||||
suit = /obj/item/clothing/suit/hooded/cultrobes
|
||||
suit_store = /obj/item/tome
|
||||
back = /obj/item/storage/backpack/cultpack
|
||||
backpack_contents = list(
|
||||
/obj/item/cult_shift = 1,
|
||||
/obj/item/flashlight/flare/culttorch = 1,
|
||||
/obj/item/reagent_containers/cup/beaker/unholywater = 1,
|
||||
/obj/item/stack/sheet/runed_metal = 15,
|
||||
)
|
||||
r_pocket = /obj/item/clothing/glasses/hud/health/night/cultblind
|
||||
backpack_contents = list(/obj/item/reagent_containers/cup/beaker/unholywater = 1, /obj/item/cult_shift = 1, /obj/item/flashlight/flare/culttorch = 1, /obj/item/stack/sheet/runed_metal = 15)
|
||||
|
||||
@@ -322,13 +322,7 @@
|
||||
var/decrement = 1
|
||||
var/atom/location = loc
|
||||
if (reactionary)
|
||||
if(location.density || !isturf(location))
|
||||
decrement += location.explosion_block
|
||||
for(var/obj/thing in location)
|
||||
if (thing == src)
|
||||
continue
|
||||
var/the_block = thing.explosion_block
|
||||
decrement += the_block == EXPLOSION_BLOCK_PROC ? thing.GetExplosionBlock() : the_block
|
||||
decrement += location.explosive_resistance
|
||||
|
||||
range = max(range - decrement + 1, 0) // Already decremented by 1 in the parent. Exists so that if we pass through something with negative block it extends the range.
|
||||
heavy_ex_range = max(heavy_ex_range - decrement, 0)
|
||||
|
||||
@@ -260,7 +260,7 @@
|
||||
desc = "Used to set the destination of properly wrapped packages."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "cargo tagger"
|
||||
worn_icon_state = "cargo tagger"
|
||||
worn_icon_state = "cargotagger"
|
||||
var/currTag = 0 //Destinations are stored in code\globalvars\lists\flavor_misc.dm
|
||||
var/locked_destination = FALSE //if true, users can't open the destination tag window to prevent changing the tagger's current destination
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
|
||||
@@ -18,6 +18,12 @@ If you create T5+ please take a pass at mech_fabricator.dm. The parts being good
|
||||
. = ..()
|
||||
create_storage(type = /datum/storage/rped)
|
||||
|
||||
// check to see if this rped have atleast one circuitboard
|
||||
/obj/item/storage/part_replacer/proc/has_an_circuitboard()
|
||||
for(var/obj/item/circuitboard/machine/board in contents)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/storage/part_replacer/pre_attack(obj/attacked_object, mob/living/user, params)
|
||||
if(!ismachinery(attacked_object) && !istype(attacked_object, /obj/structure/frame/machine))
|
||||
return ..()
|
||||
@@ -37,13 +43,12 @@ If you create T5+ please take a pass at mech_fabricator.dm. The parts being good
|
||||
return TRUE
|
||||
|
||||
var/obj/structure/frame/machine/attacked_frame = attacked_object
|
||||
|
||||
if(!attacked_frame.components)
|
||||
return ..()
|
||||
|
||||
// no point attacking the frame with the rped if the frame doesn't have wiring or it doesn't have components & rped has no circuitboard to offer as an component.
|
||||
if(attacked_frame.state == 1 || (!attacked_frame.components && !has_an_circuitboard()))
|
||||
return TRUE
|
||||
attacked_frame.attackby(src, user)
|
||||
if(works_from_distance)
|
||||
user.Beam(attacked_frame, icon_state = "rped_upgrade", time = 5)
|
||||
attacked_frame.attackby(src, user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/storage/part_replacer/afterattack(obj/attacked_object, mob/living/user, adjacent, params)
|
||||
@@ -65,13 +70,12 @@ If you create T5+ please take a pass at mech_fabricator.dm. The parts being good
|
||||
return
|
||||
|
||||
var/obj/structure/frame/machine/attacked_frame = attacked_object
|
||||
|
||||
if(!attacked_frame.components)
|
||||
return ..()
|
||||
|
||||
// no point attacking the frame with the rped if the frame doesn't have wiring or it doesn't have components & rped has no circuitboard to offer as an component.
|
||||
if(attacked_frame.state == 1 || (!attacked_frame.components && !has_an_circuitboard()))
|
||||
return
|
||||
attacked_frame.attackby(src, user)
|
||||
if(works_from_distance)
|
||||
user.Beam(attacked_frame, icon_state = "rped_upgrade", time = 5)
|
||||
attacked_frame.attackby(src, user)
|
||||
|
||||
/obj/item/storage/part_replacer/proc/play_rped_sound()
|
||||
//Plays the sound for RPED exhanging or installing parts.
|
||||
@@ -220,6 +224,9 @@ If you create T5+ please take a pass at mech_fabricator.dm. The parts being good
|
||||
var/list/part_list = list()
|
||||
//Assemble a list of current parts, then sort them by their rating!
|
||||
for(var/obj/item/component_part in contents)
|
||||
//No need to put circuit boards in this list
|
||||
if(istype(component_part, /obj/item/circuitboard))
|
||||
continue
|
||||
part_list += component_part
|
||||
//Sort the parts. This ensures that higher tier items are applied first.
|
||||
part_list = sortTim(part_list, GLOBAL_PROC_REF(cmp_rped_sort))
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
/// The base for a contextual tutorial.
|
||||
/// In order to give a tutorial to someone, use `SStutorials.suggest_tutorial(user, /datum/tutorial/subtype)`
|
||||
/datum/tutorial
|
||||
/// If set, any account who started playing before this date will not be given this tutorial.
|
||||
/// Date is in YYYY-MM-DD format.
|
||||
var/grandfather_date
|
||||
|
||||
/// The mob we are giving the tutorial to
|
||||
VAR_PROTECTED/mob/user
|
||||
|
||||
VAR_PRIVATE/atom/movable/screen/tutorial_instruction/instruction_screen
|
||||
|
||||
/datum/tutorial/New(mob/user)
|
||||
src.user = user
|
||||
|
||||
RegisterSignal(user, COMSIG_PARENT_QDELETING, PROC_REF(destroy_self))
|
||||
RegisterSignal(user.client, COMSIG_PARENT_QDELETING, PROC_REF(destroy_self))
|
||||
|
||||
/datum/tutorial/Destroy(force, ...)
|
||||
user.client?.screen -= instruction_screen
|
||||
QDEL_NULL(instruction_screen)
|
||||
|
||||
user = null
|
||||
|
||||
return ..()
|
||||
|
||||
/// Gets the [`/datum/tutorial_manager`] that owns this tutorial.
|
||||
/datum/tutorial/proc/manager()
|
||||
RETURN_TYPE(/datum/tutorial_manager)
|
||||
return SStutorials.tutorial_managers[type]
|
||||
|
||||
/// The actual steps of the tutorial. Is given any excess arguments of suggest_tutorial.
|
||||
/// Must be overridden.
|
||||
/datum/tutorial/proc/perform()
|
||||
SHOULD_CALL_PARENT(FALSE)
|
||||
CRASH("[type] does not override perform()")
|
||||
|
||||
/// Returns TRUE/FALSE if this tutorial should be given.
|
||||
/// If FALSE, does not mean it won't come back later.
|
||||
/datum/tutorial/proc/should_perform()
|
||||
SHOULD_CALL_PARENT(FALSE)
|
||||
return TRUE
|
||||
|
||||
/// Called by the tutorial when the user has successfully completed it.
|
||||
/// Will mark it as completed in the datbaase and kick off destruction of the tutorial.
|
||||
/datum/tutorial/proc/complete()
|
||||
SIGNAL_HANDLER
|
||||
PROTECTED_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
|
||||
manager().complete(user)
|
||||
perform_base_completion_effects()
|
||||
|
||||
/// As opposed to `complete()`, this merely hides the tutorial.
|
||||
/// This should be used when the user doesn't need the tutorial anymore, but didn't
|
||||
/// actually properly finish it.
|
||||
/datum/tutorial/proc/dismiss()
|
||||
SIGNAL_HANDLER
|
||||
PROTECTED_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
|
||||
manager().dismiss(user)
|
||||
perform_base_completion_effects()
|
||||
|
||||
#define INSTRUCTION_SCREEN_DELAY (1 SECONDS)
|
||||
|
||||
/datum/tutorial/proc/perform_base_completion_effects()
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
|
||||
var/delay = perform_completion_effects_with_delay()
|
||||
|
||||
if (!isnull(instruction_screen))
|
||||
animate(instruction_screen, time = INSTRUCTION_SCREEN_DELAY, alpha = 0, easing = SINE_EASING)
|
||||
delay += INSTRUCTION_SCREEN_DELAY
|
||||
|
||||
QDEL_IN(src, delay)
|
||||
|
||||
/// Called when the tutorial is being hidden, but before it is deleted.
|
||||
/// You should unregister signals and fade out any of your creations in here.
|
||||
/// Returns how long extra to delay the deletion.
|
||||
/datum/tutorial/proc/perform_completion_effects_with_delay()
|
||||
SHOULD_CALL_PARENT(FALSE)
|
||||
PROTECTED_PROC(TRUE)
|
||||
|
||||
return 0
|
||||
|
||||
#undef INSTRUCTION_SCREEN_DELAY
|
||||
|
||||
/datum/tutorial/proc/destroy_self()
|
||||
SIGNAL_HANDLER
|
||||
PRIVATE_PROC(TRUE)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
|
||||
manager().dismiss(user)
|
||||
qdel(src)
|
||||
|
||||
/// Shows a large piece of text on the user's screen with the given message.
|
||||
/// If a message already exists, will fade it out and replace it.
|
||||
/datum/tutorial/proc/show_instruction(message)
|
||||
PROTECTED_PROC(TRUE)
|
||||
|
||||
if (isnull(instruction_screen))
|
||||
instruction_screen = new(null, message, user.client)
|
||||
user.client?.screen += instruction_screen
|
||||
else
|
||||
instruction_screen.change_message(message)
|
||||
|
||||
/// Given a keybind and a message, will replace %KEY% in `message` with the first keybind they have.
|
||||
/// As a fallback, will return the third parameter, `message_without_keybinds`, if none are set.
|
||||
/datum/tutorial/proc/keybinding_message(datum/keybinding/keybinding_type, message, message_without_keybinds)
|
||||
PROTECTED_PROC(TRUE)
|
||||
|
||||
var/list/keybinds = user.client?.prefs.key_bindings[initial(keybinding_type.name)]
|
||||
return keybinds?.len > 0 ? replacetext(message, "%KEY%", "<b>[keybinds[1]]</b>") : message_without_keybinds
|
||||
|
||||
/// Creates a UI element with the given `icon_state`, starts it at `initial_screen_loc`, and animates it to `target_screen_loc`.
|
||||
/// Waits `animate_start_time` before moving.
|
||||
/datum/tutorial/proc/animate_ui_element(icon_state, initial_screen_loc, target_screen_loc, animate_start_time)
|
||||
PROTECTED_PROC(TRUE)
|
||||
|
||||
var/atom/movable/screen/preview = new
|
||||
preview.icon = ui_style2icon(user.client?.prefs.read_preference(/datum/preference/choiced/ui_style) || GLOB.available_ui_styles[1])
|
||||
preview.icon_state = icon_state
|
||||
preview.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
preview.screen_loc = "1,1"
|
||||
|
||||
var/view = user.client?.view
|
||||
|
||||
var/list/origin_offsets = screen_loc_to_offset(initial_screen_loc, view)
|
||||
|
||||
// A little offset to the right
|
||||
var/matrix/origin_transform = TRANSLATE_MATRIX(origin_offsets[1] - world.icon_size * 0.5, origin_offsets[2] - world.icon_size * 1.5)
|
||||
|
||||
var/list/target_offsets = screen_loc_to_offset(target_screen_loc, view)
|
||||
// `- world.icon_Size * 0.5` to patch over a likely bug in screen_loc_to_offset with CENTER, needs more looking at
|
||||
var/matrix/animate_to_transform = TRANSLATE_MATRIX(target_offsets[1] - world.icon_size * 1.5, target_offsets[2] - world.icon_size)
|
||||
|
||||
preview.transform = origin_transform
|
||||
|
||||
preview.alpha = 0
|
||||
animate(preview, time = animate_start_time, alpha = 255, easing = CUBIC_EASING)
|
||||
animate(1.4 SECONDS)
|
||||
animate(transform = animate_to_transform, time = 2 SECONDS, easing = SINE_EASING | EASE_IN)
|
||||
animate(alpha = 0, time = 2.4 SECONDS, easing = CUBIC_EASING | EASE_IN, flags = ANIMATION_PARALLEL)
|
||||
|
||||
user.client?.screen += preview
|
||||
|
||||
return preview
|
||||
|
||||
/// A singleton that manages when to create tutorials of a specific tutorial type.
|
||||
/datum/tutorial_manager
|
||||
VAR_PRIVATE/datum/tutorial/tutorial_type
|
||||
|
||||
/// ckeys that we know have finished the tutorial
|
||||
VAR_PRIVATE/list/finished_ckeys = list()
|
||||
|
||||
/// ckeys that have performed the tutorial, but have not completed it.
|
||||
/// Doesn't mean that they can still see the tutorial, might have meant the tutorial was dismissed
|
||||
/// without being completed, such as during a log out.
|
||||
VAR_PRIVATE/list/performing_ckeys = list()
|
||||
|
||||
/datum/tutorial_manager/New(tutorial_type)
|
||||
ASSERT(ispath(tutorial_type, /datum/tutorial))
|
||||
src.tutorial_type = tutorial_type
|
||||
|
||||
/datum/tutorial_manager/Destroy(force, ...)
|
||||
if (!force)
|
||||
stack_trace("Something is trying to destroy [type], which is a singleton")
|
||||
return QDEL_HINT_LETMELIVE
|
||||
return ..()
|
||||
|
||||
/// Checks if we should perform the tutorial for the given user, and performs if so.
|
||||
/// Use `SStutorials.suggest_tutorial` instead of calling this directly.
|
||||
/datum/tutorial_manager/proc/try_perform(mob/user, list/arguments)
|
||||
var/datum/tutorial/tutorial = new tutorial_type(user)
|
||||
if (!tutorial.should_perform(user))
|
||||
qdel(tutorial)
|
||||
return
|
||||
|
||||
performing_ckeys[user.ckey] = TRUE
|
||||
|
||||
tutorial.perform(arglist(arguments))
|
||||
|
||||
/// Checks if the user should be given this tutorial
|
||||
/datum/tutorial_manager/proc/should_run(mob/user)
|
||||
var/ckey = user.ckey
|
||||
|
||||
if (isnull(ckey))
|
||||
return FALSE
|
||||
|
||||
if (ckey in finished_ckeys)
|
||||
return FALSE
|
||||
|
||||
if (ckey in performing_ckeys)
|
||||
return FALSE
|
||||
|
||||
if (!SSdbcore.IsConnected())
|
||||
return CONFIG_GET(flag/give_tutorials_without_db)
|
||||
|
||||
var/player_join_date = user.client?.player_join_date
|
||||
if (isnull(player_join_date))
|
||||
return FALSE
|
||||
|
||||
// This works because ISO-8601 is cool
|
||||
var/grandfather_date = initial(tutorial_type.grandfather_date)
|
||||
if (!isnull(grandfather_date) && player_join_date < grandfather_date)
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/// Marks the tutorial as completed.
|
||||
/// Call `/datum/tutorial/proc/complete()` instead.
|
||||
/datum/tutorial_manager/proc/complete(mob/user)
|
||||
set waitfor = FALSE
|
||||
|
||||
ASSERT(!isnull(user.ckey))
|
||||
|
||||
finished_ckeys[user.ckey] = TRUE
|
||||
performing_ckeys -= user.ckey
|
||||
|
||||
SSblackbox.record_feedback("tally", "tutorial_completed", 1, "[tutorial_type]")
|
||||
log_game("[key_name(user)] completed the [tutorial_type] tutorial.")
|
||||
|
||||
if (SSdbcore.IsConnected())
|
||||
INVOKE_ASYNC(src, PROC_REF(log_completion_to_database), user.ckey)
|
||||
|
||||
/datum/tutorial_manager/proc/log_completion_to_database(ckey)
|
||||
PRIVATE_PROC(TRUE)
|
||||
|
||||
var/datum/db_query/insert_tutorial_query = SSdbcore.NewQuery(
|
||||
"INSERT INTO [format_table_name("tutorial_completions")] (ckey, tutorial_key) VALUES (:ckey, :tutorial_key) ON DUPLICATE KEY UPDATE tutorial_key = tutorial_key",
|
||||
list(
|
||||
"ckey" = ckey,
|
||||
"tutorial_key" = get_key(),
|
||||
)
|
||||
)
|
||||
|
||||
insert_tutorial_query.warn_execute()
|
||||
|
||||
qdel(insert_tutorial_query)
|
||||
|
||||
/// Dismisses the tutorial, not marking it as completed in the database.
|
||||
/// Call `/datum/tutorial/proc/dismiss()` instead.
|
||||
/datum/tutorial_manager/proc/dismiss(mob/user)
|
||||
performing_ckeys -= user.ckey
|
||||
|
||||
/// Given a ckey, will mark them as being completed without affecting the database.
|
||||
/// Call `/datum/tutorial/proc/complete()` instead.
|
||||
/datum/tutorial_manager/proc/mark_as_completed(ckey)
|
||||
finished_ckeys[ckey] = TRUE
|
||||
performing_ckeys -= ckey
|
||||
|
||||
/// Gives the key that will be saved in the database.
|
||||
/// Must be 64 characters or less.
|
||||
/datum/tutorial_manager/proc/get_key()
|
||||
SHOULD_BE_PURE(TRUE)
|
||||
return copytext("[tutorial_type]", length("[/datum/tutorial]") + 2)
|
||||
@@ -0,0 +1,53 @@
|
||||
/atom/movable/screen/tutorial_instruction
|
||||
icon = 'icons/effects/alphacolors.dmi'
|
||||
icon_state = "white"
|
||||
color = COLOR_NEARLY_ALL_BLACK
|
||||
alpha = 0
|
||||
screen_loc = "TOP-2,CENTER"
|
||||
layer = TUTORIAL_INSTRUCTIONS_LAYER
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
var/client/client
|
||||
var/atom/movable/screen/tutorial_instruction_text/instruction_text
|
||||
|
||||
/atom/movable/screen/tutorial_instruction/Initialize(mapload, message, client/client)
|
||||
. = ..()
|
||||
|
||||
transform = transform.Scale(36, 2.5)
|
||||
|
||||
src.client = client
|
||||
animate(src, alpha = 245, time = 0.8 SECONDS, easing = SINE_EASING)
|
||||
|
||||
instruction_text = new(src, message, client)
|
||||
vis_contents += instruction_text
|
||||
|
||||
/atom/movable/screen/tutorial_instruction/Destroy()
|
||||
client = null
|
||||
QDEL_NULL(instruction_text)
|
||||
|
||||
return ..()
|
||||
|
||||
/atom/movable/screen/tutorial_instruction/proc/change_message(message)
|
||||
instruction_text.change_message(message)
|
||||
|
||||
/atom/movable/screen/tutorial_instruction_text
|
||||
maptext_height = 480
|
||||
maptext_y = -2
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
layer = TUTORIAL_INSTRUCTIONS_LAYER
|
||||
|
||||
/atom/movable/screen/tutorial_instruction_text/Initialize(mapload, message, client/client)
|
||||
. = ..()
|
||||
|
||||
var/view = client?.view_size.getView()
|
||||
maptext_width = view ? view_to_pixels(view)[1] : 480
|
||||
pixel_x = (maptext_width - world.icon_size) * -0.5
|
||||
|
||||
change_message(message)
|
||||
|
||||
/atom/movable/screen/tutorial_instruction_text/proc/change_message(message)
|
||||
// We don't use MAPTEXT macro here because it doesn't handle big text
|
||||
message = "<span style='font-family: \"VCR OSD Mono\"; font-size: 22px; text-align: center'>[message]</span>"
|
||||
|
||||
animate(src, alpha = 0, time = (maptext ? 0.5 SECONDS : 0), easing = SINE_EASING)
|
||||
animate(alpha = 255, time = 0.5 SECONDS, maptext = message)
|
||||
@@ -0,0 +1,109 @@
|
||||
#define TIME_TO_START_MOVING_DROP_ICON (0.5 SECONDS)
|
||||
|
||||
#define STAGE_DROP_ITEM "STAGE_DROP_ITEM"
|
||||
#define STAGE_PICK_SOMETHING_UP "STAGE_PICK_SOMETHING_UP"
|
||||
|
||||
/// Tutorial for showing how to drop items.
|
||||
/// Fired when clicking on an item with another item with a filled inactive hand.
|
||||
/datum/tutorial/drop
|
||||
grandfather_date = "2023-01-07"
|
||||
|
||||
var/stage = STAGE_DROP_ITEM
|
||||
var/atom/movable/screen/drop_preview
|
||||
var/obj/last_held_item
|
||||
|
||||
/datum/tutorial/drop/Destroy(force, ...)
|
||||
last_held_item = null
|
||||
user.client?.screen -= drop_preview
|
||||
QDEL_NULL(drop_preview)
|
||||
return ..()
|
||||
|
||||
/datum/tutorial/drop/perform(list/params)
|
||||
create_drop_preview(params[SCREEN_LOC])
|
||||
addtimer(CALLBACK(src, PROC_REF(show_instructions)), TIME_TO_START_MOVING_DROP_ICON)
|
||||
|
||||
RegisterSignal(user, COMSIG_MOB_DROPPING_ITEM, PROC_REF(on_dropped_item))
|
||||
RegisterSignal(user, COMSIG_MOB_SWAP_HANDS, PROC_REF(on_swap_hands))
|
||||
RegisterSignal(user, COMSIG_LIVING_PICKED_UP_ITEM, PROC_REF(on_pick_up_item))
|
||||
|
||||
update_held_item()
|
||||
|
||||
/datum/tutorial/drop/perform_completion_effects_with_delay()
|
||||
UnregisterSignal(user, list(COMSIG_MOB_DROPPING_ITEM, COMSIG_MOB_SWAP_HANDS, COMSIG_LIVING_PICKED_UP_ITEM))
|
||||
if (!isnull(last_held_item))
|
||||
UnregisterSignal(last_held_item, COMSIG_MOVABLE_MOVED)
|
||||
|
||||
return 0
|
||||
|
||||
/datum/tutorial/drop/proc/create_drop_preview(initial_screen_loc)
|
||||
drop_preview = animate_ui_element(
|
||||
"act_drop",
|
||||
initial_screen_loc,
|
||||
ui_drop_throw,
|
||||
TIME_TO_START_MOVING_DROP_ICON,
|
||||
)
|
||||
|
||||
/datum/tutorial/drop/proc/show_instructions()
|
||||
if (QDELETED(src))
|
||||
return
|
||||
|
||||
switch (stage)
|
||||
if (STAGE_DROP_ITEM)
|
||||
show_instruction(keybinding_message(
|
||||
/datum/keybinding/mob/drop_item,
|
||||
"Press '%KEY%' to drop your current item",
|
||||
"Click '<b>DROP</b>' to drop your current item",
|
||||
))
|
||||
if (STAGE_PICK_SOMETHING_UP)
|
||||
show_instruction("Pick something up!")
|
||||
|
||||
/datum/tutorial/drop/proc/on_swap_hands()
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (isnull(user.get_active_held_item()))
|
||||
if (stage != STAGE_PICK_SOMETHING_UP)
|
||||
stage = STAGE_PICK_SOMETHING_UP
|
||||
show_instructions()
|
||||
else if (stage == STAGE_PICK_SOMETHING_UP)
|
||||
stage = STAGE_DROP_ITEM
|
||||
show_instructions()
|
||||
|
||||
update_held_item()
|
||||
|
||||
/datum/tutorial/drop/proc/on_dropped_item()
|
||||
SIGNAL_HANDLER
|
||||
|
||||
stage = STAGE_PICK_SOMETHING_UP
|
||||
show_instructions()
|
||||
|
||||
/datum/tutorial/drop/proc/on_pick_up_item()
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (stage != STAGE_PICK_SOMETHING_UP)
|
||||
dismiss()
|
||||
return
|
||||
|
||||
complete()
|
||||
|
||||
// Exists so that if we, say, place the item on a table, we don't count that as completion
|
||||
/datum/tutorial/drop/proc/update_held_item()
|
||||
if (!isnull(last_held_item))
|
||||
UnregisterSignal(last_held_item, COMSIG_MOVABLE_MOVED)
|
||||
|
||||
last_held_item = user.get_active_held_item()
|
||||
if (isnull(last_held_item))
|
||||
return
|
||||
|
||||
RegisterSignal(last_held_item, COMSIG_MOVABLE_MOVED, PROC_REF(on_held_item_moved))
|
||||
|
||||
/datum/tutorial/drop/proc/on_held_item_moved()
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (stage == STAGE_PICK_SOMETHING_UP)
|
||||
return
|
||||
|
||||
dismiss()
|
||||
|
||||
#undef STAGE_DROP_ITEM
|
||||
#undef STAGE_PICK_SOMETHING_UP
|
||||
#undef TIME_TO_START_MOVING_DROP_ICON
|
||||
@@ -0,0 +1,86 @@
|
||||
#define TIME_TO_START_MOVING_HAND_ICON (0.5 SECONDS)
|
||||
|
||||
#define STAGE_SHOULD_SWAP_HAND "STAGE_SHOULD_SWAP_HAND"
|
||||
#define STAGE_PICK_UP_ITEM "STAGE_PICK_UP_ITEM"
|
||||
|
||||
/// Tutorial for showing how to switch hands.
|
||||
/// Fired when clicking on an item with another item with an empty inactive hand.
|
||||
/datum/tutorial/switch_hands
|
||||
grandfather_date = "2023-01-07"
|
||||
|
||||
var/stage = STAGE_SHOULD_SWAP_HAND
|
||||
var/atom/movable/screen/hand_preview
|
||||
|
||||
// So that they don't just drop the item
|
||||
var/hand_to_watch
|
||||
|
||||
/datum/tutorial/switch_hands/New(mob/user)
|
||||
. = ..()
|
||||
|
||||
hand_to_watch = (user.active_hand_index % user.held_items.len) + 1
|
||||
|
||||
/datum/tutorial/switch_hands/Destroy(force, ...)
|
||||
user.client?.screen -= hand_preview
|
||||
QDEL_NULL(hand_preview)
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/tutorial/switch_hands/perform(list/params)
|
||||
create_hand_preview(params[SCREEN_LOC])
|
||||
addtimer(CALLBACK(src, PROC_REF(show_instructions)), TIME_TO_START_MOVING_HAND_ICON)
|
||||
|
||||
RegisterSignal(user, COMSIG_MOB_SWAP_HANDS, PROC_REF(on_swap_hands))
|
||||
RegisterSignal(user, COMSIG_LIVING_PICKED_UP_ITEM, PROC_REF(on_pick_up_item))
|
||||
|
||||
/datum/tutorial/switch_hands/perform_completion_effects_with_delay()
|
||||
UnregisterSignal(user, list(COMSIG_MOB_SWAP_HANDS, COMSIG_LIVING_PICKED_UP_ITEM))
|
||||
return 0
|
||||
|
||||
/datum/tutorial/switch_hands/proc/create_hand_preview(initial_screen_loc)
|
||||
hand_preview = animate_ui_element(
|
||||
"hand_[hand_to_watch % 2 == 0 ? "r" : "l"]",
|
||||
initial_screen_loc,
|
||||
ui_hand_position(hand_to_watch),
|
||||
TIME_TO_START_MOVING_HAND_ICON,
|
||||
)
|
||||
|
||||
/datum/tutorial/switch_hands/proc/show_instructions()
|
||||
if (QDELETED(src))
|
||||
return
|
||||
|
||||
switch (stage)
|
||||
if (STAGE_SHOULD_SWAP_HAND)
|
||||
var/hand_name = hand_to_watch % 2 == 0 ? "right" : "left"
|
||||
show_instruction(keybinding_message(
|
||||
/datum/keybinding/mob/swap_hands,
|
||||
"Press '%KEY%' to use your [hand_name] hand",
|
||||
"Click '<b>SWAP</b>' to use your [hand_name] hand",
|
||||
))
|
||||
if (STAGE_PICK_UP_ITEM)
|
||||
show_instruction("Pick something up!")
|
||||
|
||||
/datum/tutorial/switch_hands/proc/on_swap_hands()
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (isnull(user.get_active_held_item()))
|
||||
stage = STAGE_PICK_UP_ITEM
|
||||
show_instructions()
|
||||
else if (isnull(user.get_inactive_held_item()))
|
||||
stage = STAGE_SHOULD_SWAP_HAND
|
||||
show_instructions()
|
||||
else
|
||||
// You somehow got an item in both hands during the tutorial without switching hands.
|
||||
// Good job I guess?
|
||||
complete()
|
||||
|
||||
/datum/tutorial/switch_hands/proc/on_pick_up_item()
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if (user.active_hand_index != hand_to_watch)
|
||||
return
|
||||
|
||||
complete()
|
||||
|
||||
#undef STAGE_PICK_UP_ITEM
|
||||
#undef STAGE_SHOULD_SWAP_HAND
|
||||
#undef TIME_TO_START_MOVING_HAND_ICON
|
||||
@@ -208,10 +208,12 @@
|
||||
#include "tgui_create_message.dm"
|
||||
#include "timer_sanity.dm"
|
||||
#include "traitor.dm"
|
||||
#include "tutorial_sanity.dm"
|
||||
#include "unit_test.dm"
|
||||
#include "verify_config_tags.dm"
|
||||
#include "verify_emoji_names.dm"
|
||||
#include "wizard_loadout.dm"
|
||||
#include "worn_icons.dm"
|
||||
#ifdef REFERENCE_TRACKING_DEBUG //Don't try and parse this file if ref tracking isn't turned on. IE: don't parse ref tracking please mr linter
|
||||
#include "find_reference_sanity.dm"
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/// Verifies that every tutorial has properly set variables
|
||||
/datum/unit_test/tutorial_sanity
|
||||
|
||||
/datum/unit_test/tutorial_sanity/Run()
|
||||
var/regex/regex_valid_date = regex(@"\d{4}-\d{2}-\d{2}")
|
||||
var/list/keys = list()
|
||||
|
||||
for (var/datum/tutorial/tutorial_type as anything in SStutorials.tutorial_managers)
|
||||
var/datum/tutorial_manager/tutorial_manager = SStutorials.tutorial_managers[tutorial_type]
|
||||
|
||||
var/grandfather_date = initial(tutorial_type.grandfather_date)
|
||||
if (!isnull(grandfather_date))
|
||||
TEST_ASSERT(regex_valid_date.Find(grandfather_date), "[tutorial_type] has an invalid grandfather_date ([grandfather_date])")
|
||||
|
||||
var/key = tutorial_manager.get_key()
|
||||
TEST_ASSERT(!(key in keys), "[key] shows up twice")
|
||||
TEST_ASSERT(length(key) < 64, "[key] is more than 64 characters, it won't fit in the SQL table.")
|
||||
|
||||
TEST_ASSERT_EQUAL(SStutorials.tutorial_managers.len, length(subtypesof(/datum/tutorial)), "Expected tutorial_managers to have one of every tutorial")
|
||||
@@ -0,0 +1,117 @@
|
||||
/// Makes sure suit slot items aren't using CS:S fallbacks.
|
||||
/datum/unit_test/worn_icons
|
||||
var/static/list/possible_icon_states = list()
|
||||
/// additional_icon_location is for downstream modularity support for finding missing sprites in additonal DMI file locations.
|
||||
/// Make sure this location is also present in tools/deploy.sh
|
||||
/// If you need additional paths ontop of this second one, you can add another generate_possible_icon_states_list("your/folder/path/") below the if(additional_icon_location) block in Run(), and make sure to add that path to tools/deploy.sh as well.
|
||||
var/additional_icon_location = null
|
||||
|
||||
/datum/unit_test/worn_icons/proc/generate_possible_icon_states_list(directory_path)
|
||||
if(!directory_path)
|
||||
directory_path = "icons/mob/clothing/"
|
||||
for(var/file_path in flist(directory_path))
|
||||
if(findtext(file_path, ".dmi"))
|
||||
for(var/sprite_icon in icon_states("[directory_path][file_path]", 1)) //2nd arg = 1 enables 64x64+ icon support, otherwise you'll end up with "sword0_1" instead of "sword"
|
||||
possible_icon_states[sprite_icon] += list("[directory_path][file_path]")
|
||||
else
|
||||
possible_icon_states += generate_possible_icon_states_list("[directory_path][file_path]")
|
||||
|
||||
/datum/unit_test/worn_icons/Run()
|
||||
generate_possible_icon_states_list()
|
||||
if(additional_icon_location)
|
||||
generate_possible_icon_states_list(additional_icon_location)
|
||||
|
||||
var/list/already_warned_icons = list()
|
||||
|
||||
for(var/obj/item/item_path as anything in (subtypesof(/obj/item) - typesof(/obj/item/mod)))
|
||||
var/cached_slot_flags = initial(item_path.slot_flags)
|
||||
if(!cached_slot_flags || (cached_slot_flags & ITEM_SLOT_LPOCKET) || (cached_slot_flags & ITEM_SLOT_RPOCKET) || initial(item_path.item_flags) & ABSTRACT)
|
||||
continue
|
||||
|
||||
|
||||
if(initial(item_path.greyscale_colors) && initial(item_path.greyscale_config_worn)) //GAGS has its own unit test.
|
||||
continue
|
||||
|
||||
var/worn_icon = initial(item_path.worn_icon) //override icon file. where our sprite is contained if set. (ie modularity stuff)
|
||||
var/worn_icon_state = initial(item_path.worn_icon_state) //overrides icon_state.
|
||||
var/icon_state = worn_icon_state || initial(item_path.icon_state) //icon_state. what sprite name we are looking for.
|
||||
|
||||
|
||||
if(isnull(icon_state))
|
||||
continue //no sprite for the item.
|
||||
if(icon_state in already_warned_icons)
|
||||
continue
|
||||
|
||||
var/match_message
|
||||
if(icon_state in possible_icon_states)
|
||||
for(var/file_place in possible_icon_states[icon_state])
|
||||
match_message += (match_message ? " & '[file_place]'" : " - Matching sprite found in: '[file_place]'")
|
||||
|
||||
if(worn_icon) //easiest to check since we override everything. this automatically includes downstream support.
|
||||
if(!(icon_state in icon_states(worn_icon, 1)))
|
||||
TEST_FAIL("[item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in worn_icon override file, '[worn_icon]'[match_message]")
|
||||
continue
|
||||
|
||||
var/icon_file //checks against all the default icon locations if one isn't defined.
|
||||
var/fail_reasons
|
||||
var/spacer
|
||||
if(cached_slot_flags & ITEM_SLOT_BACK)
|
||||
icon_file = 'icons/mob/clothing/back.dmi'
|
||||
|
||||
if(!(icon_state in icon_states(icon_file, 1)))
|
||||
already_warned_icons += icon_state
|
||||
fail_reasons += "[item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in '[icon_file]'[match_message]"
|
||||
spacer = "\n\t"
|
||||
|
||||
if(cached_slot_flags & ITEM_SLOT_ID)
|
||||
icon_file = 'icons/mob/clothing/id.dmi'
|
||||
if(!(icon_state in icon_states(icon_file, 1)))
|
||||
already_warned_icons += icon_state
|
||||
fail_reasons += "[spacer][item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in '[icon_file]'[match_message]"
|
||||
spacer = "\n\t"
|
||||
|
||||
if(cached_slot_flags & ITEM_SLOT_GLOVES)
|
||||
icon_file = 'icons/mob/clothing/hands.dmi'
|
||||
if(!(icon_state in icon_states(icon_file, 1)))
|
||||
already_warned_icons += icon_state
|
||||
fail_reasons += "[spacer][item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in '[icon_file]'[match_message]"
|
||||
spacer = "\n\t"
|
||||
|
||||
if(cached_slot_flags & ITEM_SLOT_EYES)
|
||||
icon_file = 'icons/mob/clothing/eyes.dmi'
|
||||
if(!(icon_state in icon_states(icon_file, 1)))
|
||||
already_warned_icons += icon_state
|
||||
fail_reasons += "[spacer][item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in '[icon_file]'[match_message]"
|
||||
spacer = "\n\t"
|
||||
|
||||
if(cached_slot_flags & ITEM_SLOT_EARS)
|
||||
icon_file = 'icons/mob/clothing/ears.dmi'
|
||||
if(!(icon_state in icon_states(icon_file, 1)))
|
||||
already_warned_icons += icon_state
|
||||
fail_reasons += "[spacer][item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in '[icon_file]'[match_message]"
|
||||
spacer = "\n\t"
|
||||
|
||||
if(cached_slot_flags & ITEM_SLOT_NECK)
|
||||
icon_file = 'icons/mob/clothing/neck.dmi'
|
||||
if(!(icon_state in icon_states(icon_file, 1)))
|
||||
already_warned_icons += icon_state
|
||||
fail_reasons += "[spacer][item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in '[icon_file]'[match_message]"
|
||||
spacer = "\n\t"
|
||||
|
||||
if(cached_slot_flags & ITEM_SLOT_MASK)
|
||||
icon_file = 'icons/mob/clothing/mask.dmi'
|
||||
if(!(icon_state in icon_states(icon_file, 1)))
|
||||
already_warned_icons += icon_state
|
||||
fail_reasons += "[spacer][item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in '[icon_file]'[match_message]"
|
||||
spacer = "\n\t"
|
||||
|
||||
if(cached_slot_flags & ITEM_SLOT_BELT)
|
||||
icon_file = 'icons/mob/clothing/belt.dmi'
|
||||
if(!(icon_state in icon_states(icon_file, 1)))
|
||||
already_warned_icons += icon_state
|
||||
fail_reasons += "[spacer][item_path] using invalid [worn_icon_state ? "worn_icon_state" : "icon_state"], \"[icon_state]\" in '[icon_file]'[match_message]"
|
||||
spacer = "\n\t"
|
||||
|
||||
if(fail_reasons)
|
||||
TEST_FAIL(fail_reasons)
|
||||
|
||||
@@ -648,3 +648,7 @@ PR_ANNOUNCEMENTS_PER_ROUND 5
|
||||
|
||||
## Uncomment to block granting profiling privileges to users with R_DEBUG, for performance purposes
|
||||
#FORBID_ADMIN_PROFILING
|
||||
|
||||
## Comment to disable sending a toast notification on the host server when initializations complete.
|
||||
## Even if this is enabled, a notification will only be sent if there are no clients connected.
|
||||
TOAST_NOTIFICATION_ON_INIT
|
||||
|
||||
@@ -556,3 +556,8 @@ MAXFINE 2000
|
||||
## Comment if you wish to enable title music playing at the lobby screen. This flag is disabled by default to facilitate better code testing on local machines.
|
||||
## Do keep in mind that this flag will not affect individual player's preferences: if they opt-out on your server, it will never play for them.
|
||||
DISALLOW_TITLE_MUSIC
|
||||
|
||||
## If enabled, then when the database is disabled, all players will get tutorials.
|
||||
## This is primarily useful for developing tutorials. If you have a proper DB setup, you
|
||||
## don't need (or want) this.
|
||||
#GIVE_TUTORIALS_WITHOUT_DB
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
author: "SkyratBot"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "you can flip eyepatches"
|
||||
- bugfix: "blindfolds now take into consideration both eye colors for their color"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "Big chungus wholesome 100"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Amputated and reattached limbs now get wounded based on their own biology, not the current owner's biology."
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user