diff --git a/.editorconfig b/.editorconfig
index 1770177310de..5e08df597a3a 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,14 +1,17 @@
-[*]
-indent_style = tab
-indent_size = 4
-charset = utf-8
-trim_trailing_whitespace = true
-insert_final_newline = true
-end_of_line = lf
-
-[*.yml]
-indent_style = space
-indent_size = 2
-
-[*.py]
-indent_style = space
+[*]
+indent_style = tab
+indent_size = 4
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+end_of_line = lf
+
+[*.yml]
+indent_style = space
+indent_size = 2
+
+[*.py]
+indent_style = space
+
+[*.json]
+indent_style = space
diff --git a/.gitignore b/.gitignore
index 5731511cb76b..3e82ddf9387f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,16 +15,14 @@ cfg/
tmp/
tools/Runtime Condenser/Input.txt
tools/Runtime Condenser/Output.txt
-tools/MapDaemon/logs/*.txt
sound/music/*.ogg
sound/music/walkman/*/*.ogg
sound/music/walkman/*.txt
icons/custom/*
maps/**/backup
-*.json
*.before
__pycache__
test_environment.txt
-
+*.json
*.vscode/*
!/.vscode/extensions.json
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 06e7edfbc64d..b50b83f5b747 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,39 +1,42 @@
image: i386/ubuntu:xenial
-stages:
- - build
-
variables:
- BYOND_MAJOR: "513"
- BYOND_MINOR: "1527"
- SPACEMAN_DMM_VERSION: "1.6"
GITLAB_CHANGELOG_PID: "21031593"
GITLAB_REPO_LINK: "git@gitlab.com:cmdevs/colonial-warfare.git"
+stages:
+ - build
-before_script:
- - apt-get update -qq
- - apt-get --yes install build-essential unzip libc6:i386 libgcc1:i386 libstdc++6:i386 curl -qq
- - curl "http://www.byond.com/download/build/${BYOND_MAJOR}/${BYOND_MAJOR}.${BYOND_MINOR}_byond_linux.zip" -o byond.zip
- - unzip byond.zip
- - cd byond
- - make install
- - cd ..
- - curl -LJO "https://github.com/SpaceManiac/SpacemanDMM/releases/download/suite-${SPACEMAN_DMM_VERSION}/dreamchecker" -o dreamchecker
- - chmod +x dreamchecker
-
-build:
- stage: build
- script:
- - ./dreamchecker
- - chmod +rwx ./insert_maps_in_dme.sh
- - ./insert_maps_in_dme.sh
- - DreamMaker ColonialMarinesALPHA.dme
- artifacts:
- paths:
- - ColonialMarinesALPHA.dmb
- - ColonialMarinesALPHA.rsc
- expire_in: 20min
+run_linters:
+ stage: build
+ before_script:
+ - apt update
+ - apt install -y software-properties-common
+ - add-apt-repository ppa:deadsnakes/ppa
+ - apt update
+ - apt install -y curl unzip build-essential libssl-dev build-essential libc6:i386 libgcc1:i386 libstdc++6:i386 python3.7 wget
+ - bash tools/ci/install_spaceman_dmm.sh dreamchecker
+ script:
+ - find . -name "*.json" -not -path "*/node_modules/*" -print0 | xargs -0 python3 ./tools/json_verifier.py
+ - ~/dreamchecker
+compile_all_maps:
+ stage: build
+ before_script:
+ - apt update
+ - apt install -y software-properties-common
+ - add-apt-repository ppa:deadsnakes/ppa
+ - apt update
+ - apt install -y curl python3.7 unzip build-essential libc6:i386 libgcc1:i386 libstdc++6:i386
+ script:
+ - bash tools/ci/install_byond.sh
+ - source $HOME/BYOND/byond/bin/byondsetup
+ - python3 tools/ci/template_dm_generator.py
+ - bash tools/ci/dm.sh -DCIBUILDING -DCITESTING -DALL_MAPS ColonialMarinesALPHA.dme
+ artifacts:
+ paths:
+ - ColonialMarinesALPHA.dmb
+ - ColonialMarinesALPHA.rsc
+ expire_in: 20min
changelog:
stage: build
diff --git a/ColonialMarinesALPHA.dme b/ColonialMarinesALPHA.dme
index 4ed9a9e9f363..3d6dfb0dcfc4 100644
--- a/ColonialMarinesALPHA.dme
+++ b/ColonialMarinesALPHA.dme
@@ -47,6 +47,7 @@
#include "code\__DEFINES\icon_source_map.dm"
#include "code\__DEFINES\job.dm"
#include "code\__DEFINES\layers.dm"
+#include "code\__DEFINES\maps.dm"
#include "code\__DEFINES\marine.dm"
#include "code\__DEFINES\math_physics.dm"
#include "code\__DEFINES\MC.dm"
@@ -66,6 +67,7 @@
#include "code\__DEFINES\subsystem.dm"
#include "code\__DEFINES\tests.dm"
#include "code\__DEFINES\tgui.dm"
+#include "code\__DEFINES\turf_flags.dm"
#include "code\__DEFINES\urls.dm"
#include "code\__DEFINES\vehicle.dm"
#include "code\__DEFINES\vendors.dm"
@@ -137,7 +139,6 @@
#include "code\_onclick\hud\yautja.dm"
#include "code\controllers\_DynamicAreaLighting_TG.dm"
#include "code\controllers\shuttle_controller.dm"
-#include "code\controllers\voting.dm"
#include "code\controllers\configuration\config_entry.dm"
#include "code\controllers\configuration\configuration.dm"
#include "code\controllers\configuration\entries\combat_config.dm"
@@ -173,6 +174,7 @@
#include "code\controllers\subsystem\item_cleanup.dm"
#include "code\controllers\subsystem\lighting.dm"
#include "code\controllers\subsystem\machinery.dm"
+#include "code\controllers\subsystem\mapping.dm"
#include "code\controllers\subsystem\mapview.dm"
#include "code\controllers\subsystem\midi.dm"
#include "code\controllers\subsystem\mob.dm"
@@ -203,7 +205,6 @@
#include "code\controllers\subsystem\init\landmarks.dm"
#include "code\controllers\subsystem\init\law.dm"
#include "code\controllers\subsystem\init\lobby_art.dm"
-#include "code\controllers\subsystem\init\mapview.dm"
#include "code\controllers\subsystem\processing\objects.dm"
#include "code\controllers\subsystem\processing\processing.dm"
#include "code\datums\_atmos_setup.dm"
@@ -221,6 +222,7 @@
#include "code\datums\event_info_text.dm"
#include "code\datums\fluff_emails.dm"
#include "code\datums\global_variables.dm"
+#include "code\datums\map_config.dm"
#include "code\datums\matrix_editor.dm"
#include "code\datums\medal_awards.dm"
#include "code\datums\mind.dm"
@@ -430,6 +432,7 @@
#include "code\game\sound.dm"
#include "code\game\supplyshuttle.dm"
#include "code\game\world.dm"
+#include "code\game\area\admin_level.dm"
#include "code\game\area\almayer.dm"
#include "code\game\area\areas.dm"
#include "code\game\area\BigRed.dm"
@@ -445,7 +448,6 @@
#include "code\game\area\strata.dm"
#include "code\game\area\Sulaco.dm"
#include "code\game\area\WhiskeyOutpost.dm"
-#include "code\game\area\Z_Holder.dm"
#include "code\game\cas_manager\datums\cas_fire_envelope.dm"
#include "code\game\cas_manager\datums\cas_fire_mission.dm"
#include "code\game\cas_manager\datums\cas_iff_group.dm"
@@ -1047,6 +1049,7 @@
#include "code\modules\admin\IsBanned.dm"
#include "code\modules\admin\NewBan.dm"
#include "code\modules\admin\player_notes.dm"
+#include "code\modules\admin\server_verbs.dm"
#include "code\modules\admin\stickyban.dm"
#include "code\modules\admin\STUI.dm"
#include "code\modules\admin\ToRban.dm"
@@ -1120,6 +1123,7 @@
#include "code\modules\clans\ship.dm"
#include "code\modules\client\client_defines.dm"
#include "code\modules\client\client_procs.dm"
+#include "code\modules\client\player_details.dm"
#include "code\modules\client\preferences.dm"
#include "code\modules\client\preferences_factions.dm"
#include "code\modules\client\preferences_gear.dm"
@@ -1289,6 +1293,14 @@
#include "code\modules\law\laws\major_crime.dm"
#include "code\modules\law\laws\minor_crime.dm"
#include "code\modules\law\laws\optional.dm"
+#include "code\modules\mapping\map_template.dm"
+#include "code\modules\mapping\preloader.dm"
+#include "code\modules\mapping\reader.dm"
+#include "code\modules\mapping\verify.dm"
+#include "code\modules\mapping\space_management\space_level.dm"
+#include "code\modules\mapping\space_management\space_reservation.dm"
+#include "code\modules\mapping\space_management\traits.dm"
+#include "code\modules\mapping\space_management\zlevel_manager.dm"
#include "code\modules\maps\dmm_suite.dm"
#include "code\modules\maps\reader.dm"
#include "code\modules\mapview\generation.dm"
@@ -1815,9 +1827,5 @@
#include "code\modules\vehicles\tank\tank.dm"
#include "interface\interface.dm"
#include "interface\skin.dmf"
-#include "maps\Z.02.Admin_Level.dm"
-#include "maps\Z.01.LV624.dmm"
-#include "maps\Z.02.Admin_Level.dmm"
-#include "maps\Z.03.USS_Almayer.dmm"
-#include "maps\Z.04.Low_Orbit.dmm"
+#include "maps\_basemap.dm"
// END_INCLUDE
diff --git a/code/__DEFINES/__game.dm b/code/__DEFINES/__game.dm
index e1a1799caf2e..dc198be191eb 100644
--- a/code/__DEFINES/__game.dm
+++ b/code/__DEFINES/__game.dm
@@ -37,7 +37,7 @@
#define PLAYERCOUNT_LOWPOP_MAP_LIMIT 130 // number of players before we switch to lowpop maps only (LV, BR, Prison)
-#define PREROUND_TIME 240 // time before the round starts
+#define PREROUND_TIME 360 // time before the round starts
//A set of constants used to determine which type of mute an admin wishes to apply:
//Please read and understand the muting/automuting stuff before changing these. MUTE_IC_AUTO etc = (MUTE_IC << 1)
@@ -179,9 +179,6 @@
//=================================================
//Game mode related defines.
-var/list/accessable_z_levels = list("1" = 10, "3" = 10, "4" = 10, "5" = 70)
-//This list contains the z-level numbers which can be accessed via space travel and the percentile chances to get there.
-
#define TRANSITIONEDGE 3 //Distance from edge to move to another z-level
//Flags for zone sleeping
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index ec6a32a52f4c..3018271b6402 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -6,6 +6,8 @@
// These are signals which can be listened to by any component on any parent
// start global signals with "!", this used to be necessary but now it's just a formatting choice
+///from base of datum/controller/subsystem/mapping/proc/add_new_zlevel(): (list/args)
+#define COMSIG_GLOB_NEW_Z "!new_z"
///from base of datum/controller/subsystem/mapping/proc/add_new_zlevel(): (list/args)
#define COMSIG_GLOB_VEHICLE_ORDERED "!vehicle_ordered"
///from /datum/game_mode/proc/pre_setup
@@ -16,6 +18,7 @@
#define COMSIG_GLOB_MARINE_DEATH "!marine_death"
///from /mob/living/carbon/Xenomorph/death
#define COMSIG_GLOB_XENO_DEATH "!xeno_death"
+#define COMSIG_GLOB_REMOVE_VOTE_BUTTON "!remove_vote_button"
//////////////////////////////////////////////////////////////////
diff --git a/code/__DEFINES/equipment.dm b/code/__DEFINES/equipment.dm
index 96fcaa20a423..76db7338420e 100644
--- a/code/__DEFINES/equipment.dm
+++ b/code/__DEFINES/equipment.dm
@@ -24,6 +24,7 @@
#define CAN_BE_SYRINGED (1<<13) // syringes can inject or drain reagents in this even if it isn't an OPENCONTAINER
#define CAN_BE_DISPENSED_INTO (1<<14) // Chem dispenser can dispense in this even if it isn't an OPENCONTAINER
#define INITIALIZED (1<<15) // Initialized by SSatoms.
+#define ATOM_DECORATED (1<<16) // Has run Decorate() as part of subsystem init
//==========================================================================================
#define HANDLE_BARRIER_CHANCE 1
diff --git a/code/__DEFINES/icon_source_map.dm b/code/__DEFINES/icon_source_map.dm
index 7fb782ef53f3..ca63c788f582 100644
--- a/code/__DEFINES/icon_source_map.dm
+++ b/code/__DEFINES/icon_source_map.dm
@@ -1,7 +1,7 @@
GLOBAL_LIST_EMPTY(icon_source_files)
/proc/get_icon_from_source(source_name)
- var/icon/I = null
+ if(GLOB.icon_source_files[source_name])
+ return GLOB.icon_source_files[source_name]
GLOB.icon_source_files[source_name] = file(source_name)
- I = GLOB.icon_source_files[source_name]
- return I
+ return GLOB.icon_source_files[source_name]
diff --git a/code/__DEFINES/maps.dm b/code/__DEFINES/maps.dm
new file mode 100644
index 000000000000..4d1bc730048e
--- /dev/null
+++ b/code/__DEFINES/maps.dm
@@ -0,0 +1,116 @@
+/*
+The /tg/ codebase allows mixing of hardcoded and dynamically-loaded z-levels.
+Z-levels can be reordered as desired and their properties are set by "traits".
+See map_config.dm for how a particular station's traits may be chosen.
+The list DEFAULT_MAP_TRAITS at the bottom of this file should correspond to
+the maps that are hardcoded, as set in maps/_basemap.dm. SSmapping is
+responsible for loading every non-hardcoded z-level.
+
+
+Multi-Z stations are supported and multi-Z mining and away missions would
+require only minor tweaks.
+*/
+
+// helpers for modifying jobs, used in various job_changes.dm files
+#define MAP_JOB_CHECK if(SSmapping.configs[GROUND_MAP].map_name != JOB_MODIFICATION_MAP_NAME) { return; }
+#define MAP_JOB_CHECK_BASE if(SSmapping.configs[GROUND_MAP].map_name != JOB_MODIFICATION_MAP_NAME) { return ..(); }
+#define MAP_REMOVE_JOB(jobpath) /datum/job/##jobpath/map_check() { return (SSmapping.configs[GROUND_MAP].map_name != JOB_MODIFICATION_MAP_NAME) && ..() }
+
+#define SPACERUIN_MAP_EDGE_PAD 15
+
+// traits
+// boolean - marks a level as having that property if present
+#define ZTRAIT_STATION "Station"
+#define ZTRAIT_RESERVED "Transit/Reserved"
+#define ZTRAIT_GROUND "Ground"
+#define ZTRAIT_MARINE_MAIN_SHIP "Marine Main Ship"
+#define ZTRAIT_ADMIN "Admin"
+#define ZTRAIT_LOWORBIT "LowOrbit"
+#define ZTRAIT_HUNTER_SHIP "HunterShop"
+#define ZTRAIT_INTERIORS "Interiors"
+
+#define ZTRAIT_FOG "Fog"
+#define ZTRAIT_LOCKDOWN "Lockdown"
+
+// boolean - weather types that occur on the level
+#define ZTRAIT_SNOWSTORM "weather_snowstorm"
+#define ZTRAIT_ASHSTORM "weather_ashstorm"
+#define ZTRAIT_ACIDRAIN "weather_acidrain"
+#define ZTRAIT_SANDSTORM "weather_sandstorm"
+
+// number - bombcap is multiplied by this before being applied to bombs
+#define ZTRAIT_BOMBCAP_MULTIPLIER "Bombcap Multiplier"
+
+// number - default gravity if there's no gravity generators or area overrides present
+#define ZTRAIT_GRAVITY "Gravity"
+
+// numeric offsets - e.g. {"Down": -1} means that chasms will fall to z - 1 rather than oblivion
+#define ZTRAIT_UP "Up"
+#define ZTRAIT_DOWN "Down"
+
+// enum - how space transitions should affect this level
+#define ZTRAIT_LINKAGE "Linkage"
+ // UNAFFECTED if absent - no space transitions
+ #define UNAFFECTED null
+ // SELFLOOPING - space transitions always self-loop
+ #define SELFLOOPING "Self"
+ // CROSSLINKED - mixed in with the cross-linked space pool
+ #define CROSSLINKED "Cross"
+
+// string - type path of the z-level's baseturf (defaults to space)
+#define ZTRAIT_BASETURF "Baseturf"
+
+// default trait definitions, used by SSmapping
+#define ZTRAITS_MAIN_SHIP list(ZTRAIT_MARINE_MAIN_SHIP = TRUE)
+#define ZTRAITS_GROUND list(ZTRAIT_GROUND = TRUE)
+#define ZTRAITS_ADMIN list(ZTRAIT_ADMIN = TRUE)
+#define ZTRAITS_LOWORBIT list(ZTRAIT_LOWORBIT = TRUE)
+#define ZTRAITS_SPACE list(ZTRAIT_LINKAGE = CROSSLINKED, ZTRAIT_SPACE_RUINS = TRUE)
+#define ZTRAITS_INTERIORS list(ZTRAIT_INTERIORS = TRUE)
+
+#define DL_NAME "name"
+#define DL_TRAITS "traits"
+#define DECLARE_LEVEL(NAME, TRAITS) list(DL_NAME = NAME, DL_TRAITS = TRAITS)
+
+// must correspond to _basemap.dm for things to work correctly
+#define DEFAULT_MAP_TRAITS list(\
+ DECLARE_LEVEL("CentCom", ZTRAITS_ADMIN),\
+ DECLARE_LEVEL("LowOrbit", ZTRAITS_LOWORBIT),\
+)
+
+// Camera lock flags
+#define CAMERA_LOCK_SHIP (1<<0)
+#define CAMERA_LOCK_GROUND (1<<1)
+#define CAMERA_LOCK_ADMIN (1<<2)
+
+//Reserved/Transit turf type
+#define RESERVED_TURF_TYPE /turf/open/space/basic //What the turf is when not being used
+
+//Ruin Generation
+
+#define PLACEMENT_TRIES 100 //How many times we try to fit the ruin somewhere until giving up (really should just swap to some packing algo)
+
+#define PLACE_DEFAULT "random"
+#define PLACE_SAME_Z "same"
+#define PLACE_SPACE_RUIN "space"
+#define PLACE_LAVA_RUIN "lavaland"
+
+
+#define GROUND_MAP "ground_map"
+#define SHIP_MAP "ship_map"
+#define ALL_MAPTYPES list(GROUND_MAP, SHIP_MAP)
+#define MAP_TO_FILENAME list(GROUND_MAP = "data/next_map.json", SHIP_MAP = "data/next_ship.json")
+
+// traity things
+#define MAP_COLD "COLD"
+
+#define MAP_ARMOR_STYLE_DEFAULT "default"
+#define MAP_ARMOR_STYLE_ICE "ice"
+#define MAP_ARMOR_STYLE_JUNGLE "jungle"
+#define MAP_ARMOR_STYLE_PRISON "prison"
+
+//turf-only flags
+#define NOJAUNT_1 (1<<0)
+#define UNUSED_RESERVATION_TURF_1 (1<<1)
+/// If a turf can be made dirty at roundstart. This is also used in areas.
+#define CAN_BE_DIRTY_1 (1<<2)
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 924ba146fa86..3e9900c0614c 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -188,6 +188,9 @@
*/
#define get_area(A) (isarea(A) ? A : get_step(A, 0)?.loc)
+//Misc text define. Does 4 spaces. Used as a makeshift tabulator.
+#define FOURSPACES " "
+
//https://secure.byond.com/docs/ref/info.html#/atom/var/mouse_opacity
#define MOUSE_OPACITY_TRANSPARENT 0
#define MOUSE_OPACITY_ICON 1
diff --git a/code/__DEFINES/subsystem.dm b/code/__DEFINES/subsystem.dm
index 9febd392c513..df3c6e768e30 100644
--- a/code/__DEFINES/subsystem.dm
+++ b/code/__DEFINES/subsystem.dm
@@ -51,30 +51,31 @@
#define SS_INIT_TICKER_SPAWN 999
#define SS_INIT_RUST 26
#define SS_INIT_SUPPLY_SHUTTLE 25
-#define SS_INIT_GARBAGE 23
-#define SS_INIT_JOB 22
+#define SS_INIT_GARBAGE 24
+#define SS_INIT_JOB 23
+#define SS_INIT_MAPPING 22
#define SS_INIT_PLANT 21.5
#define SS_INIT_HUMANS 21
#define SS_INIT_MAP 20
#define SS_INIT_COMPONENT 19.5
#define SS_INIT_POWER 19
#define SS_INIT_OBJECT 18
-#define SS_INIT_DECORATOR 17.9
#define SS_INIT_PIPENET 17.5
#define SS_INIT_XENOARCH 17
#define SS_INIT_MORE_INIT 16
#define SS_INIT_AIR 15
-#define SS_INIT_SHUTTLE 14
#define SS_INIT_TELEPORTER 13
#define SS_INIT_LIGHTING 12
-#define SS_INIT_LANDMARK 11
#define SS_INIT_DEFCON 9
#define SS_INIT_LAW 6
#define SS_INIT_FZ_TRANSITIONS 5
#define SS_INIT_ATOMS 4
+#define SS_INIT_DECORATOR 3.7
+#define SS_INIT_SHUTTLE 3.5
+#define SS_INIT_LANDMARK 3.2
#define SS_INIT_MACHINES 3
#define SS_INIT_RADIO 2
-#define SS_INIT_TIMER 1
+#define SS_INIT_TIMER 100
#define SS_INIT_UNSPECIFIED 0
#define SS_INIT_EMERGENCY_SHUTTLE -19
#define SS_INIT_ASSETS -20
diff --git a/code/__DEFINES/turf_flags.dm b/code/__DEFINES/turf_flags.dm
new file mode 100644
index 000000000000..4cf9e4d243b7
--- /dev/null
+++ b/code/__DEFINES/turf_flags.dm
@@ -0,0 +1,6 @@
+#define CHANGETURF_DEFER_CHANGE (1<<0)
+#define CHANGETURF_IGNORE_AIR (1<<1) // This flag prevents changeturf from gathering air from nearby turfs to fill the new turf with an approximation of local air
+#define CHANGETURF_FORCEOP (1<<2)
+#define CHANGETURF_SKIP (1<<3) // A flag for PlaceOnTop to just instance the new turf instead of calling ChangeTurf. Used for uninitialized turfs NOTHING ELSE
+
+#define IS_OPAQUE_TURF(turf) (turf.directional_opacity == ALL_CARDINALS)
diff --git a/code/__HELPERS/level_traits.dm b/code/__HELPERS/level_traits.dm
index 6bd1a7bcc9b2..0e565e46672f 100644
--- a/code/__HELPERS/level_traits.dm
+++ b/code/__HELPERS/level_traits.dm
@@ -1,31 +1,12 @@
-// placeholders
-#define ZTRAIT_GROUND 1
-#define ZTRAIT_ADMIN 2
-#define ZTRAIT_MARINE_MAIN_SHIP 3
-#define ZTRAIT_LOWORBITT 4
-#define ZTRAIT_HUNTER_SHIP 5
-#define is_admin_level(z) (z == ZTRAIT_ADMIN)
+#define is_admin_level(z) SSmapping.level_trait(z, ZTRAIT_ADMIN)
-#define is_ground_level(z) (z == ZTRAIT_GROUND)
+#define is_ground_level(z) SSmapping.level_trait(z, ZTRAIT_GROUND)
-#define is_mainship_level(z) (z == ZTRAIT_MARINE_MAIN_SHIP)
+#define is_mainship_level(z) SSmapping.level_trait(z, ZTRAIT_MARINE_MAIN_SHIP)
-#define is_loworbit_level(z) (z == ZTRAIT_LOWORBITT)
+#define is_loworbit_level(z) SSmapping.level_trait(z, ZTRAIT_LOWORBIT)
-#define is_huntership_level(z) (z == ZTRAIT_HUNTER_SHIP)
-
-// extremely placeholder
-GLOBAL_REAL(SSmapping, /datum/mapping_placeholder) = new
-
-/datum/mapping_placeholder
-
-/datum/mapping_placeholder/proc/levels_by_trait(trait)
- RETURN_TYPE(/list)
- return list(trait)
-
-/datum/mapping_placeholder/proc/levels_by_any_trait(list/traits)
- RETURN_TYPE(/list)
- return traits
+#define is_huntership_level(z) SSmapping.level_trait(z, ZTRAIT_HUNTER_SHIP)
#define OBJECTS_CAN_REACH(Oa, Ob) (!(is_admin_level(Oa.z) || is_admin_level(Ob.z)) || Oa.z == Ob.z)
diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm
index 642d461f91f5..36b4a7a805bb 100644
--- a/code/__HELPERS/lists.dm
+++ b/code/__HELPERS/lists.dm
@@ -570,3 +570,12 @@ proc/listclearnulls(list/list)
right.Cut(1,2)
return result
+
+/proc/typecache_filter_list_reverse(list/atoms, list/typecache)
+ RETURN_TYPE(/list)
+ . = list()
+ for(var/thing in atoms)
+ var/atom/A = thing
+ if(!typecache[A.type])
+ . += A
+
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 3b53e6b3b4f8..d36ecb6be604 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1153,16 +1153,22 @@ var/global/image/action_blue_power_up
//Takes: Area type as text string or as typepath OR an instance of the area.
//Returns: A list of all turfs in areas of that type of that type in the world.
-/proc/get_area_turfs(var/areatype)
- if(!areatype) return null
+/proc/get_area_turfs(areatype)
+ if(!areatype)
+ return
+
+ if(istext(areatype))
+ areatype = text2path(areatype)
+
if(isarea(areatype))
var/area/areatemp = areatype
areatype = areatemp.type
- var/list/turfs = new/list()
- for(var/area/N in all_areas)
- if(istype(N, areatype))
- for(var/turf/T in N) turfs += T
+ var/list/turfs = list()
+ var/area/A = GLOB.areas_by_type[areatype]
+ for(var/turf/T in A)
+ turfs += T
+
return turfs
/datum/coords //Simple datum for storing coordinates.
@@ -1562,7 +1568,7 @@ var/list/WALLITEMS = list(
var/turf/T = get_turf(G)
if(!(T.loc.type in grenade_antigrief_exempt_areas))
var/crash_occured = (SSticker?.mode?.is_in_endgame)
- if(G.harmful && (T.z in SSmapping.levels_by_any_trait(list(ZTRAIT_MARINE_MAIN_SHIP, ZTRAIT_LOWORBITT))) && (security_level < SEC_LEVEL_RED) && !crash_occured && grenade_antigrief_on)
+ if(G.harmful && (T.z in SSmapping.levels_by_any_trait(list(ZTRAIT_MARINE_MAIN_SHIP, ZTRAIT_LOWORBIT))) && (security_level < SEC_LEVEL_RED) && !crash_occured && grenade_antigrief_on)
return TRUE
return FALSE
@@ -1743,3 +1749,25 @@ var/list/WALLITEMS = list(
if(istype(D))
return !QDELETED(D)
return FALSE
+
+//Repopulates sortedAreas list
+/proc/repopulate_sorted_areas()
+ GLOB.sorted_areas = list()
+
+ for(var/area/A in world)
+ GLOB.sorted_areas.Add(A)
+
+ sortTim(GLOB.sorted_areas, /proc/cmp_name_asc)
+
+/atom/proc/GetAllContentsIgnoring(list/ignore_typecache)
+ if(!length(ignore_typecache))
+ return GetAllContents()
+ var/list/processing = list(src)
+ var/list/assembled = list()
+ while(processing.len)
+ var/atom/A = processing[1]
+ processing.Cut(1,2)
+ if(!ignore_typecache[A.type])
+ processing += A.contents
+ assembled += A
+ return assembled
diff --git a/code/_globalvars/global_lists.dm b/code/_globalvars/global_lists.dm
index c5ea676ab808..be8f9aaa9c17 100644
--- a/code/_globalvars/global_lists.dm
+++ b/code/_globalvars/global_lists.dm
@@ -12,10 +12,6 @@ var/list/DEFAULT_NEXT_MAP_CANDIDATES = list(MAP_LV_624, MAP_BIG_RED, MAP_WHISKEY
var/list/LOWPOP_NEXT_MAP_CANDIDATES = list(MAP_LV_624, MAP_BIG_RED, MAP_PRISON_STATION, MAP_KUTJEVO)
var/list/NOTVOTABLE_MAPS = list(MAP_WHISKEY_OUTPOST, MAP_ICE_COLONY)
var/list/NEXT_MAP_CANDIDATES = DEFAULT_NEXT_MAP_CANDIDATES.Copy() - NOTVOTABLE_MAPS
-var/list/MAPS_COLD_TEMP = list(MAP_ICE_COLONY, MAP_SOROKYNE_STRATA, MAP_CORSAT)
-
-//List of player votes. Name of the map from NEXT_MAP_CANDIADATES indexed by ckey
-var/list/player_votes = list()
// Global lists of the HUDs
var/global/list/custom_huds_list = list("midnight" = new /datum/custom_hud(),
diff --git a/code/_globalvars/lists/mapping_globals.dm b/code/_globalvars/lists/mapping_globals.dm
index 8b284b744a9a..70140dfb57eb 100644
--- a/code/_globalvars/lists/mapping_globals.dm
+++ b/code/_globalvars/lists/mapping_globals.dm
@@ -1,3 +1,11 @@
+
+GLOBAL_LIST_EMPTY(sorted_areas)
+/// An association from typepath to area instance. Only includes areas with `unique` set.
+GLOBAL_LIST_EMPTY_TYPED(areas_by_type, /area)
+
+GLOBAL_DATUM(supply_elevator, /turf)
+GLOBAL_DATUM(vehicle_elevator, /turf)
+
GLOBAL_LIST_EMPTY(spawns_by_job)
GLOBAL_LIST_EMPTY(queen_spawns)
GLOBAL_LIST_EMPTY(xeno_spawns)
diff --git a/code/_macros.dm b/code/_macros.dm
index 004a28a15873..e4798583f628 100644
--- a/code/_macros.dm
+++ b/code/_macros.dm
@@ -38,6 +38,7 @@
#define LAZYREMOVE(L, I) if(L) { L -= I; if(!length(L)) { L = null; } }
// Adds I to L, initalizing L if necessary
#define LAZYADD(L, I) if(!L) { L = list(); } L += I;
+#define LAZYOR(L, I) if(!L) { L = list(); } L |= I;
// Insert I into L at position X, initalizing L if necessary
#define LAZYINSERT(L, I, X) if(!L) { L = list(); } L.Insert(X, I);
// Adds I to L, initalizing L if necessary, if I is not already in L
diff --git a/code/controllers/_DynamicAreaLighting_TG.dm b/code/controllers/_DynamicAreaLighting_TG.dm
index 90a861f4eabb..0d5e514707d0 100644
--- a/code/controllers/_DynamicAreaLighting_TG.dm
+++ b/code/controllers/_DynamicAreaLighting_TG.dm
@@ -98,7 +98,7 @@
changed = 0
ls_remove_effect(src)
ls_add_effect(src)
-
+
return 0
/datum/light_source/proc/changed()
@@ -123,19 +123,10 @@
// We may read it, but NEVER set it directly.
var/directional_lum = 0
-//Turfs with opacity when they are constructed will trigger nearby lights to update
-//Turfs and atoms with luminosity when they are constructed will create a light_source automatically
-/turf/New()
- ..()
- if(luminosity)
- if(light) WARNING("[type] - Don't set lights up manually during New(), We do it automatically.")
- trueLuminosity = luminosity * luminosity
- light = new(src)
-
//Movable atoms with opacity when they are constructed will trigger nearby lights to update
//Movable atoms with luminosity when they are constructed will create a light_source automatically
-/atom/movable/New()
- ..()
+/atom/movable/Initialize(mapload, ...)
+ . = ..()
if(opacity)
if(isturf(loc))
if(loc:lighting_lumcount > 1)
@@ -377,4 +368,4 @@
#undef LIGHTING_MAX_LUMINOSITY_MOBILE
#undef LIGHTING_MAX_LUMINOSITY_TURF
#undef DIRECTIONAL_LUM_OFFSET
-#undef DIRECTIONAL_LUM_MULT
\ No newline at end of file
+#undef DIRECTIONAL_LUM_MULT
diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm
index ef17294a7d2d..4b3cb7932d4b 100644
--- a/code/controllers/configuration/configuration.dm
+++ b/code/controllers/configuration/configuration.dm
@@ -47,12 +47,72 @@
for(var/J in legacy_configs)
LoadEntries(J)
break
+ loadmaplist(CONFIG_GROUND_MAPS_FILE, GROUND_MAP)
+ loadmaplist(CONFIG_SHIP_MAPS_FILE, SHIP_MAP)
LoadChatFilter()
if(Master)
Master.OnConfigLoad()
+/datum/controller/configuration/proc/loadmaplist(filename, maptype)
+ log_config("Loading config file [filename]...")
+ filename = "[directory]/[filename]"
+ var/list/Lines = file2list(filename)
+
+ var/datum/map_config/currentmap
+ for(var/t in Lines)
+ if(!t)
+ continue
+
+ t = trim(t)
+ if(length(t) == 0)
+ continue
+ else if(copytext(t, 1, 2) == "#")
+ continue
+
+ var/pos = findtext(t, " ")
+ var/command = null
+ var/data = null
+
+ if(pos)
+ command = lowertext(copytext(t, 1, pos))
+ data = copytext(t, pos + 1)
+ else
+ command = lowertext(t)
+
+ if(!command)
+ continue
+
+ if(!currentmap && command != "map")
+ continue
+
+ switch(command)
+ if("map")
+ currentmap = load_map_config("maps/[data].json")
+ if(currentmap.defaulted)
+ log_config("Failed to load map config for [data]!")
+ currentmap = null
+ if("minplayers", "minplayer")
+ currentmap.config_min_users = text2num(data)
+ if("maxplayers", "maxplayer")
+ currentmap.config_max_users = text2num(data)
+ if("weight", "voteweight")
+ currentmap.voteweight = text2num(data)
+ if("default", "defaultmap")
+ LAZYINITLIST(defaultmaps)
+ defaultmaps[maptype] = currentmap
+ if("endmap")
+ LAZYINITLIST(maplist)
+ LAZYINITLIST(maplist[maptype])
+ maplist[maptype][currentmap.map_name] = currentmap
+ currentmap = null
+ if("disabled")
+ currentmap = null
+ else
+ log_config("Unknown command in map vote config: '[command]'")
+
+
/datum/controller/configuration/proc/full_wipe()
if(IsAdminAdvancedProcCall())
return
diff --git a/code/controllers/shuttle_controller.dm b/code/controllers/shuttle_controller.dm
index 12006556f023..f5b476f5f0a3 100644
--- a/code/controllers/shuttle_controller.dm
+++ b/code/controllers/shuttle_controller.dm
@@ -95,7 +95,7 @@
// START: CORSAT shuttle(s).. i mean monorails, what
// Added by Fourkhan, 5/31/2019 - 6/7/19
- if (map_tag == MAP_CORSAT)
+ if (SSmapping.configs[GROUND_MAP].map_name)
shuttle1 = new
shuttle1.location = 0
shuttle1.warmup_time = SECONDS_10
@@ -383,6 +383,9 @@
shuttles["Transit 2"] = shuttle
process_shuttles += shuttle
+ for(var/obj/structure/machinery/computer/shuttle_control/S in GLOB.shuttle_controls)
+ S.shuttle_datum = shuttles[S.shuttle_tag]
+
//This is called by gameticker after all the machines and radio frequencies have been properly initialized
/datum/controller/shuttle_controller/proc/setup_shuttle_docks()
diff --git a/code/controllers/subsystem/communications.dm b/code/controllers/subsystem/communications.dm
index fc333fe0627d..931282269ed9 100644
--- a/code/controllers/subsystem/communications.dm
+++ b/code/controllers/subsystem/communications.dm
@@ -251,7 +251,7 @@ SUBSYSTEM_DEF(radio)
target_zs += SSmapping.levels_by_trait(ZTRAIT_GROUND)
if(tcomm_machines_almayer.len > 0)
target_zs += SSmapping.levels_by_trait(ZTRAIT_MARINE_MAIN_SHIP)
- target_zs += SSmapping.levels_by_trait(ZTRAIT_LOWORBITT)
+ target_zs += SSmapping.levels_by_trait(ZTRAIT_LOWORBIT)
return target_zs
/datum/controller/subsystem/radio/proc/add_tcomm_machine(var/obj/machine)
diff --git a/code/controllers/subsystem/decorator.dm b/code/controllers/subsystem/decorator.dm
index d01412f5ca82..9c2db22316cf 100644
--- a/code/controllers/subsystem/decorator.dm
+++ b/code/controllers/subsystem/decorator.dm
@@ -1,15 +1,16 @@
// our atom declaration should not be hardcoded for this SS existance.
// if this subsystem is deleted, stuff still works
// That's why we define this here
-/atom/Decorate()
- if(SSdecorator && SSdecorator.registered_decorators[type])
+/atom/proc/Decorate()
+ if(SSdecorator.registered_decorators[type])
SSdecorator.decorate(src)
+ flags_atom |= ATOM_DECORATED
SUBSYSTEM_DEF(decorator)
- name = "Decorator"
- init_order = SS_INIT_DECORATOR
- priority = SS_PRIORITY_DECORATOR
- flags = SS_NO_FIRE
+ name = "Decorator"
+ init_order = SS_INIT_DECORATOR
+ priority = SS_PRIORITY_DECORATOR
+ flags = SS_NO_FIRE
can_fire = FALSE
@@ -37,7 +38,8 @@ SUBSYSTEM_DEF(decorator)
registered_decorators[i] = sortDecorators(registered_decorators[i])
for(var/atom/object in world)
- object.Decorate()
+ if(!(object.flags_atom & ATOM_DECORATED))
+ object.Decorate()
CHECK_TICK
return ..()
diff --git a/code/controllers/subsystem/init/mapview.dm b/code/controllers/subsystem/init/mapview.dm
deleted file mode 100644
index 96826f8b3dfc..000000000000
--- a/code/controllers/subsystem/init/mapview.dm
+++ /dev/null
@@ -1,8 +0,0 @@
-SUBSYSTEM_DEF(mapview_init)
- name = "Mapview Init"
- init_order = SS_INIT_MAPVIEW
- flags = SS_NO_FIRE
-
-/datum/controller/subsystem/mapview_init/Initialize()
- generate_marine_mapview()
- return ..()
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
new file mode 100644
index 000000000000..adc1483b8378
--- /dev/null
+++ b/code/controllers/subsystem/mapping.dm
@@ -0,0 +1,300 @@
+SUBSYSTEM_DEF(mapping)
+ name = "Mapping"
+ init_order = SS_INIT_MAPPING
+ flags = SS_NO_FIRE
+
+ var/list/datum/map_config/configs
+ var/list/datum/map_config/next_map_configs
+
+ var/list/map_templates = list()
+
+ var/list/areas_in_z = list()
+
+ var/list/turf/unused_turfs = list() //Not actually unused turfs they're unused but reserved for use for whatever requests them. "[zlevel_of_turf]" = list(turfs)
+ var/list/datum/turf_reservations //list of turf reservations
+ var/list/used_turfs = list() //list of turf = datum/turf_reservation
+
+ var/list/reservation_ready = list()
+ var/clearing_reserved_turfs = FALSE
+
+ // Z-manager stuff
+ var/ground_start // should only be used for maploading-related tasks
+ var/list/z_list
+ var/datum/space_level/transit
+ var/num_of_res_levels = 1
+
+//dlete dis once #39770 is resolved
+/datum/controller/subsystem/mapping/proc/HACK_LoadMapConfig()
+ if(!configs)
+ configs = load_map_configs(ALL_MAPTYPES, error_if_missing = FALSE)
+ for(var/i in GLOB.clients)
+ var/client/C = i
+ winset(C, null, "mainwindow.title='[CONFIG_GET(string/title)] - [SSmapping.configs[SHIP_MAP].map_name]'")
+
+/datum/controller/subsystem/mapping/Initialize(timeofday)
+ HACK_LoadMapConfig()
+ if(initialized)
+ return
+
+ for(var/i in ALL_MAPTYPES)
+ var/datum/map_config/MC = configs[i]
+ if(MC.defaulted)
+ var/old_config = configs[i]
+ configs[i] = global.config.defaultmaps[i]
+ if(!configs || configs[i].defaulted)
+ to_chat(world, "Unable to load next or default map config, defaulting.")
+ configs[i] = old_config
+
+ if(configs[GROUND_MAP])
+ for(var/i in config.votable_modes)
+ if(!(i in configs[GROUND_MAP].gamemodes))
+ config.votable_modes -= i // remove invalid modes
+
+ loadWorld()
+ repopulate_sorted_areas()
+ preloadTemplates()
+ // Add the transit level
+ transit = add_new_zlevel("Transit/Reserved", list(ZTRAIT_RESERVED = TRUE))
+ initialize_reserved_level(transit.z_value)
+ GLOB.interior_manager = new
+ repopulate_sorted_areas()
+ return ..()
+
+/datum/controller/subsystem/mapping/proc/wipe_reservations(wipe_safety_delay = 100)
+ if(clearing_reserved_turfs || !initialized) //in either case this is just not needed.
+ return
+ clearing_reserved_turfs = TRUE
+ message_admins("Clearing dynamic reservation space.")
+ do_wipe_turf_reservations()
+ clearing_reserved_turfs = FALSE
+
+/datum/controller/subsystem/mapping/Recover()
+ flags |= SS_NO_INIT
+ initialized = SSmapping.initialized
+ map_templates = SSmapping.map_templates
+ unused_turfs = SSmapping.unused_turfs
+ turf_reservations = SSmapping.turf_reservations
+ used_turfs = SSmapping.used_turfs
+
+ configs = SSmapping.configs
+ next_map_configs = SSmapping.next_map_configs
+
+ clearing_reserved_turfs = SSmapping.clearing_reserved_turfs
+
+ z_list = SSmapping.z_list
+
+#define INIT_ANNOUNCE(X) to_chat(world, "[X]"); log_world(X)
+/datum/controller/subsystem/mapping/proc/LoadGroup(list/errorList, name, path, files, list/traits, list/default_traits, silent = FALSE)
+ . = list()
+ var/start_time = REALTIMEOFDAY
+
+ if (!islist(files)) // handle single-level maps
+ files = list(files)
+
+ // check that the total z count of all maps matches the list of traits
+ var/total_z = 0
+ var/list/parsed_maps = list()
+ for (var/file in files)
+ var/full_path = "maps/[path]/[file]"
+ var/datum/parsed_map/pm = new(file(full_path))
+ var/bounds = pm?.bounds
+ if (!bounds)
+ errorList |= full_path
+ continue
+ parsed_maps[pm] = total_z // save the start Z of this file
+ total_z += bounds[MAP_MAXZ] - bounds[MAP_MINZ] + 1
+
+ if (!length(traits)) // null or empty - default
+ for (var/i in 1 to total_z)
+ traits += list(default_traits)
+ else if (total_z != traits.len) // mismatch
+ INIT_ANNOUNCE("WARNING: [traits.len] trait sets specified for [total_z] z-levels in [path]!")
+ if (total_z < traits.len) // ignore extra traits
+ traits.Cut(total_z + 1)
+ while (total_z > traits.len) // fall back to defaults on extra levels
+ traits += list(default_traits)
+
+ // preload the relevant space_level datums
+ var/start_z = world.maxz + 1
+ var/i = 0
+ for (var/level in traits)
+ add_new_zlevel("[name][i ? " [i + 1]" : ""]", level)
+ ++i
+
+ // load the maps
+ for (var/P in parsed_maps)
+ var/datum/parsed_map/pm = P
+ if (!pm.load(1, 1, start_z + parsed_maps[P], no_changeturf = TRUE))
+ errorList |= pm.original_path
+ if(!silent)
+ INIT_ANNOUNCE("Loaded [name] in [(REALTIMEOFDAY - start_time)/10]s!")
+ return parsed_maps
+
+/datum/controller/subsystem/mapping/proc/Loadship(list/errorList, name, path, files, list/traits, list/default_traits, silent = FALSE)
+ LoadGroup(errorList, name, path, files, traits, default_traits, silent)
+
+/datum/controller/subsystem/mapping/proc/Loadground(list/errorList, name, path, files, list/traits, list/default_traits, silent = FALSE)
+ LoadGroup(errorList, name, path, files, traits, default_traits, silent)
+
+/datum/controller/subsystem/mapping/proc/loadWorld()
+ //if any of these fail, something has gone horribly, HORRIBLY, wrong
+ var/list/FailedZs = list()
+
+ // ensure we have space_level datums for compiled-in maps
+ InitializeDefaultZLevels()
+
+ // load the ground level
+ ground_start = world.maxz + 1
+
+ var/datum/map_config/ground_map = configs[GROUND_MAP]
+ INIT_ANNOUNCE("Loading [ground_map.map_name]...")
+ Loadground(FailedZs, ground_map.map_name, ground_map.map_path, ground_map.map_file, ground_map.traits, ZTRAITS_GROUND)
+
+ var/datum/map_config/ship_map = configs[SHIP_MAP]
+ INIT_ANNOUNCE("Loading [ship_map.map_name]...")
+ Loadship(FailedZs, ship_map.map_name, ship_map.map_path, ship_map.map_file, ship_map.traits, ZTRAITS_MAIN_SHIP)
+
+ if(LAZYLEN(FailedZs)) //but seriously, unless the server's filesystem is messed up this will never happen
+ var/msg = "RED ALERT! The following map files failed to load: [FailedZs[1]]"
+ if(FailedZs.len > 1)
+ for(var/I in 2 to FailedZs.len)
+ msg += ", [FailedZs[I]]"
+ msg += ". Yell at your server host!"
+ INIT_ANNOUNCE(msg)
+#undef INIT_ANNOUNCE
+
+/datum/controller/subsystem/mapping/proc/changemap(datum/map_config/VM, maptype = GROUND_MAP)
+ LAZYINITLIST(next_map_configs)
+ if(maptype == GROUND_MAP)
+ if(!VM.MakeNextMap(maptype))
+ next_map_configs[GROUND_MAP] = load_map_configs(list(maptype), default = TRUE)
+ message_admins("Failed to set new map with next_map.json for [VM.map_name]! Using default as backup!")
+ return
+
+ next_map_configs[GROUND_MAP] = VM
+ return TRUE
+
+ else if(maptype == SHIP_MAP)
+ if(!VM.MakeNextMap(maptype))
+ next_map_configs[SHIP_MAP] = load_map_configs(list(maptype), default = TRUE)
+ message_admins("Failed to set new map with next_map.json for [VM.map_name]! Using default as backup!")
+ return
+
+ next_map_configs[SHIP_MAP] = VM
+ return TRUE
+
+/datum/controller/subsystem/mapping/proc/preloadTemplates(path = "maps/templates/") //see master controller setup
+ var/list/filelist = flist(path)
+ for(var/map in filelist)
+ var/datum/map_template/T = new(path = "[path][map]", rename = "[map]")
+ map_templates[T.name] = T
+
+/proc/generateMapList(filename)
+ . = list()
+ var/list/Lines = file2list(filename)
+
+ if(!Lines.len)
+ return
+ for (var/t in Lines)
+ if (!t)
+ continue
+
+ t = trim(t)
+ if (length(t) == 0)
+ continue
+ else if (t[1] == "#")
+ continue
+
+ var/pos = findtext(t, " ")
+ var/name = null
+
+ if (pos)
+ name = lowertext(copytext(t, 1, pos))
+
+ else
+ name = lowertext(t)
+
+ if (!name)
+ continue
+
+ . += t
+
+/datum/controller/subsystem/mapping/proc/RequestBlockReservation(width, height, z, type = /datum/turf_reservation, turf_type_override)
+ UNTIL(initialized && !clearing_reserved_turfs)
+ var/datum/turf_reservation/reserve = new type
+ if(turf_type_override)
+ reserve.turf_type = turf_type_override
+ if(!z)
+ for(var/i in levels_by_trait(ZTRAIT_RESERVED))
+ if(reserve.Reserve(width, height, i))
+ return reserve
+ //If we didn't return at this point, theres a good chance we ran out of room on the exisiting reserved z levels, so lets try a new one
+ log_debug("Ran out of space in existing transit levels, adding a new one")
+ num_of_res_levels += 1
+ var/datum/space_level/newReserved = add_new_zlevel("Transit/Reserved [num_of_res_levels]", list(ZTRAIT_RESERVED = TRUE))
+ initialize_reserved_level(newReserved.z_value)
+ for(var/i in levels_by_trait(ZTRAIT_RESERVED))
+ if(reserve.Reserve(width, height, i))
+ return reserve
+ CRASH("Despite adding a fresh reserved zlevel still failed to get a reservation")
+ else
+ if(!level_trait(z, ZTRAIT_RESERVED))
+ log_debug("Cannot block reserve on a non-ZTRAIT_RESERVED level")
+ qdel(reserve)
+ return
+ else
+ if(reserve.Reserve(width, height, z))
+ return reserve
+ log_debug("unknown reservation failure")
+ QDEL_NULL(reserve)
+
+//This is not for wiping reserved levels, use wipe_reservations() for that.
+/datum/controller/subsystem/mapping/proc/initialize_reserved_level(z)
+ UNTIL(!clearing_reserved_turfs) //regardless, lets add a check just in case.
+ clearing_reserved_turfs = TRUE //This operation will likely clear any existing reservations, so lets make sure nothing tries to make one while we're doing it.
+ if(!level_trait(z,ZTRAIT_RESERVED))
+ clearing_reserved_turfs = FALSE
+ CRASH("Invalid z level prepared for reservations.")
+ var/turf/A = get_turf(locate(8,8,z))
+ var/turf/B = get_turf(locate(world.maxx - 8,world.maxy - 8,z))
+ var/block = block(A, B)
+ for(var/t in block)
+ // No need to empty() these, because it's world init and they're
+ // already /turf/open/space/basic.
+ var/turf/T = t
+ T.flags_atom |= UNUSED_RESERVATION_TURF_1
+ unused_turfs["[z]"] = block
+ reservation_ready["[z]"] = TRUE
+ clearing_reserved_turfs = FALSE
+
+/datum/controller/subsystem/mapping/proc/reserve_turfs(list/turfs)
+ for(var/i in turfs)
+ var/turf/T = i
+ T.empty(RESERVED_TURF_TYPE, RESERVED_TURF_TYPE, null, TRUE)
+ LAZYINITLIST(unused_turfs["[T.z]"])
+ unused_turfs["[T.z]"] |= T
+ T.flags_atom |= UNUSED_RESERVATION_TURF_1
+ GLOB.areas_by_type[world.area].contents += T
+ CHECK_TICK
+
+//DO NOT CALL THIS PROC DIRECTLY, CALL wipe_reservations().
+/datum/controller/subsystem/mapping/proc/do_wipe_turf_reservations()
+ UNTIL(initialized) //This proc is for AFTER init, before init turf reservations won't even exist and using this will likely break things.
+ for(var/i in turf_reservations)
+ var/datum/turf_reservation/TR = i
+ if(!QDELETED(TR))
+ qdel(TR, TRUE)
+ UNSETEMPTY(turf_reservations)
+ var/list/clearing = list()
+ for(var/l in unused_turfs) //unused_turfs is a assoc list by z = list(turfs)
+ if(islist(unused_turfs[l]))
+ clearing |= unused_turfs[l]
+ clearing |= used_turfs //used turfs is an associative list, BUT, reserve_turfs() can still handle it. If the code above works properly, this won't even be needed as the turfs would be freed already.
+ unused_turfs.Cut()
+ used_turfs.Cut()
+ reserve_turfs(clearing)
+
+/datum/controller/subsystem/mapping/proc/reg_in_areas_in_z(list/areas)
+ for(var/B in areas)
+ var/area/A = B
+ A.reg_in_areas_in_z()
diff --git a/code/controllers/subsystem/mapview.dm b/code/controllers/subsystem/mapview.dm
index ae1dce8ac2ec..8df92dace162 100644
--- a/code/controllers/subsystem/mapview.dm
+++ b/code/controllers/subsystem/mapview.dm
@@ -4,9 +4,11 @@ SUBSYSTEM_DEF(mapview)
wait = 2 SECONDS
flags = SS_KEEP_TIMING | SS_DISABLE_FOR_TESTING
priority = SS_PRIORITY_MAPVIEW
+ init_order = SS_INIT_MAPVIEW
var/list/map_machines
/datum/controller/subsystem/mapview/Initialize(start_timeofday)
+ generate_marine_mapview()
create_map_machines()
return ..()
diff --git a/code/controllers/subsystem/objectives_controller.dm b/code/controllers/subsystem/objectives_controller.dm
index aaae719e9ec1..d46ecd6d1538 100644
--- a/code/controllers/subsystem/objectives_controller.dm
+++ b/code/controllers/subsystem/objectives_controller.dm
@@ -57,11 +57,10 @@ SUBSYSTEM_DEF(objectives)
var/vial_boxes = 20
//A stub of tweaking item spawns based on map
- switch(map_tag)
- if(MAP_CORSAT)
- vial_boxes = 30
- research_papers = 30
- experimental_devices = 20
+ if(SSmapping.configs[GROUND_MAP].map_name == MAP_CORSAT)
+ vial_boxes = 30
+ research_papers = 30
+ experimental_devices = 20
//Calculating document ratios so we don't end up with filing cabinets holding 10 documents because there are few filing cabinets
var/relative_document_ratio_close = objective_spawn_close_documents.len / objective_spawn_close.len
@@ -111,15 +110,16 @@ SUBSYSTEM_DEF(objectives)
var/obj/effect/landmark/corpsespawner/spawnpoint
for(var/i = 0 to corpses)
- spawnpoint = pick(objective_spawn_corpse)
+ spawnpoint = pick_n_take(objective_spawn_corpse)
//Creates a mob and checks for gear in each slot before attempting to equip it.
var/mob/living/carbon/human/M = new /mob/living/carbon/human(spawnpoint.loc)
M.create_hud() //Need to generate hud before we can equip anything apparently...
arm_equipment(M, "Corpse - [spawnpoint.name]", TRUE, FALSE)
- LAZYREMOVE(objective_spawn_corpse, spawnpoint)
qdel(spawnpoint)
+ if(!length(objective_spawn_corpse))
+ break
for(var/obj/effect/landmark/corpsespawner/C in objective_spawn_corpse)
qdel(C)
diff --git a/code/controllers/subsystem/perf_logging.dm b/code/controllers/subsystem/perf_logging.dm
index 86935c20c28f..ed49172dc671 100644
--- a/code/controllers/subsystem/perf_logging.dm
+++ b/code/controllers/subsystem/perf_logging.dm
@@ -23,7 +23,7 @@ SUBSYSTEM_DEF(perf_logging)
while(!SSentity_manager.ready)
stoplag()
round = SSentity_manager.select(/datum/entity/mc_round)
- round.map_name = "[map_tag]"
+ round.map_name = SSmapping.configs[GROUND_MAP].map_name
round.save()
round.sync()
if(!Master)
diff --git a/code/controllers/subsystem/sound.dm b/code/controllers/subsystem/sound.dm
index 7f03654b6018..17a7650597fb 100644
--- a/code/controllers/subsystem/sound.dm
+++ b/code/controllers/subsystem/sound.dm
@@ -6,7 +6,7 @@ SUBSYSTEM_DEF(sound)
runlevels = RUNLEVELS_DEFAULT|RUNLEVEL_LOBBY
var/list/template_queue = list() // Full Template Queue
- var/list/run_queue = list() // Queue subset being processed during this tick
+ var/list/run_queue = list() // Queue subset being processed during this tick
var/list/run_hearers = null // Hearers for currently being processed template
/datum/controller/subsystem/sound/fire(resumed = FALSE)
@@ -36,10 +36,10 @@ SUBSYSTEM_DEF(sound)
/datum/controller/subsystem/sound/proc/queue(datum/sound_template/template, var/list/client/hearers, list/datum/interior/extra_interiors)
if(!hearers)
hearers = list()
- if(extra_interiors && interior_manager)
+ if(extra_interiors && GLOB.interior_manager)
for(var/datum/interior/VI in extra_interiors)
if(VI?.ready && VI?.chunk_id)
- var/list/bounds = interior_manager.get_chunk_coords(VI.chunk_id)
+ var/list/bounds = GLOB.interior_manager.get_chunk_coords(VI.chunk_id)
if(bounds.len >= 2)
- hearers |= SSquadtree.players_in_range(RECT(bounds[1], bounds[2], interior_manager.chunk_size, interior_manager.chunk_size), interior_manager.interior_z)
- template_queue[template] = hearers
\ No newline at end of file
+ hearers |= SSquadtree.players_in_range(RECT(bounds[1], bounds[2], GLOB.interior_manager.chunk_size, GLOB.interior_manager.chunk_size), GLOB.interior_manager.interior_z)
+ template_queue[template] = hearers
diff --git a/code/controllers/subsystem/statpanel.dm b/code/controllers/subsystem/statpanel.dm
index 257c06bc718d..b806a4b2c503 100644
--- a/code/controllers/subsystem/statpanel.dm
+++ b/code/controllers/subsystem/statpanel.dm
@@ -11,11 +11,13 @@ SUBSYSTEM_DEF(statpanels)
/datum/controller/subsystem/statpanels/fire(resumed = FALSE)
if (!resumed)
-// var/datum/map_config/cached = SSmapping.next_map_config
+ var/datum/map_config/cached
+ if(SSmapping.next_map_configs)
+ cached = SSmapping.next_map_configs[GROUND_MAP]
// var/round_time = world.time - SSticker.round_start_time
var/list/global_data = list(
-// "Map: [SSmapping.config?.map_name || "Loading..."]",
-// cached ? "Next Map: [cached.map_name]" : null,
+ "Map: [SSmapping.configs[GROUND_MAP]?.map_name || "Loading..."]",
+ cached ? "Next Map: [cached?.map_name]" : null,
// "Round ID: [GLOB.round_id ? GLOB.round_id : "NULL"]",
"Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]",
"Round Time: [duration2text()]",
diff --git a/code/controllers/subsystem/teleporter.dm b/code/controllers/subsystem/teleporter.dm
index 40a87862a257..858c2c7494f1 100644
--- a/code/controllers/subsystem/teleporter.dm
+++ b/code/controllers/subsystem/teleporter.dm
@@ -13,7 +13,7 @@ SUBSYSTEM_DEF(teleporter)
//Corsat_Teleporter
/datum/controller/subsystem/teleporter/Initialize()
- if (map_tag != MAP_CORSAT) // Bad style, but I'm leaving it here for now until someone wants to add a teleporter to another map
+ if (SSmapping.configs[GROUND_MAP].map_name != MAP_CORSAT) // Bad style, but I'm leaving it here for now until someone wants to add a teleporter to another map
return
teleporters_by_id = list()
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index 91ccf73bbdb6..9b221e9b04ee 100644
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -110,6 +110,7 @@ SUBSYSTEM_DEF(ticker)
current_state = GAME_STATE_FINISHED
ooc_allowed = TRUE
mode.declare_completion(force_ending)
+ addtimer(CALLBACK(SSvote, /datum/controller/subsystem/vote.proc/initiate_vote, "groundmap", "SERVER"), 3 SECONDS)
addtimer(CALLBACK(src, .proc/Reboot), 63 SECONDS)
Master.SetRunLevel(RUNLEVEL_POSTGAME)
@@ -173,7 +174,6 @@ SUBSYSTEM_DEF(ticker)
for(var/mob/new_player/np in GLOB.new_player_list)
np.new_player_panel_proc(TRUE)
- run_mapdaemon_batch()
begin_game_recording()
if((master_mode == "Distress Signal") && SSevents)
diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm
index dab9bd739d0f..4d836661c484 100644
--- a/code/controllers/subsystem/vote.dm
+++ b/code/controllers/subsystem/vote.dm
@@ -1,10 +1,411 @@
SUBSYSTEM_DEF(vote)
- name = "Vote"
- flags = SS_NO_INIT
- wait = 1 SECONDS
- priority = SS_PRIORITY_VOTE
- flags = SS_KEEP_TIMING | SS_DISABLE_FOR_TESTING
- runlevels = RUNLEVELS_DEFAULT|RUNLEVEL_LOBBY
-
-/datum/controller/subsystem/vote/fire(resumed = FALSE)
- vote.process()
+ name = "Vote"
+ wait = 10
+
+ flags = SS_KEEP_TIMING|SS_NO_INIT
+
+ runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
+
+ var/initiator = null
+ var/started_time = null
+ var/time_remaining = 0
+ var/mode = null
+ var/question = null
+ var/list/choices = list()
+ var/list/voted = list()
+ var/list/voting = list()
+
+ // mapvotes carryover
+ var/list/datum/entity/map_vote/votes
+
+/datum/controller/subsystem/vote/fire()
+ if(mode)
+ time_remaining = round((started_time + CONFIG_GET(number/vote_period) - world.time)/10)
+
+ if(time_remaining < 0)
+ result()
+ for(var/client/C in voting)
+ C << browse(null, "window=vote")
+ reset()
+ else
+ var/datum/browser/client_popup
+ for(var/client/C in voting)
+ client_popup = new(C, "vote", "Voting Panel")
+ client_popup.set_window_options("can_close=0")
+ client_popup.set_content(interface(C))
+ client_popup.open(FALSE)
+
+
+/datum/controller/subsystem/vote/proc/reset()
+ initiator = null
+ time_remaining = 0
+ mode = null
+ question = null
+ choices.Cut()
+ voted.Cut()
+ voting.Cut()
+ remove_action_buttons()
+
+
+/datum/controller/subsystem/vote/proc/get_result()
+ var/greatest_votes = 0
+ var/total_votes = 0
+ for(var/option in choices)
+ var/votes = choices[option]
+ total_votes += votes
+ if(votes > greatest_votes)
+ greatest_votes = votes
+ if(!CONFIG_GET(flag/default_no_vote) && length(choices))
+ var/list/non_voters = GLOB.directory.Copy()
+ non_voters -= voted
+ for (var/non_voter_ckey in non_voters)
+ var/client/C = non_voters[non_voter_ckey]
+ if(!C || C.is_afk())
+ non_voters -= non_voter_ckey
+ if(length(non_voters) > 0)
+ if(mode == "restart")
+ choices["Continue Playing"] += length(non_voters)
+ if(choices["Continue Playing"] >= greatest_votes)
+ greatest_votes = choices["Continue Playing"]
+ . = list()
+ if(greatest_votes)
+ for(var/option in choices)
+ if(choices[option] == greatest_votes)
+ . += option
+ return .
+
+
+/datum/controller/subsystem/vote/proc/announce_result()
+ var/list/winners = get_result()
+ var/text
+ if(length(winners) > 0)
+ if(question)
+ text += "[question]"
+ else
+ text += "[capitalize(mode)] Vote"
+ for(var/i = 1 to length(choices))
+ var/votes = choices[choices[i]]
+ if(!votes)
+ votes = 0
+ text += "
[choices[i]]: [votes]"
+ if(mode != "custom")
+ if(length(winners) > 1)
+ text = "
Vote Tied Between:"
+ for(var/option in winners)
+ text += "
[FOURSPACES][option]"
+ . = pick(winners)
+ text += "
Vote Result: [.]"
+ else
+ text += "
Did not vote: [length(GLOB.clients) - length(voted)]"
+ else
+ text += "Vote Result: Inconclusive - No Votes!"
+ log_vote(text)
+ remove_action_buttons()
+ to_chat(world, "
[text]")
+ return .
+
+
+/datum/controller/subsystem/vote/proc/result()
+ . = announce_result()
+ var/restart = FALSE
+ if(.)
+ switch(mode)
+ if("restart")
+ if(. == "Restart Round")
+ restart = TRUE
+ if("groundmap")
+ var/datum/map_config/VM = config.maplist[GROUND_MAP][.]
+ SSmapping.changemap(VM, GROUND_MAP)
+ for(var/datum/entity/map_vote/in_vote in votes)
+ if(!isnull(choices[in_vote.map_name]))
+ in_vote.total_votes = (. == in_vote.map_name) ? 0 : choices[in_vote.map_name]
+ in_vote.save()
+ if("shipmap")
+ var/datum/map_config/VM = config.maplist[SHIP_MAP][.]
+ SSmapping.changemap(VM, SHIP_MAP)
+ if(restart)
+ var/active_admins = 0
+ for(var/client/C in GLOB.admins)
+ if(!C.is_afk() && check_rights(R_SERVER))
+ active_admins = TRUE
+ break
+ if(!active_admins)
+ world.Reboot("Restart vote successful.")
+ else
+ to_chat(world, "Notice:Restart vote will not restart the server automatically because there are active admins on.")
+ message_admins("A restart vote has passed, but there are active admins on with +SERVER, so it has been canceled. If you wish, you may restart the server.")
+
+ return .
+
+
+/datum/controller/subsystem/vote/proc/submit_vote(vote)
+ if(mode)
+ if(CONFIG_GET(flag/no_dead_vote) && usr.stat == DEAD && !check_rights(R_ADMIN))
+ return FALSE
+ if(!(usr.ckey in voted))
+ if(vote && 1 <= vote && vote <= length(choices))
+ voted += usr.ckey
+ choices[choices[vote]]++
+ return vote
+ return FALSE
+
+
+/datum/controller/subsystem/vote/proc/carry_over_callback(list/datum/entity/map_vote/votes)
+ src.votes = votes
+ for(var/i in choices)
+ var/found = FALSE
+ var/datum/entity/map_vote/vote
+ for(var/datum/entity/map_vote/in_vote in votes)
+ if(in_vote.map_name == i)
+ found = TRUE
+ vote = in_vote
+ break
+
+ if(!found)
+ vote = SSentity_manager.select(/datum/entity/map_vote)
+ vote.map_name = i
+ vote.total_votes = 0
+ vote.save()
+
+ choices[i] += vote.total_votes
+
+/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key)
+ if(!mode)
+ if(started_time)
+ var/next_allowed_time = (started_time + CONFIG_GET(number/vote_delay))
+ if(mode)
+ to_chat(usr, "There is already a vote in progress! please wait for it to finish.")
+ return FALSE
+
+ var/admin = FALSE
+ var/ckey = ckey(initiator_key)
+ if(initiator_key == "SERVER")
+ admin = TRUE
+ else
+ for(var/i in GLOB.admins)
+ var/client/C = i
+ if(C.ckey == ckey)
+ admin = TRUE
+ break
+
+ if(next_allowed_time > world.time && !admin)
+ to_chat(usr, "A vote was initiated recently, you must wait [DisplayTimeText(next_allowed_time-world.time)] before a new vote can be started!")
+ return FALSE
+
+ reset()
+ switch(vote_type)
+ if("restart")
+ choices.Add("Restart Round", "Continue Playing")
+ if("gamemode")
+ choices.Add(config.votable_modes)
+ if("groundmap")
+ var/list/maps = list()
+ for(var/i in config.maplist[GROUND_MAP])
+ var/datum/map_config/VM = config.maplist[GROUND_MAP][i]
+ if(VM.map_file == SSmapping.configs[GROUND_MAP].map_file)
+ continue
+ if(!VM.voteweight)
+ continue
+ if(VM.config_max_users || VM.config_min_users)
+ var/players = length(GLOB.clients)
+ if(VM.config_max_users && players > VM.config_max_users)
+ continue
+ if(VM.config_min_users && players < VM.config_min_users)
+ continue
+ maps += i
+
+ choices.Add(maps)
+ if(length(choices) < 2)
+ return FALSE
+ SSentity_manager.filter_then(/datum/entity/map_vote, null, CALLBACK(src, .proc/carry_over_callback))
+ if("shipmap")
+ var/list/maps = list()
+ for(var/i in config.maplist[SHIP_MAP])
+ var/datum/map_config/VM = config.maplist[SHIP_MAP][i]
+ if(!VM.voteweight)
+ continue
+ if(VM.config_max_users || VM.config_min_users)
+ var/players = length(GLOB.clients)
+ if(players > VM.config_max_users)
+ continue
+ if(players < VM.config_min_users)
+ continue
+ maps += i
+ choices.Add(maps)
+ if(length(choices) < 2)
+ return FALSE
+ if("custom")
+ question = stripped_input(usr, "What is the vote for?")
+ if(!question)
+ return FALSE
+ for(var/i = 1 to 10)
+ var/option = capitalize(stripped_input(usr, "Please enter an option or hit cancel to finish"))
+ if(!option || mode || !usr.client)
+ break
+ choices.Add(option)
+ else
+ return FALSE
+ mode = vote_type
+ initiator = initiator_key
+ started_time = world.time
+ var/text = "[capitalize(mode)] vote started by [initiator]."
+ if(mode == "custom")
+ text += "
[question]"
+ log_vote(text)
+ var/vp = CONFIG_GET(number/vote_period)
+ //SEND_SOUND(world, sound('sound/ambience/alarm4.ogg', channel = CHANNEL_NOTIFY))
+ to_chat(world, "
[text]
Type vote or click here to place your votes.
You have [DisplayTimeText(vp)] to vote.")
+ time_remaining = round(vp/10)
+ for(var/c in GLOB.clients)
+ var/client/C = c
+ var/datum/action/innate/vote/V = new
+ if(question)
+ V.name = "Vote: [question]"
+ C.player_details.player_actions += V
+ V.give_action(C.mob)
+ return TRUE
+ return FALSE
+
+
+/datum/controller/subsystem/vote/proc/interface(client/C)
+ if(!C)
+ return
+ var/admin = FALSE
+ if(check_rights(R_ADMIN))
+ admin = TRUE
+ voting |= C
+
+ if(mode)
+ if(question)
+ . += "
Vote: '[question]'
"
+ else
+ . += "Vote: [capitalize(mode)]
"
+ . += "Time Left: [time_remaining] s
"
+ for(var/i = 1 to length(choices))
+ var/votes = choices[choices[i]]
+ if(!votes)
+ votes = 0
+ . += "- [choices[i]] ([votes] votes)
"
+ . += "
"
+ if(admin)
+ . += "(Cancel Vote) "
+ else
+ . += "Start a vote:
"
+ . += "Close"
+ return .
+
+
+///datum/controller/subsystem/vote/can_interact(mob/user) // can_interact refactor TODO:
+// return TRUE
+
+
+/datum/controller/subsystem/vote/Topic(href, list/href_list, hsrc)
+ . = ..()
+ if(.)
+ return
+
+ if(!usr?.client)
+ return
+
+ switch(href_list["vote"])
+ if("close")
+ voting -= usr.client
+ DIRECT_OUTPUT(usr, browse(null, "window=vote"))
+ return
+ if("cancel")
+ if(check_rights(R_ADMIN) && alert(usr, "Are you sure you want to cancel the vote?", "Cancel Vote", "Yes", "No") == "Yes")
+ reset()
+ to_chat(world, "The vote has been cancelled.")
+ if("toggle_restart")
+ if(check_rights(R_ADMIN))
+ CONFIG_SET(flag/allow_vote_restart, !CONFIG_GET(flag/allow_vote_restart))
+ if("toggle_gamemode")
+ if(check_rights(R_ADMIN))
+ CONFIG_SET(flag/allow_vote_mode, !CONFIG_GET(flag/allow_vote_mode))
+ if("restart")
+ if(CONFIG_GET(flag/allow_vote_restart) || check_rights(R_ADMIN))
+ initiate_vote("restart", usr.key)
+ if("gamemode")
+ if(CONFIG_GET(flag/allow_vote_mode) || check_rights(R_ADMIN))
+ initiate_vote("gamemode", usr.key)
+ if("custom")
+ if(check_rights(R_ADMIN))
+ initiate_vote("custom", usr.key)
+ if("groundmap")
+ if(check_rights(R_ADMIN))
+ initiate_vote("groundmap", usr.key)
+ if("shipmap")
+ if(check_rights(R_ADMIN))
+ initiate_vote("shipmap", usr.key)
+ else
+ submit_vote(round(text2num(href_list["vote"])))
+ usr.vote()
+
+
+/mob/verb/vote()
+ set category = "OOC"
+ set name = "Vote"
+
+ var/datum/browser/popup = new(src, "vote", "Voting Panel")
+ popup.set_window_options("can_close=0")
+ popup.set_content(SSvote.interface(client))
+ popup.open(FALSE)
+
+/datum/controller/subsystem/vote/proc/remove_action_buttons()
+ SEND_GLOBAL_SIGNAL(COMSIG_GLOB_REMOVE_VOTE_BUTTON)
+
+/datum/action/innate/vote
+ name = "Vote!"
+ action_icon_state = "vote"
+
+/datum/action/innate/vote/give_action(mob/M)
+ . = ..()
+ RegisterSignal(SSdcs, COMSIG_GLOB_REMOVE_VOTE_BUTTON, .proc/remove_vote_action)
+
+/datum/action/innate/vote/proc/remove_vote_action(datum/source)
+ SIGNAL_HANDLER
+
+ if(remove_from_client())
+ remove_action(owner)
+ qdel(src)
+
+/datum/action/innate/vote/action_activate()
+ owner.vote()
+ remove_vote_action()
+
+/datum/action/innate/vote/proc/remove_from_client()
+ if(!owner)
+ return FALSE
+ if(owner.client)
+ owner.client.player_details.player_actions -= src
+ else if(owner.ckey)
+ var/datum/player_details/P = GLOB.player_details[owner.ckey]
+ if(P)
+ P.player_actions -= src
+ return TRUE
diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/weather.dm
index 5230d28ab65f..e5bdf22d3dfe 100644
--- a/code/controllers/subsystem/weather.dm
+++ b/code/controllers/subsystem/weather.dm
@@ -34,9 +34,9 @@ SUBSYSTEM_DEF(weather)
// Set up our map delegate datum for supported maps
// The ONLY place where things should depend on map_tag
// in the weather subsystem
- switch(map_tag)
- if (MAP_SOROKYNE_STRATA)
- map_holder = new /datum/weather_ss_map_holder/sorokyne()
+ if(SSmapping.configs[GROUND_MAP].weather_holder)
+ var/weathertype = SSmapping.configs[GROUND_MAP].weather_holder
+ map_holder = new weathertype
// Disable the weather subsystem on maps that don't currently implement it
if (!map_holder)
diff --git a/code/controllers/voting.dm b/code/controllers/voting.dm
deleted file mode 100644
index 9b9de5d54f69..000000000000
--- a/code/controllers/voting.dm
+++ /dev/null
@@ -1,468 +0,0 @@
-var/datum/controller/vote/vote = new()
-
-datum/controller/vote
- var/initiator = null
- var/started_time = null
- var/time_remaining = 0
- var/mode = null
- var/question = null
- var/list/choices = list()
- var/list/voted = list()
- var/list/voting = list()
- var/list/current_votes = list()
- var/list/additional_text = list()
- var/auto_muted = 0
-
- New()
- if(vote != src)
- if(istype(vote))
- qdel(vote)
- vote = src
-
- process() //called by master_controller
- if(mode)
- // No more change mode votes after the game has started.
- // 3 is GAME_STATE_PLAYING, but that #define is undefined for some reason
- if(mode == "gamemode" && SSticker.current_state >= GAME_STATE_SETTING_UP)
- to_world("Voting aborted due to game start.")
- src.reset()
- return
-
- // Calculate how much time is remaining by comparing current time, to time of vote start,
- // plus vote duration
- time_remaining = round((started_time + CONFIG_GET(number/vote_period) - world.time)/10)
-
- if(time_remaining < 0)
- result()
- for(var/client/C in voting)
- if(C)
- close_browser(C,"vote")
- reset()
- else
- for(var/client/C in voting)
- if(C)
- show_browser(C, vote.interface(C), "Vote", "vote", "can_close=0")
-
- voting.Cut()
-
- proc/autogamemode()
- initiate_vote("gamemode","the server")
- log_debug("The server has called a gamemode vote")
-
- proc/reset()
- initiator = null
- time_remaining = 0
- mode = null
- question = null
- choices.Cut()
- voted.Cut()
- voting.Cut()
- current_votes.Cut()
- additional_text.Cut()
-
- /* if(auto_muted && !ooc_allowed)
- auto_muted = 0
- ooc_allowed = !( ooc_allowed )
- to_world("The OOC channel has been automatically enabled due to vote end.")
- log_admin("OOC was toggled automatically due to vote end.")
- message_admins("OOC has been toggled on automatically.")
- */
-
- proc/get_result()
- //get the highest number of votes
- var/greatest_votes = 0
- var/total_votes = 0
- for(var/option in choices)
- var/votes = choices[option]
- total_votes += votes
- if(votes > greatest_votes)
- greatest_votes = votes
- //default-vote for everyone who didn't vote
- if(!CONFIG_GET(flag/vote_no_default) && choices.len)
- var/non_voters = (GLOB.clients.len - total_votes)
- if(non_voters > 0)
- if(mode == "restart")
- choices["Continue Playing"] += non_voters
- if(choices["Continue Playing"] >= greatest_votes)
- greatest_votes = choices["Continue Playing"]
- else if(mode == "gamemode")
- if(choices[master_mode])
- choices[master_mode] += non_voters
- if(choices[master_mode] >= greatest_votes)
- greatest_votes = choices[master_mode]
-
-
- //get all options with that many votes and return them in a list
- . = list()
- if(greatest_votes)
- for(var/option in choices)
- if(choices[option] == greatest_votes)
- . += option
- return .
-
- proc/announce_result()
- var/list/winners = get_result()
- var/text
- if(winners.len > 0)
- if(winners.len > 1)
- if(mode != "gamemode") // Here we are making sure we don't announce potential game modes
- text = "Vote Tied Between:\n"
- for(var/option in winners)
- text += "\t[option]\n"
- . = pick(winners)
-
- if((mode == "gamemode" && . == "extended")) // Announce Extended gamemode, but not other gamemodes
- text += "Vote Result: [.]"
- else
- if(mode != "gamemode")
- text += "Vote Result: [.]"
- else
- text += "The vote has ended." // What will be shown if it is a gamemode vote that isn't extended
-
- else
- text += "Vote Result: Inconclusive - No Votes!"
- log_vote(text)
- to_world("[text]")
- return .
-
- proc/result()
- . = announce_result()
- var/restart = 0
- if(.)
- switch(mode)
- if("restart")
- if(. == "Restart Round")
- restart = 1
- if("gamemode")
- if(master_mode != .)
- world.save_mode(.)
- if(SSticker && SSticker.mode)
- restart = 1
- else
- master_mode = .
-
- if(mode == "gamemode") //fire this even if the vote fails.
- if(!going)
- going = 1
- to_world("The round will start soon.")
-
- if(restart)
- to_world("World restarting due to vote...")
- sleep(50)
- log_game("Rebooting due to restart vote")
- world.Reboot()
-
- return .
-
- proc/submit_vote(var/ckey, var/vote)
- if(mode)
- if(CONFIG_GET(flag/vote_no_dead) && usr.stat == DEAD && (!usr.client.admin_holder || !(usr.client.admin_holder.rights & R_MOD)))
- return 0
- if(current_votes[ckey])
- choices[choices[current_votes[ckey]]]--
- if(vote && 1<=vote && vote<=choices.len)
- voted += usr.ckey
- choices[choices[vote]]++ //check this
- current_votes[ckey] = vote
- return vote
- return 0
-
- proc/initiate_vote(var/vote_type, var/initiator_key)
- if(!mode)
- if(started_time != null && !check_rights(R_ADMIN))
- var/next_allowed_time = (started_time + CONFIG_GET(number/vote_delay))
- if(next_allowed_time > world.time)
- return 0
-
- reset()
- switch(vote_type)
- if("restart")
- choices.Add("Restart Round","Continue Playing")
- if("gamemode")
- if(SSticker.current_state == GAME_STATE_SETTING_UP)
- return 0
- choices.Add(config.votable_modes)
- var/list/L = typesof(/datum/game_mode) - /datum/game_mode
- for (var/F in choices)
- for (var/T in L)
- var/datum/game_mode/M = new T()
- if (M.config_tag == F)
- additional_text.Add("[M.required_players] | ")
- break
- if("custom")
- question = stripped_input(usr,"What is the vote for?")
- if(!question) return 0
- for(var/i=1,i<=10,i++)
- var/option = capitalize(stripped_input(usr,"Please enter an option or hit cancel to finish"))
- if(!option || mode || !usr.client) break
- choices.Add(option)
- else return 0
- mode = vote_type
- initiator = initiator_key
- started_time = world.time
- var/text = "[capitalize(mode)] vote started by [initiator]."
- if(mode == "custom")
- text += "\n[question]"
-
- log_vote(text)
- to_world("[text]\nType vote to place your votes.\nYou have [CONFIG_GET(number/vote_period)/10] seconds to vote.")
- switch(vote_type)
- if("gamemode")
- world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 1)
- if("custom")
- world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 1)
- if(mode == "gamemode" && going)
- going = 0
- to_world("Round start has been delayed.")
-
-
-
- time_remaining = round(CONFIG_GET(number/vote_period)/10)
- return 1
- return 0
-
- proc/interface(var/client/C)
- if(!C) return
- var/admin = 0
- var/trialmin = 0
- if(C.admin_holder)
- if(C.admin_holder.rights & R_ADMIN)
- admin = 1
- trialmin = 1 // don't know why we use both of these it's really weird, but I'm 2 lasy to refactor this all to use just admin.
- voting |= C
-
- . = "Voting Panel"
- if(mode)
- if(question) . += "Vote: '[question]'
"
- else . += "Vote: [capitalize(mode)]
"
- . += "Time Left: [time_remaining] s
"
- . += "Choices | Votes | "
- if(capitalize(mode) == "Gamemode") .+= "Minimum Players |
"
-
- for(var/i = 1, i <= choices.len, i++)
- var/votes = choices[choices[i]]
- if(!votes) votes = 0
- . += ""
- if(current_votes[C.ckey] == i)
- . += "[choices[i]] | [votes] | "
- else
- . += "[choices[i]] | [votes] | "
-
- if (additional_text.len >= i)
- . += additional_text[i]
- . += "
"
-
- . += "
"
- if(admin)
- . += "(Cancel Vote) "
- else
- . += "Start a vote:
"
- . += "Close"
- return .
-
-
- Topic(href,href_list[],hsrc)
- if(!usr || !usr.client) return //not necessary but meh...just in-case somebody does something stupid
- switch(href_list["vote"])
- if("close")
- voting -= usr.client
- close_browser(usr, "vote")
- return
- if("cancel")
- if(usr.client.admin_holder && (usr.client.admin_holder.rights & R_MOD))
- reset()
- if("toggle_restart")
- if(usr.client.admin_holder && (usr.client.admin_holder.rights & R_MOD))
- CONFIG_SET(flag/allow_vote_restart, !CONFIG_GET(flag/allow_vote_restart))
- if("toggle_gamemode")
- if(usr.client.admin_holder && (usr.client.admin_holder.rights & R_MOD))
- CONFIG_SET(flag/allow_vote_mode, !CONFIG_GET(flag/allow_vote_mode))
- if("restart")
- if(CONFIG_GET(flag/allow_vote_restart) || (usr.client.admin_holder && (usr.client.admin_holder.rights & R_MOD)))
- initiate_vote("restart",usr.key)
- if("gamemode")
- if(CONFIG_GET(flag/allow_vote_mode) || (usr.client.admin_holder && (usr.client.admin_holder.rights & R_MOD)))
- initiate_vote("gamemode",usr.key)
- if("custom")
- if(usr.client.admin_holder && (usr.client.admin_holder.rights & R_MOD))
- initiate_vote("custom",usr.key)
- else
- submit_vote(usr.ckey, round(text2num(href_list["vote"])))
- usr.vote()
-
-/mob/verb/vote()
- set category = "OOC"
- set name = "Vote"
-
- if(vote)
- show_browser(src, vote.interface(client), "Vote", "vote", "can_close=0")
-
-
-
-var/MapDaemon_UID = -1 //-1 by default so we know when to set it
-var/force_mapdaemon_vote = 0
-
-//Basically, this completely ignores the voting datum etc in favor of editing a simple a simple list, player_votes
-//Upon request by MapDaemon, world/Topic() will it into JSON and send it away, so we do 0 handling in DM
-/client/verb/mapVote()
- set category = "OOC"
- set name = "Map Vote"
-
- if(!SSticker.mode || !SSticker.mode.round_finished)
- to_chat(src, SPAN_NOTICE("Please wait until the round ends."))
- return
-
- var/list/L = list()
- L += "Don't care"
-
- // For future modularity and maybe more subtle solutions here?
- switch(GLOB.clients.len)
- if (0 to PLAYERCOUNT_LOWPOP_MAP_LIMIT)
- L += LOWPOP_NEXT_MAP_CANDIDATES.Copy()
- else
- L += NEXT_MAP_CANDIDATES.Copy()
- L -= map_tag
- var/selection = input("Vote for the next map to play on", "Vote:", "Don't care") as null|anything in L
-
- if(!selection || !src) return
-
- if(selection == "Don't care")
- to_chat(src, SPAN_NOTICE("You have not voted."))
- return
-
- to_chat(src, SPAN_NOTICE("You have voted for [selection]."))
-
- player_votes[src.ckey] = selection
-
-/client/proc/forceMDMapVote()
- set name = "Force Map Vote"
- set category = "Server.MapDaemon"
-
- force_mapdaemon_vote = !force_mapdaemon_vote
- to_chat(src, SPAN_NOTICE("The server will [force_mapdaemon_vote ? "now" : "no longer"] tell Mapdaemon to start a vote the next time possible."))
-
- message_staff("[src] is attempting to force a MapDaemon vote.")
-
-//Uses an invalid ckey to rig the votes
-//Special case for }}} handled in World/Topic()
-//Set up so admins can fight over what the map will be, hurray
-/client/proc/forceNextMap()
- set name = "Force Map"
- set category = "Server.MapDaemon"
-
- if(alert("Are you sure you want to force the next map?",, "Yes", "No") == "No") return
-
- var/selection = input("Vote for the next map to play on", "Vote:", "LV-624") as null|anything in DEFAULT_NEXT_MAP_CANDIDATES
-
- if(!selection || !src) return
-
- to_chat(src, SPAN_NOTICE("You have forced the next map to be [selection]"))
-
- message_staff("[src] just forced the next map to be [selection].")
-
- player_votes["}}}"] = selection //}}} is an invalid ckey so we won't be in risk of someone using this cheekily
-
-
-var/enable_map_vote = 1
-/client/proc/cancelMapVote()
- set name = "Toggle Map Vote"
- set category = "Server.MapDaemon"
-
- if(alert("Are you sure you want to turn the map vote [!enable_map_vote ? "on" : "off"]?",, "Yes", "No") == "No") return
-
- enable_map_vote = !enable_map_vote
-
- to_world(SPAN_NOTICE("[src] has toggled the map vote [enable_map_vote ? "on" : "off"]"))
- to_chat(src, SPAN_NOTICE("You have toggled the map vote [enable_map_vote ? "on" : "off"]"))
-
- message_staff("[src] just toggled the map vote [enable_map_vote ? "on" : "off"].")
-
-/client/proc/showVotableMaps()
- set name = "List Maps"
- set category = "Server.MapDaemon"
-
- to_chat(src, "Possible maps irrespective of pop:")
- for(var/i in NEXT_MAP_CANDIDATES)
- to_chat(src, SPAN_NOTICE(i))
-
-/client/proc/editVotableMaps()
- set name = "Edit Maps"
- set category = "Server.MapDaemon"
-
- if(alert("Are you sure you want to edit the map voting candidates?",, "Yes", "No") == "No") return
-
- switch(alert("Do you want to add or remove a map?",, "Add", "Remove", "Cancel"))
- if("Cancel")
- return
- if("Add")
- var/selection = ""
- switch(alert("Do you want to add one of the default map possibilities?",, "Yes", "No"))
- if("Yes")
- selection = input("Pick a default map.") as null|anything in DEFAULT_NEXT_MAP_CANDIDATES
- if("No")
- if(alert("Warning! This is a very dangerous option. If there is a typo in the map name and your choice wins, MapDaemon will crash. Please make sure you enter the exact name of the map. Are you sure you want to continue?", "WARNING", "Yes", "No") == "No") return
- selection = input("Enter a map at your own risk.")
-
- if(!selection || !src) return
- if(NEXT_MAP_CANDIDATES.Find(selection))
- alert("That option was already available.")
- return
- NEXT_MAP_CANDIDATES.Add(selection)
- message_staff("[src] just added [selection] to the map pool.")
- if("Remove")
- var/selection = input("Pick a map to remove from the pool") as null|anything in NEXT_MAP_CANDIDATES
- if(!selection || !src) return
- NEXT_MAP_CANDIDATES.Remove(selection)
- message_staff("[src] just removed [selection] from the map pool.")
-
-var/kill_map_daemon = 0
-/client/proc/killMapDaemon()
- set name = "Kill MapDaemon"
- set category = "Server.MapDaemon"
-
- if(alert("Are you sure you want to kill MapDaemon?",, "Yes", "No") == "No") return
-
- kill_map_daemon = 1
-
- alert("MapDaemon will be killed on next round-end check.")
- message_staff("[src] just killed MapDaemon. It may be restarted with \"Map Vote - Revive MapDaemon\".")
-
-/client/proc/reviveMapDaemon()
- set name = "Revive MapDaemon"
- set category = "Server.MapDaemon"
-
- kill_map_daemon = 0
-
- message_staff("[src] is attempting to restart MapDaemon.")
-
- run_mapdaemon_batch()
-
-/proc/run_mapdaemon_batch()
-
- set waitfor = 0
-
- if(world.system_type != MS_WINDOWS) return 0 //Don't know if it'll work for non-Windows, so let's just abort
-
- shell("run_mapdaemon.bat")
diff --git a/code/datums/agents/objectives/steal.dm b/code/datums/agents/objectives/steal.dm
index 007d11ce1b89..1f1bc5d6b2be 100644
--- a/code/datums/agents/objectives/steal.dm
+++ b/code/datums/agents/objectives/steal.dm
@@ -83,14 +83,14 @@
icon_state = "golden_health"
item_state = "analyzer"
-/obj/item/device/healthanalyzer/golden/New()
+/obj/item/device/healthanalyzer/golden/Initialize()
. = ..()
-
+
LAZYADD(objects_of_interest, src)
/obj/item/device/healthanalyzer/golden/Destroy()
. = ..()
-
+
LAZYREMOVE(objects_of_interest, src)
// Medbay item
@@ -100,14 +100,14 @@
icon_state = "folded_sheet_medical"
item_state = "folded_sheet_medical"
-/obj/item/folded_medical_sheet/New()
+/obj/item/folded_medical_sheet/Initialize()
. = ..()
-
+
LAZYADD(objects_of_interest, src)
/obj/item/folded_medical_sheet/Destroy()
. = ..()
-
+
LAZYREMOVE(objects_of_interest, src)
// Req tally book
@@ -117,14 +117,14 @@
icon = 'icons/obj/items/books.dmi'
icon_state ="book"
-/obj/item/tally_book/New()
+/obj/item/tally_book/Initialize()
. = ..()
-
+
LAZYADD(objects_of_interest, src)
/obj/item/tally_book/Destroy()
. = ..()
-
+
LAZYREMOVE(objects_of_interest, src)
// CIC item
@@ -134,12 +134,12 @@
icon_state = "golden_cup"
item_state = "golden_cup"
-/obj/item/golden_cup/New()
+/obj/item/golden_cup/Initialize()
. = ..()
-
+
LAZYADD(objects_of_interest, src)
-
+
/obj/item/golden_cup/Destroy()
. = ..()
-
- LAZYREMOVE(objects_of_interest, src)
\ No newline at end of file
+
+ LAZYREMOVE(objects_of_interest, src)
diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm
index 7168a78ac2cc..a0dcb2aa8862 100644
--- a/code/datums/diseases/advance/advance.dm
+++ b/code/datums/diseases/advance/advance.dm
@@ -395,7 +395,7 @@ var/list/advance_cures = list(
AD.Refresh()
for(var/mob/living/carbon/human/H in shuffle(GLOB.alive_mob_list.Copy()))
- if(H.z != 1)
+ if(!is_ground_level(H.z))
continue
if(!H.has_disease(D))
H.contract_disease(D, 1)
diff --git a/code/datums/emergency_calls/cryo_marines.dm b/code/datums/emergency_calls/cryo_marines.dm
index 7a6e3989f00a..a1829b9c5713 100644
--- a/code/datums/emergency_calls/cryo_marines.dm
+++ b/code/datums/emergency_calls/cryo_marines.dm
@@ -14,7 +14,7 @@
/datum/emergency_call/cryo_squad/create_member(datum/mind/M)
set waitfor = 0
- if(map_tag == MAP_WHISKEY_OUTPOST)
+ if(SSmapping.configs[GROUND_MAP].map_name == MAP_WHISKEY_OUTPOST)
name_of_spawn = /obj/effect/landmark/ert_spawns/distress_wo
var/turf/spawn_loc = get_spawn_point()
@@ -27,14 +27,14 @@
if (medics < max_medics)
medics++
arm_equipment(H, "USCM (Cryo) Squad Medic", TRUE, TRUE)
- to_chat(H, "\red You are a medic in the USCM, you are here to assist in the defence of the [map_tag]. Listen to the chain of command. ")
+ to_chat(H, "\red You are a medic in the USCM, you are here to assist in the defence of the [SSmapping.configs[GROUND_MAP].map_name]. Listen to the chain of command. ")
else if (heavies < max_heavies)
heavies++
arm_equipment(H, "USCM (Cryo) Squad Engineer", TRUE, TRUE)
- to_chat(H, "\red You are an engineer in the USCM, you are here to assist in the defence of the [map_tag]. Listen to the chain of command. ")
+ to_chat(H, "\red You are an engineer in the USCM, you are here to assist in the defence of the [SSmapping.configs[GROUND_MAP].map_name]. Listen to the chain of command. ")
else
arm_equipment(H, "USCM (Cryo) Squad Marine (PFC)", TRUE, TRUE)
- to_chat(H, "\red You are a private in the USCM, you are here to assist in the defence of the [map_tag]. Listen to the chain of command. ")
+ to_chat(H, "\red You are a private in the USCM, you are here to assist in the defence of the [SSmapping.configs[GROUND_MAP].map_name]. Listen to the chain of command. ")
sleep(10)
to_chat(H, "Objectives: [objectives]")
diff --git a/code/datums/emergency_calls/cryo_marines_heavy.dm b/code/datums/emergency_calls/cryo_marines_heavy.dm
index 0ec7d9758c3a..38d679592379 100644
--- a/code/datums/emergency_calls/cryo_marines_heavy.dm
+++ b/code/datums/emergency_calls/cryo_marines_heavy.dm
@@ -16,7 +16,7 @@
/datum/emergency_call/cryo_squad_equipped/create_member(datum/mind/M)
set waitfor = 0
- if(map_tag == MAP_WHISKEY_OUTPOST)
+ if(SSmapping.configs[GROUND_MAP].map_name == MAP_WHISKEY_OUTPOST)
name_of_spawn = /obj/effect/landmark/ert_spawns/distress_wo
var/turf/spawn_loc = get_spawn_point()
@@ -29,25 +29,25 @@
if(!leader)
leader = H
arm_equipment(H, "USCM Cryo Squad Leader (Equipped)", TRUE, TRUE)
- to_chat(H, SPAN_WARNING("You are a Squad leader in the USCM, your squad is here to assist in the defence of the [map_tag]. "))
+ to_chat(H, SPAN_WARNING("You are a Squad leader in the USCM, your squad is here to assist in the defence of the [SSmapping.configs[GROUND_MAP].map_name]. "))
else if (heavies < max_heavies)
heavies++
if(prob(40))
arm_equipment(H, "USCM Cryo Smartgunner (Equipped)", TRUE, TRUE)
- to_chat(H, SPAN_WARNING("You are a smartgunner in the USCM, your squad is here to assist in the defence of the [map_tag]. Listen to [leader.name] they are your (acting) squad leader. "))
+ to_chat(H, SPAN_WARNING("You are a smartgunner in the USCM, your squad is here to assist in the defence of the [SSmapping.configs[GROUND_MAP].map_name]. Listen to [leader.name] they are your (acting) squad leader. "))
else if(prob(20))
arm_equipment(H, "USCM Cryo Specialist (Equipped)", TRUE, TRUE)
- to_chat(H, SPAN_WARNING("You are a specialist in the USCM, your squad is here to assist in the defence of the [map_tag]. Listen to [leader.name] they are your (acting) squad leader. "))
+ to_chat(H, SPAN_WARNING("You are a specialist in the USCM, your squad is here to assist in the defence of the [SSmapping.configs[GROUND_MAP].map_name]. Listen to [leader.name] they are your (acting) squad leader. "))
else
arm_equipment(H, "USCM Cryo Engineer (Equipped)", TRUE, TRUE)
- to_chat(H, SPAN_WARNING("You are an engineer in the USCM, your squad is here to assist in the defence of the [map_tag]. Listen to [leader.name] they are your (acting) squad leader. "))
+ to_chat(H, SPAN_WARNING("You are an engineer in the USCM, your squad is here to assist in the defence of the [SSmapping.configs[GROUND_MAP].map_name]. Listen to [leader.name] they are your (acting) squad leader. "))
else if (medics < max_medics)
medics++
arm_equipment(H, "USCM Cryo Medic (Equipped)", TRUE, TRUE)
- to_chat(H, SPAN_WARNING("You are a medic in the USCM, your squad is here to assist in the defence of the [map_tag]. Listen to [leader.name] they are your (acting) squad leader. "))
+ to_chat(H, SPAN_WARNING("You are a medic in the USCM, your squad is here to assist in the defence of the [SSmapping.configs[GROUND_MAP].map_name]. Listen to [leader.name] they are your (acting) squad leader. "))
else
arm_equipment(H,"USCM Cryo Private (Equipped)", TRUE, TRUE)
- to_chat(H, SPAN_WARNING("You are a private in the USCM, your squad is here to assist in the defence of [map_tag]. Listen to [leader.name] they are your (acting) squad leader. "))
+ to_chat(H, SPAN_WARNING("You are a private in the USCM, your squad is here to assist in the defence of [SSmapping.configs[GROUND_MAP].map_name]. Listen to [leader.name] they are your (acting) squad leader. "))
sleep(10)
to_chat(H, "Objectives: [objectives]")
diff --git a/code/datums/emergency_calls/emergency_call.dm b/code/datums/emergency_calls/emergency_call.dm
index 9d08de522b61..8ec07ab1f776 100644
--- a/code/datums/emergency_calls/emergency_call.dm
+++ b/code/datums/emergency_calls/emergency_call.dm
@@ -139,7 +139,7 @@
var/deathtime = world.time - usr.timeofdeath
if(deathtime < SECONDS_60) //Nice try, ghosting right after the announcement
- if(map_tag != MAP_WHISKEY_OUTPOST) // people ghost so often on whiskey outpost.
+ if(SSmapping.configs[GROUND_MAP].map_name != MAP_WHISKEY_OUTPOST) // people ghost so often on whiskey outpost.
to_chat(usr, SPAN_WARNING("You ghosted too recently."))
return
diff --git a/code/datums/emergency_calls/tank_crew.dm b/code/datums/emergency_calls/tank_crew.dm
index caf343054d3e..86a258466bf8 100644
--- a/code/datums/emergency_calls/tank_crew.dm
+++ b/code/datums/emergency_calls/tank_crew.dm
@@ -12,7 +12,7 @@
/datum/emergency_call/tank_crew/create_member(datum/mind/M)
set waitfor = 0
- if(map_tag == MAP_WHISKEY_OUTPOST)
+ if(SSmapping.configs[GROUND_MAP].map_name == MAP_WHISKEY_OUTPOST)
name_of_spawn = /obj/effect/landmark/ert_spawns/distress_wo
var/turf/spawn_loc = get_spawn_point()
@@ -23,7 +23,7 @@
sleep(5)
arm_equipment(H, "USCM Vehicle Crewman (CRMN)", TRUE, TRUE)
- to_chat(H, "\red You are a vehicle crewman in the USCM, you are here to assist in the defence of the [map_tag]. Listen to the chain of command.")
+ to_chat(H, "\red You are a vehicle crewman in the USCM, you are here to assist in the defence of the [SSmapping.configs[GROUND_MAP].map_name]. Listen to the chain of command.")
sleep(10)
to_chat(H, "Objectives: [objectives]")
diff --git a/code/datums/emergency_calls/whiskey_outpost.dm b/code/datums/emergency_calls/whiskey_outpost.dm
index 6746b4ec6651..fada80a8275f 100644
--- a/code/datums/emergency_calls/whiskey_outpost.dm
+++ b/code/datums/emergency_calls/whiskey_outpost.dm
@@ -12,7 +12,7 @@
/datum/emergency_call/wo/create_member(datum/mind/M)
set waitfor = 0
- if(map_tag == MAP_WHISKEY_OUTPOST)
+ if(SSmapping.configs[GROUND_MAP].map_name == MAP_WHISKEY_OUTPOST)
name_of_spawn = /obj/effect/landmark/ert_spawns/distress_wo
var/turf/spawn_loc = get_spawn_point()
@@ -25,25 +25,25 @@
if(!leader)
leader = mob
arm_equipment(mob, "Dust Raider Squad Leader", TRUE, TRUE)
- to_chat(mob, "\red You are a Squad leader in the USCM, your squad is here to assist in the defence of the [map_tag]. ")
+ to_chat(mob, "\red You are a Squad leader in the USCM, your squad is here to assist in the defence of the [SSmapping.configs[GROUND_MAP].map_name]. ")
else if (heavies < max_heavies)
heavies++
if(prob(40))
arm_equipment(mob, "Dust Raider Smartgunner", TRUE, TRUE)
- to_chat(mob, "\red You are a smartgunner in the USCM, your squad is here to assist in the defence of the [map_tag]. Listen to [leader.name] they are your (acting) squad leader. ")
+ to_chat(mob, "\red You are a smartgunner in the USCM, your squad is here to assist in the defence of the [SSmapping.configs[GROUND_MAP].map_name]. Listen to [leader.name] they are your (acting) squad leader. ")
else if(prob(20))
arm_equipment(mob, "Dust Raider Specialist", TRUE, TRUE)
- to_chat(mob, "\red You are a specialist in the USCM, your squad is here to assist in the defence of the [map_tag]. Listen to [leader.name] they are your (acting) squad leader. ")
+ to_chat(mob, "\red You are a specialist in the USCM, your squad is here to assist in the defence of the [SSmapping.configs[GROUND_MAP].map_name]. Listen to [leader.name] they are your (acting) squad leader. ")
else
arm_equipment(mob, "Dust Raider Engineer", TRUE, TRUE)
- to_chat(mob, "\red You are an engineer in the USCM, your squad is here to assist in the defence of the [map_tag]. Listen to [leader.name] they are your (acting) squad leader. ")
+ to_chat(mob, "\red You are an engineer in the USCM, your squad is here to assist in the defence of the [SSmapping.configs[GROUND_MAP].map_name]. Listen to [leader.name] they are your (acting) squad leader. ")
else if (medics < max_medics)
medics++
arm_equipment(mob, "Dust Raider Medic", TRUE, TRUE)
- to_chat(mob, "\red You are a medic in the USCM, your squad is here to assist in the defence of the [map_tag]. Listen to [leader.name] they are your (acting) squad leader. ")
+ to_chat(mob, "\red You are a medic in the USCM, your squad is here to assist in the defence of the [SSmapping.configs[GROUND_MAP].map_name]. Listen to [leader.name] they are your (acting) squad leader. ")
else
arm_equipment(mob,"Dust Raider Private", TRUE, TRUE)
- to_chat(mob, "\red You are a private in the USCM, your squad is here to assist in the defence of [map_tag]. Listen to [leader.name] they are your (acting) squad leader. ")
+ to_chat(mob, "\red You are a private in the USCM, your squad is here to assist in the defence of [SSmapping.configs[GROUND_MAP].map_name]. Listen to [leader.name] they are your (acting) squad leader. ")
sleep(10)
to_chat(mob, "Objectives: [objectives]")
diff --git a/code/datums/entities/map_votes.dm b/code/datums/entities/map_votes.dm
index f708f250d596..eaa799da71e1 100644
--- a/code/datums/entities/map_votes.dm
+++ b/code/datums/entities/map_votes.dm
@@ -2,7 +2,7 @@
var/map_name
var/total_votes
-
+
/datum/entity_meta/map_vote
entity_type = /datum/entity/map_vote
table_name = "map_vote"
@@ -11,4 +11,4 @@
)
/datum/entity_meta/map_vote/on_read(var/datum/entity/map_vote/vote)
- vote.total_votes = text2num("[vote.total_votes]")
\ No newline at end of file
+ vote.total_votes = text2num("[vote.total_votes]")
diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm
index d9140b39e51a..2ad6b232e45d 100644
--- a/code/datums/helper_datums/teleport.dm
+++ b/code/datums/helper_datums/teleport.dm
@@ -177,12 +177,9 @@
teleatom.visible_message(SPAN_DANGER("The [teleatom] bounces off of the portal!"))
return 0
- if(is_admin_level(destination.z)) //centcomm z-level
+ if(is_admin_level(destination.z))
if(length(teleatom.search_contents_for(/obj/item/storage/backpack/holding)))
teleatom.visible_message(SPAN_DANGER("The Bag of Holding bounces off of the portal!"))
return 0
-
- if(destination.z > 7) //Away mission z-levels
- return 0
return 1
diff --git a/code/datums/map_config.dm b/code/datums/map_config.dm
new file mode 100644
index 000000000000..27ac225c7ab8
--- /dev/null
+++ b/code/datums/map_config.dm
@@ -0,0 +1,264 @@
+//used for holding information about unique properties of maps
+//feed it json files that match the datum layout
+//defaults to box
+// -Cyberboss
+
+/datum/map_config
+ // Metadata
+ var/config_filename = "maps/LV624.json"
+ var/defaulted = TRUE // set to FALSE by LoadConfig() succeeding
+ // Config from maps.txt
+ var/config_max_users = 0
+ var/config_min_users = 0
+ var/voteweight = 1
+
+ // Config actually from the JSON - default values
+ var/map_name = "LV624"
+ var/map_path = "map_files/LV624"
+ var/map_file = "LV624.dmm"
+
+ var/traits = null
+ var/space_empty_levels = 1
+ var/list/environment_traits = list()
+ var/armor_style = "default"
+ var/list/gamemodes = list()
+
+ var/allow_custom_shuttles = TRUE
+ var/shuttles = list()
+
+ var/announce_text = ""
+
+ var/squads_max_num = 4
+
+ var/weather_holder
+
+ var/list/survivor_types = list(
+ "Survivor - Scientist",
+ "Survivor - Doctor",
+ "Survivor - Chef",
+ "Survivor - Chaplain",
+ "Survivor - Miner",
+ "Survivor - Colonial Marshall",
+ "Survivor - Engineer"
+ )
+
+ var/list/defcon_triggers = list(5150, 4225, 2800, 1000, 0.0)
+
+ var/survivor_message = "You are a survivor of the attack on the colony. You worked or lived in the archaeology colony, and managed to avoid the alien attacks... until now."
+
+ var/map_item_type
+
+ var/force_mode
+
+ var/list/monkey_types = list(/mob/living/carbon/human/monkey)
+
+/proc/load_map_config(filename, default, delete_after, error_if_missing = TRUE)
+ var/datum/map_config/config = new
+ if(default)
+ return config
+ if(!config.LoadConfig(filename, error_if_missing))
+ qdel(config)
+ config = new /datum/map_config
+ if(delete_after)
+ fdel(filename)
+ return config
+
+
+/proc/load_map_configs(list/maptypes, default, delete_after, error_if_missing = TRUE)
+ var/list/configs = list()
+
+ for(var/i in maptypes)
+ var/filename = MAP_TO_FILENAME[i]
+ var/datum/map_config/config = new
+ if(default)
+ configs[i] = config
+ continue
+ if(!config.LoadConfig(filename, error_if_missing, i))
+ qdel(config)
+ config = new /datum/map_config
+ if(delete_after)
+ fdel(filename)
+ configs[i] = config
+ return configs
+
+#define CHECK_EXISTS(X) if(!istext(json[X])) { log_world("[##X] missing from json!"); return; }
+/datum/map_config/proc/LoadConfig(filename, error_if_missing, maptype)
+ if(!fexists(filename))
+ if(error_if_missing)
+ log_world("map_config not found: [filename]")
+ return
+
+ var/json = file(filename)
+ if(!json)
+ log_world("Could not open map_config: [filename]")
+ return
+
+ json = file2text(json)
+ if(!json)
+ log_world("map_config is not text: [filename]")
+ return
+
+ json = json_decode(json)
+ if(!json)
+ log_world("map_config is not json: [filename]")
+ return
+
+ config_filename = filename
+
+ CHECK_EXISTS("map_name")
+ map_name = json["map_name"]
+ CHECK_EXISTS("map_path")
+ map_path = json["map_path"]
+
+ map_file = json["map_file"]
+ // "map_file": "BoxStation.dmm"
+ if (istext(map_file))
+ if (!fexists("maps/[map_path]/[map_file]"))
+ log_world("Map file ([map_file]) does not exist!")
+ return
+ // "map_file": ["Lower.dmm", "Upper.dmm"]
+ else if (islist(map_file))
+ for (var/file in map_file)
+ if (!fexists("maps/[map_path]/[file]"))
+ log_world("Map file ([file]) does not exist!")
+ return
+ else
+ log_world("map_file missing from json!")
+ return
+
+ if (islist(json["shuttles"]))
+ var/list/L = json["shuttles"]
+ for(var/key in L)
+ var/value = L[key]
+ shuttles[key] = value
+ else if ("shuttles" in json)
+ log_world("map_config shuttles is not a list!")
+ return
+
+ if (islist(json["survivor_types"]))
+ survivor_types = json["survivor_types"]
+ else if ("survivor_types" in json)
+ log_world("map_config survivor_types is not a list!")
+ return
+
+ if (islist(json["monkey_types"]))
+ monkey_types = list()
+ for(var/monkey in json["monkey_types"])
+ switch(monkey)
+ if("farwa")
+ monkey_types += /mob/living/carbon/human/farwa
+ if("monkey")
+ monkey_types += /mob/living/carbon/human/monkey
+ if("neaera")
+ monkey_types += /mob/living/carbon/human/neaera
+ if("stok")
+ monkey_types += /mob/living/carbon/human/stok
+ if("yiren")
+ monkey_types += /mob/living/carbon/human/yiren
+ else
+ log_world("map_config monkey_types has invalid name!")
+ return
+ else if ("monkey_types" in json)
+ log_world("map_config monkey_types is not a list!")
+ return
+
+ if (islist(json["defcon_triggers"]))
+ defcon_triggers = json["defcon_triggers"]
+ else if ("defcon_triggers" in json)
+ log_world("map_config defcon_triggers is not a list!")
+ return
+
+ traits = json["traits"]
+ if(islist(traits))
+ for(var/list/ztraits in traits) // Defaults to ground map if not specified
+ if(!ztraits[ZTRAIT_GROUND] && !ztraits[ZTRAIT_MARINE_MAIN_SHIP])
+ ztraits[ZTRAIT_GROUND] = TRUE
+ else if(traits)
+ log_world("map_config traits is not a list!")
+ return
+
+ var/temp = json["space_empty_levels"]
+ if (isnum(temp))
+ space_empty_levels = temp
+ else if (!isnull(temp))
+ log_world("map_config space_empty_levels is not a number!")
+ return
+
+ temp = json["squads"]
+ if(isnum(temp))
+ squads_max_num = temp
+ else if(!isnull(temp))
+ log_world("map_config squads_max_num is not a number!")
+ return
+
+ allow_custom_shuttles = json["allow_custom_shuttles"] != FALSE
+
+ if(json["armor"])
+ armor_style = json["armor"]
+
+ if(json["survivor_message"])
+ survivor_message = json["survivor_message"]
+
+ if(json["force_mode"])
+ force_mode = json["force_mode"]
+
+ if(json["announce_text"])
+ announce_text = replacetext(json["announce_text"], "###SHIPNAME###", MAIN_SHIP_NAME)
+
+ if(json["weather_holder"])
+ weather_holder = text2path(json["weather_holder"])
+ if(!weather_holder)
+ log_world("map_config weather_holder is not a proper typepath!")
+ return
+
+ if(json["map_item_type"])
+ map_item_type = text2path(json["map_item_type"])
+ if(!map_item_type)
+ log_world("map_config map_item_type is not a proper typepath!")
+ return
+
+ if(islist(json["environment_traits"]))
+ environment_traits = json["environment_traits"]
+ else if(!isnull(json["environment_traits"]))
+ log_world("map_config environment_traits is not a list!")
+ return
+
+ var/list/gamemode_names = list()
+ for(var/t in subtypesof(/datum/game_mode))
+ var/datum/game_mode/G = t
+ gamemode_names += initial(G.config_tag)
+
+ if(islist(json["gamemodes"]))
+ for(var/g in json["gamemodes"])
+ if(!(g in gamemode_names))
+ log_world("map_config has an invalid gamemode name!")
+ return
+ if(g == "Extended") // always allow extended
+ continue
+ gamemodes += g
+ gamemodes += "Extended"
+ else if(!isnull(json["gamemodes"]))
+ log_world("map_config gamemodes is not a list!")
+ return
+ else
+ for(var/a in subtypesof(/datum/game_mode))
+ var/datum/game_mode/G = a
+ gamemodes += initial(G.config_tag)
+
+ defaulted = FALSE
+ return TRUE
+#undef CHECK_EXISTS
+
+/datum/map_config/proc/GetFullMapPaths()
+ if (istext(map_file))
+ return list("maps/[map_path]/[map_file]")
+ . = list()
+ for (var/file in map_file)
+ . += "maps/[map_path]/[file]"
+
+
+/datum/map_config/proc/MakeNextMap(maptype = GROUND_MAP)
+ if(maptype == GROUND_MAP)
+ return config_filename == "data/next_map.json" || fcopy(config_filename, "data/next_map.json")
+ else if(maptype == SHIP_MAP)
+ return config_filename == "data/next_ship.json" || fcopy(config_filename, "data/next_ship.json")
diff --git a/code/datums/soundOutput.dm b/code/datums/soundOutput.dm
index ae5786604445..c8be5c6f17e2 100644
--- a/code/datums/soundOutput.dm
+++ b/code/datums/soundOutput.dm
@@ -27,8 +27,8 @@
var/turf/owner_turf = get_turf(owner.mob)
if(owner_turf)
// We're in an interior and sound came from outside
- if(owner_turf.z == interior_manager.interior_z && owner_turf.z != T.z)
- var/datum/interior/VI = interior_manager.get_interior_by_coords(owner_turf.x, owner_turf.y)
+ if(owner_turf.z == GLOB.interior_manager.interior_z && owner_turf.z != T.z)
+ var/datum/interior/VI = GLOB.interior_manager.get_interior_by_coords(owner_turf.x, owner_turf.y)
if(VI && VI.exterior)
var/turf/candidate = get_turf(VI.exterior)
if(!(candidate.z == T.z))
diff --git a/code/datums/weather/weather_map_holder.dm b/code/datums/weather/weather_map_holder.dm
index e694ebee068b..f78a9f0b6992 100644
--- a/code/datums/weather/weather_map_holder.dm
+++ b/code/datums/weather/weather_map_holder.dm
@@ -1,18 +1,17 @@
-// Delegate object that holds all the map-dependent pieces of the
+// Delegate object that holds all the map-dependent pieces of the
// One of these is instanced into the weather subsystem when it's initialized
// based on the current map_tag (should be the only map_tag dependent piece of code)
/datum/weather_ss_map_holder
var/name = "set this" // For VV
- var/source_map_tag // Map tag that made this
// Weather SS configuration options
var/min_time_between_events = MINUTES_5 // Self explanatory
- var/warn_time = SECONDS_30 // Warning time between the call to
+ var/warn_time = SECONDS_30 // Warning time between the call to
var/no_weather_turf_icon_state = "" // Icon state to set on the global VFX holder
// when there's no weather.
var/list/potential_weather_events // List of types of possible weather events
-
+
/datum/weather_ss_map_holder/New()
potential_weather_events = list()
@@ -26,12 +25,12 @@
/datum/weather_ss_map_holder/proc/should_affect_atom(var/atom/A)
if (!istype(A))
return FALSE
-
+
var/area/target_area = get_area(A)
return should_affect_area(target_area)
// Should we start an event? This just deals with the logic that an event is starting
-// period, nothing to do with what the type of the event will be when its
+// period, nothing to do with what the type of the event will be when its
// eventually chosen
/datum/weather_ss_map_holder/proc/should_start_event()
log_debug("Weather subsystem map holder [src] is improperly configured. Code: WSSMH02")
@@ -46,7 +45,7 @@
log_debug("Weather subsystem map holder [src] is improperly configured. Code: WSSMH03")
return null
-// Called whenever the weather SS decides to start an event, but
+// Called whenever the weather SS decides to start an event, but
// warn_time deciseconds before it actually starts
// (think weather sirens on sorokyne)
// This can do nothing safely, so you don't have to override it
diff --git a/code/datums/weather/weather_map_holders/sorokyne.dm b/code/datums/weather/weather_map_holders/sorokyne.dm
index 3255cc4d254f..d101e9147203 100644
--- a/code/datums/weather/weather_map_holders/sorokyne.dm
+++ b/code/datums/weather/weather_map_holders/sorokyne.dm
@@ -2,7 +2,6 @@
/datum/weather_ss_map_holder/sorokyne
name = "Sorokyne Map Holder"
- source_map_tag = MAP_SOROKYNE_STRATA
min_time_between_events = MINUTES_20
no_weather_turf_icon_state = "strata_clearsky"
@@ -23,4 +22,4 @@
/datum/weather_ss_map_holder/sorokyne/weather_warning()
for (var/obj/structure/machinery/weather_siren/WS in weather_notify_objects)
- WS.weather_warning()
\ No newline at end of file
+ WS.weather_warning()
diff --git a/code/game/area/Z_Holder.dm b/code/game/area/Z_Holder.dm
deleted file mode 100644
index 0dbdf5e42d76..000000000000
--- a/code/game/area/Z_Holder.dm
+++ /dev/null
@@ -1,64 +0,0 @@
-////////////////////////////////////////////////////////////
-// This is the Z-holder, which will do a LOT of things to //
-// handle the fact that we have a shit-ton of maps. Each //
-// Layer will need to have this object in it's T-comm //
-// area. If you don't, you won't be able to manage things //
-// like where gibbed bodies land, where beacons go, and //
-// which levels are "planets" and are unbreachable. //
-// Follow the format for the example, and set the vars as //
-// Needed. //
-////////////////////////////////////////////////////////////
-
-
-/obj/item/z_holder
- name = "Default" //Name of the item
- var/MapName = "Default" //This should be the name of the map, without the Z.##
- desc = "Something you shouldn't be fucking with while the server is running." //This shouldn't be changed
- var/Planet = 0 //Set true if this is a planet, and the ground shouldn't "breach to space"
- var/Station = 0 //Set true if this is a station, and it should breach to space
- var/Sulaco = 0 //Set true if this is a deck of the Sulaco.
- icon = 'icons/obj/structures/props/stationobjs.dmi'
- icon_state = "relay"
- unacidable = TRUE
- anchored = 1
-
-/obj/item/z_holder/LV624 //Zlayer 1
- name = "LV-624 Z-Holder"
- MapName = "LV624"
- Planet = 1
-
-
-/obj/item/z_holder/CentCom //Zlayer 2
- name = "CentCom Z-Holder"
- MapName = "CentComm"
- Station = 1
-
-
-/obj/item/z_holder/SulacoUpper //Zlayer 3
- name = "Sulaco Upper Z-Holder"
- MapName = "PlaceholderSulaco"
- Station = 1
-
-
-/obj/item/z_holder/SulacoLower //Zlayer 4
- name = "Sulaco Lower Z-Holder"
- MapName = "SulacoBottom"
- Station = 1
-
-
-/obj/item/z_holder/Space //Zlayer 5
- name = "Space Z-holder"
- MapName = "Space"
-
-
-/obj/item/z_holder/Halloween //Zlayer 6
- name = "HauntedHouse Z-holder"
- MapName = "HauntedHouse"
- Planet = 1
-
-
-/obj/item/z_holder/Prison //Zlayer 7
- name = "Prison Z-holder"
- MapName = "Prison"
- Station = 1
-
diff --git a/maps/Z.02.Admin_Level.dm b/code/game/area/admin_level.dm
similarity index 100%
rename from maps/Z.02.Admin_Level.dm
rename to code/game/area/admin_level.dm
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 44b6f2565d4b..dc81328e3813 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -17,6 +17,8 @@
var/flags_alarm_state = NO_FLAGS
+ var/unique = TRUE
+
var/has_gravity = 1
var/list/apc = list()
var/list/area_machines = list() // list of machines only for master areas
@@ -78,17 +80,24 @@
/area/New()
+ // This interacts with the map loader, so it needs to be set immediately
+ // rather than waiting for atoms to initialize.
+ if(unique)
+ GLOB.areas_by_type[type] = src
..()
+ master = src //moved outside the spawn(1) to avoid runtimes in lighting.dm when it references loc.loc.master ~Carn
+ related = list(src)
+ initialize_power_and_lighting()
+
+/area/Initialize(mapload, ...)
icon_state = "" //Used to reset the icon overlay, I assume.
layer = AREAS_LAYER
- master = src //moved outside the spawn(1) to avoid runtimes in lighting.dm when it references loc.loc.master ~Carn
uid = ++global_uid
- related = list(src)
+ . = ..()
active_areas += src
all_areas += src
-
- initialize_power_and_lighting()
+ reg_in_areas_in_z()
/area/proc/initialize_power_and_lighting(override_power)
if(requires_power)
@@ -448,3 +457,26 @@
return gas_type
+// A hook so areas can modify the incoming args
+/area/proc/PlaceOnTopReact(list/new_baseturfs, turf/fake_turf_type, flags)
+ return flags
+
+/area/proc/reg_in_areas_in_z()
+ if(!length(contents))
+ return
+
+ var/list/areas_in_z = SSmapping.areas_in_z
+ var/z
+ for(var/i in contents)
+ var/atom/thing = i
+ if(!thing)
+ continue
+ z = thing.z
+ break
+ if(!z)
+ WARNING("No z found for [src]")
+ return
+ if(!areas_in_z["[z]"])
+ areas_in_z["[z]"] = list()
+ areas_in_z["[z]"] += src
+
diff --git a/code/game/area/space_station_13_areas.dm b/code/game/area/space_station_13_areas.dm
index db342d09a708..a24bd14f43e8 100644
--- a/code/game/area/space_station_13_areas.dm
+++ b/code/game/area/space_station_13_areas.dm
@@ -13,23 +13,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
*/
-var/list/ghostteleportlocs = list()
-
-/proc/setupGhostTeleportLocs()
- for(var/area/AR in all_areas)
- if(ghostteleportlocs.Find(AR.name)) continue
- if(istype(AR, /area/tdome) || istype(AR, /area/adminlevel/bunker01/mainroom) || istype(AR, /area/adminlevel/ert_station))
- ghostteleportlocs += AR.name
- ghostteleportlocs[AR.name] = AR
- var/turf/picked = pick(get_area_turfs(AR.type))
- if (is_ground_level(picked.z) || is_mainship_level(picked.z) || is_loworbit_level(picked.z) || is_huntership_level(picked.z))
- ghostteleportlocs += AR.name
- ghostteleportlocs[AR.name] = AR
-
- ghostteleportlocs = sortAssoc(ghostteleportlocs)
-
- return 1
-
/*-----------------------------------------------------------------------------*/
/area/space
name = "\improper Space"
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 2f974641e5e7..e730f4f14b16 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -61,16 +61,6 @@
//we were deleted
return
- pass_flags = pass_flags_cache[type]
- if (isnull(pass_flags))
- pass_flags = new()
- initialize_pass_flags(pass_flags)
- pass_flags_cache[type] = pass_flags
- else
- initialize_pass_flags()
-
- Decorate()
-
/*
We actually care what this returns, since it can return different directives.
Not specifically here, but in other variations of this. As a general safety,
@@ -386,6 +376,17 @@ Parameters are passed from New.
CRASH("Warning: [src]([type]) initialized multiple times!")
flags_atom |= INITIALIZED
+ pass_flags = pass_flags_cache[type]
+ if (isnull(pass_flags))
+ pass_flags = new()
+ initialize_pass_flags(pass_flags)
+ pass_flags_cache[type] = pass_flags
+ else
+ initialize_pass_flags()
+
+ if(!mapload)
+ Decorate()
+
return INITIALIZE_HINT_NORMAL
//called if Initialize returns INITIALIZE_HINT_LATELOAD
@@ -396,9 +397,6 @@ Parameters are passed from New.
/atom/process()
return
-/atom/proc/Decorate()
- return
-
///---CLONE---///
/atom/clone
diff --git a/code/game/gamemodes/cm_initialize.dm b/code/game/gamemodes/cm_initialize.dm
index ec31142749d7..bb52d6060ac0 100644
--- a/code/game/gamemodes/cm_initialize.dm
+++ b/code/game/gamemodes/cm_initialize.dm
@@ -665,71 +665,12 @@ Additional game mode variables.
return survivor_non_event_transform(ghost.current, picked_spawn, is_synth)
/datum/game_mode/proc/survivor_old_equipment(var/mob/living/carbon/human/H, var/is_synth = FALSE)
- var/list/survivor_types
+ var/list/survivor_types = SSmapping.configs[GROUND_MAP].survivor_types
if(is_synth)
survivor_types = list(
"Survivor - Synthetic", //to be expanded later
)
- else
- switch(map_tag)
- if(MAP_PRISON_STATION)
- survivor_types = list(
- "Survivor - Scientist",
- "Survivor - Doctor",
- "Survivor - Corporate Liaison",
- "Survivor - Security",
- "Survivor - Prisoner",
- "Survivor - Prisoner",
- "Survivor - Gang Leader",
- "Survivor - Engineer"
- )
- if(MAP_LV_624,MAP_BIG_RED,MAP_DESERT_DAM,MAP_KUTJEVO)
- survivor_types = list(
- "Survivor - Scientist",
- "Survivor - Doctor",
- "Survivor - Chef",
- "Survivor - Chaplain",
- "Survivor - Miner",
- "Survivor - Engineer",
- "Survivor - Trucker",
- "Survivor - Colonial Marshall",
- )
- if(MAP_ICE_COLONY)
- survivor_types = list(
- "Survivor - Scientist",
- "Survivor - Doctor",
- "Survivor - Security",
- "Survivor - Trucker",
- "Survivor - Engineer"
- )
- if (MAP_SOROKYNE_STRATA)
- survivor_types = list(
- "Survivor - Scientist",
- "Survivor - Doctor",
- "Survivor - Security",
- "Survivor - Engineer"
- )
- if(MAP_CORSAT)
- survivor_types = list(
- "Survivor - Scientist",
- "Survivor - Scientist",
- "Survivor - Scientist",
- "Survivor - Doctor",
- "Survivor - Security",
- "Survivor - Corporate Liaison",
- "Survivor - Engineer"
- )
- else
- survivor_types = list(
- "Survivor - Scientist",
- "Survivor - Doctor",
- "Survivor - Chef",
- "Survivor - Chaplain",
- "Survivor - Miner",
- "Survivor - Colonial Marshall",
- "Survivor - Engineer"
- )
//Give them proper jobs and stuff here later
var/randjob = pick(survivor_types)
@@ -764,15 +705,7 @@ Additional game mode variables.
else
spawn(4)
to_chat(H, "You are a survivor!
")
- switch(map_tag)
- if(MAP_PRISON_STATION)
- to_chat(H, SPAN_NOTICE(" You are a survivor of the attack on Fiorina Orbital Penitentiary. You worked or lived on the prison station, and managed to avoid the alien attacks... until now."))
- if(MAP_CORSAT)
- to_chat(H, SPAN_NOTICE("You are a survivor of the containment breach on the Corporate Orbital Research Station for Advanced Technology (CORSAT). You worked or lived on the station, and managed to avoid the alien attacks... until now."))
- if(MAP_ICE_COLONY)
- to_chat(H, SPAN_NOTICE("You are a survivor of the attack on the ice habitat. You worked or lived on the colony, and managed to avoid the alien attacks... until now."))
- else
- to_chat(H, SPAN_NOTICE("You are a survivor of the attack on the colony. You worked or lived in the archaeology colony, and managed to avoid the alien attacks... until now."))
+ to_chat(H, SPAN_NOTICE(SSmapping.configs[GROUND_MAP].survivor_message))
to_chat(H, SPAN_NOTICE("You are fully aware of the xenomorph threat and are able to use this knowledge as you see fit."))
to_chat(H, SPAN_NOTICE("You are NOT aware of the marines or their intentions. "))
if(spawner.story_text)
@@ -797,15 +730,7 @@ Additional game mode variables.
new /datum/cm_objective/move_mob/almayer/survivor(H)
spawn(4)
to_chat(H, "You are a survivor!
")
- switch(map_tag)
- if(MAP_PRISON_STATION)
- to_chat(H, SPAN_NOTICE("You are a survivor of the attack on Fiorina Orbital Penitentiary. You worked or lived on the prison station, and managed to avoid the alien attacks.. until now."))
- if(MAP_CORSAT)
- to_chat(H, SPAN_NOTICE("You are a survivor of the containment breach on the Corporate Orbital Research Station for Advanced Technology (CORSAT). You worked or lived on the station, and managed to avoid the alien attacks... until now."))
- if(MAP_ICE_COLONY)
- to_chat(H, SPAN_NOTICE("You are a survivor of the attack on the ice habitat. You worked or lived on the colony, and managed to avoid the alien attacks.. until now."))
- else
- to_chat(H, SPAN_NOTICE("You are a survivor of the attack on the colony. You worked or lived in the archaeology colony, and managed to avoid the alien attacks...until now."))
+ to_chat(H, SPAN_NOTICE(SSmapping.configs[GROUND_MAP].survivor_message))
to_chat(H, SPAN_NOTICE("You are fully aware of the xenomorph threat and are able to use this knowledge as you see fit."))
to_chat(H, SPAN_NOTICE("You are NOT aware of the marines or their intentions."))
return 1
diff --git a/code/game/gamemodes/cm_process.dm b/code/game/gamemodes/cm_process.dm
index a6f6def098ad..a1f97a521e20 100644
--- a/code/game/gamemodes/cm_process.dm
+++ b/code/game/gamemodes/cm_process.dm
@@ -211,7 +211,7 @@ var/nextAdminBioscan = MINUTES_30//30 minutes in
var/atom/where = M
if (where == 0 && M.loc)
where = M.loc
- if(where.z in SSmapping.levels_by_any_trait(list(ZTRAIT_GROUND, ZTRAIT_LOWORBITT)))
+ if(where.z in SSmapping.levels_by_any_trait(list(ZTRAIT_GROUND, ZTRAIT_LOWORBIT)))
numXenosPlanet++
xenosPlanetLocations+=where
else if(is_mainship_level(where.z))
@@ -225,7 +225,7 @@ var/nextAdminBioscan = MINUTES_30//30 minutes in
var/atom/where = M
if (where == 0 && M.loc)
where = M.loc
- if(where.z in SSmapping.levels_by_any_trait(list(ZTRAIT_GROUND, ZTRAIT_LOWORBITT)))
+ if(where.z in SSmapping.levels_by_any_trait(list(ZTRAIT_GROUND, ZTRAIT_LOWORBIT)))
numHostsPlanet++
hostsPlanetLocations += where
else if(is_mainship_level(where.z))
@@ -308,7 +308,7 @@ Can't be in a locker, in space, in the thunderdome, or distress.
Only checks living mobs with a client attached.
*/
-/datum/game_mode/proc/count_xenos(list/z_levels = SSmapping.levels_by_any_trait(list(ZTRAIT_GROUND, ZTRAIT_LOWORBITT, ZTRAIT_MARINE_MAIN_SHIP)))
+/datum/game_mode/proc/count_xenos(list/z_levels = SSmapping.levels_by_any_trait(list(ZTRAIT_GROUND, ZTRAIT_LOWORBIT, ZTRAIT_MARINE_MAIN_SHIP)))
var/num_xenos = 0
for(var/i in GLOB.living_xeno_list)
var/mob/M = i
@@ -316,7 +316,7 @@ Only checks living mobs with a client attached.
num_xenos++
return num_xenos
-/datum/game_mode/proc/count_humans_and_xenos(list/z_levels = SSmapping.levels_by_any_trait(list(ZTRAIT_GROUND, ZTRAIT_LOWORBITT, ZTRAIT_MARINE_MAIN_SHIP)))
+/datum/game_mode/proc/count_humans_and_xenos(list/z_levels = SSmapping.levels_by_any_trait(list(ZTRAIT_GROUND, ZTRAIT_LOWORBIT, ZTRAIT_MARINE_MAIN_SHIP)))
var/num_humans = 0
var/num_xenos = 0
@@ -339,7 +339,7 @@ Only checks living mobs with a client attached.
return list(num_humans,num_xenos)
-/datum/game_mode/proc/count_marines_and_pmcs(list/z_levels = SSmapping.levels_by_any_trait(list(ZTRAIT_GROUND, ZTRAIT_LOWORBITT, ZTRAIT_MARINE_MAIN_SHIP)))
+/datum/game_mode/proc/count_marines_and_pmcs(list/z_levels = SSmapping.levels_by_any_trait(list(ZTRAIT_GROUND, ZTRAIT_LOWORBIT, ZTRAIT_MARINE_MAIN_SHIP)))
var/num_marines = 0
var/num_pmcs = 0
@@ -353,7 +353,7 @@ Only checks living mobs with a client attached.
return list(num_marines,num_pmcs)
-/datum/game_mode/proc/count_marines(list/z_levels = SSmapping.levels_by_any_trait(list(ZTRAIT_GROUND, ZTRAIT_LOWORBITT, ZTRAIT_MARINE_MAIN_SHIP)))
+/datum/game_mode/proc/count_marines(list/z_levels = SSmapping.levels_by_any_trait(list(ZTRAIT_GROUND, ZTRAIT_LOWORBIT, ZTRAIT_MARINE_MAIN_SHIP)))
var/num_marines = 0
for(var/i in GLOB.alive_human_list)
diff --git a/code/game/gamemodes/cm_self_destruct.dm b/code/game/gamemodes/cm_self_destruct.dm
index 8cafded6bbae..5997cd352408 100644
--- a/code/game/gamemodes/cm_self_destruct.dm
+++ b/code/game/gamemodes/cm_self_destruct.dm
@@ -78,10 +78,10 @@ var/global/datum/authority/branch/evacuation/EvacuationAuthority //This is initi
/datum/authority/branch/evacuation/proc/get_affected_zlevels() //This proc returns the ship's z level list (or whatever specified), when an evac/self destruct happens.
if(dest_status < NUKE_EXPLOSION_IN_PROGRESS && evac_status == EVACUATION_STATUS_COMPLETE) //Nuke is not in progress and evacuation finished, end the round on ship and low orbit (dropships in transit) only.
- . = SSmapping.levels_by_any_trait(list(ZTRAIT_MARINE_MAIN_SHIP, ZTRAIT_LOWORBITT))
+ . = SSmapping.levels_by_any_trait(list(ZTRAIT_MARINE_MAIN_SHIP, ZTRAIT_LOWORBIT))
else
if(SSticker.mode && SSticker.mode.is_in_endgame)
- . = SSmapping.levels_by_any_trait(list(ZTRAIT_MARINE_MAIN_SHIP, ZTRAIT_LOWORBITT))
+ . = SSmapping.levels_by_any_trait(list(ZTRAIT_MARINE_MAIN_SHIP, ZTRAIT_LOWORBIT))
//=========================================================================================
//=========================================================================================
diff --git a/code/game/gamemodes/colonialmarines/colonialmarines.dm b/code/game/gamemodes/colonialmarines/colonialmarines.dm
index a98497272d82..59da44d044db 100644
--- a/code/game/gamemodes/colonialmarines/colonialmarines.dm
+++ b/code/game/gamemodes/colonialmarines/colonialmarines.dm
@@ -16,7 +16,7 @@
return TRUE
/datum/game_mode/colonialmarines/announce()
- to_world("")
+ to_world("")
////////////////////////////////////////////////////////////////////////////////////////
//Temporary, until we sort this out properly.
@@ -63,19 +63,12 @@
QDEL_LIST(GLOB.good_items)
// Spawn gamemode-specific map items
- for(var/i in GLOB.map_items)
- var/turf/T = get_turf(i)
- qdel(i)
- switch(map_tag)
- if(MAP_LV_624) new /obj/item/map/lazarus_landing_map(T)
- if(MAP_ICE_COLONY) new /obj/item/map/ice_colony_map(T)
- if(MAP_BIG_RED) new /obj/item/map/big_red_map(T)
- if(MAP_PRISON_STATION) new /obj/item/map/FOP_map(T)
- if(MAP_DESERT_DAM) new /obj/item/map/desert_dam(T)
- if(MAP_WHISKEY_OUTPOST) new /obj/item/map/whiskey_outpost_map(T)
- if(MAP_SOROKYNE_STRATA) new /obj/item/map/sorokyne_map(T)
- if(MAP_CORSAT) new /obj/item/map/corsat(T)
- if(MAP_KUTJEVO) new /obj/item/map/kutjevo_map(T)
+ if(SSmapping.configs[GROUND_MAP].map_item_type)
+ var/type_to_spawn = SSmapping.configs[GROUND_MAP].map_item_type
+ for(var/i in GLOB.map_items)
+ var/turf/T = get_turf(i)
+ qdel(i)
+ new type_to_spawn(T)
if(!round_fog.len)
round_fog = null //No blockers?
@@ -125,25 +118,7 @@
if(!marines_assigned)
return
- switch(map_tag)
- if(MAP_LV_624)
- monkey_types = list(/mob/living/carbon/human/farwa, /mob/living/carbon/human/monkey, /mob/living/carbon/human/neaera, /mob/living/carbon/human/stok)
- if(MAP_ICE_COLONY)
- monkey_types = list(/mob/living/carbon/human/yiren)
- if(MAP_BIG_RED)
- monkey_types = list(/mob/living/carbon/human/neaera)
- if(MAP_KUTJEVO)
- monkey_types = list(/mob/living/carbon/human/neaera, /mob/living/carbon/human/stok)
- if(MAP_PRISON_STATION)
- monkey_types = list(/mob/living/carbon/human/monkey)
- if(MAP_DESERT_DAM)
- monkey_types = list(/mob/living/carbon/human/stok)
- if(MAP_SOROKYNE_STRATA)
- monkey_types = list(/mob/living/carbon/human/yiren)
- if(MAP_CORSAT)
- monkey_types = list(/mob/living/carbon/human/yiren, /mob/living/carbon/human/farwa, /mob/living/carbon/human/monkey, /mob/living/carbon/human/neaera, /mob/living/carbon/human/stok)
- else
- monkey_types = list(/mob/living/carbon/human/monkey) //make sure we always have a monkey type
+ monkey_types = SSmapping.configs[GROUND_MAP].monkey_types
if(!length(monkey_types))
return
@@ -161,23 +136,8 @@
shipwide_ai_announcement(input, name, 'sound/AI/ares_online.ogg')
/datum/game_mode/colonialmarines/proc/map_announcement()
- switch(map_tag)
- if(MAP_LV_624)
- marine_announcement("An automated distress signal has been received from archaeology site Lazarus Landing, on border world LV-624. A response team from the [MAIN_SHIP_NAME] will be dispatched shortly to investigate.", "[MAIN_SHIP_NAME]")
- if(MAP_ICE_COLONY)
- marine_announcement("An automated distress signal has been received from archaeology site \"Shiva's Snowball\", on border ice world \"Ifrit\". A response team from the [MAIN_SHIP_NAME] will be dispatched shortly to investigate.", "[MAIN_SHIP_NAME]")
- if(MAP_BIG_RED)
- marine_announcement("We've lost contact with the Weston-Yamada's research facility, [map_tag]. The [MAIN_SHIP_NAME] has been dispatched to assist.", "[MAIN_SHIP_NAME]")
- if(MAP_PRISON_STATION)
- marine_announcement("An automated distress signal has been received from maximum-security prison \"Fiorina Orbital Penitentiary\". A response team from the [MAIN_SHIP_NAME] will be dispatched shortly to investigate.", "[MAIN_SHIP_NAME]")
- if(MAP_DESERT_DAM)
- marine_announcement("We've lost contact with Weston-Yamada's extra-solar colony, \"[map_tag]\", on the planet \"Navarone.\" The [MAIN_SHIP_NAME] has been dispatched to assist.", "[MAIN_SHIP_NAME]")
- if (MAP_SOROKYNE_STRATA)
- marine_announcement("An automated distress signal has been recieved from a mining colony on border world LV-976, \"Sorokyne Outpost\". A response team from the [MAIN_SHIP_NAME] will be dispatched shortly to investigate.", "[MAIN_SHIP_NAME]")
- if (MAP_CORSAT)
- marine_announcement("An automated distress signal has been received from Weston-Yamada's Corporate Orbital Research Station for Advanced Technology, or CORSAT. The [MAIN_SHIP_NAME] has been dispatched to investigate.", "[MAIN_SHIP_NAME]")
- if (MAP_KUTJEVO)
- marine_announcement("An automated distress signal has been received from Weston-Yamada colony Kutjevo Refinery, known for botanical research, export, and raw materials processing and refinement. The [MAIN_SHIP_NAME] has been dispatched to investigate.", "[MAIN_SHIP_NAME]")
+ if(SSmapping.configs[GROUND_MAP].announce_text)
+ marine_announcement(SSmapping.configs[GROUND_MAP].announce_text, "[MAIN_SHIP_NAME]")
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
@@ -207,9 +167,9 @@
bioscan_current_interval += bioscan_ongoing_interval //Add to the interval based on our set interval time.
if(++round_checkwin >= 5) //Only check win conditions every 5 ticks.
- if(flags_round_type & MODE_FOG_ACTIVATED && map_tag == MAP_LV_624 && world.time >= (FOG_DELAY_INTERVAL + SSticker.round_start_time))
+ if(flags_round_type & MODE_FOG_ACTIVATED && SSmapping.configs[GROUND_MAP].environment_traits[ZTRAIT_FOG] && world.time >= (FOG_DELAY_INTERVAL + SSticker.round_start_time))
disperse_fog() //Some RNG thrown in.
- if(!(round_status_flags & ROUNDSTATUS_PODDOORS_OPEN) && (map_tag == MAP_CORSAT || map_tag == MAP_PRISON_STATION) && world.time >= (PODLOCKS_OPEN_WAIT + round_time_lobby))
+ if(!(round_status_flags & ROUNDSTATUS_PODDOORS_OPEN) && SSmapping.configs[GROUND_MAP].environment_traits[ZTRAIT_LOCKDOWN] && world.time >= (PODLOCKS_OPEN_WAIT + round_time_lobby))
round_status_flags |= ROUNDSTATUS_PODDOORS_OPEN
var/input = "Security lockdown will be lifting in 30 seconds per automated lockdown protocol."
diff --git a/code/game/gamemodes/colonialmarines/whiskey_outpost.dm b/code/game/gamemodes/colonialmarines/whiskey_outpost.dm
index 40d267f79e68..e49c4ad49a2e 100644
--- a/code/game/gamemodes/colonialmarines/whiskey_outpost.dm
+++ b/code/game/gamemodes/colonialmarines/whiskey_outpost.dm
@@ -2,7 +2,7 @@
//Global proc for checking if the game is whiskey outpost so I dont need to type if(gamemode == whiskey outpost) 50000 times
/proc/Check_WO()
- if(SSticker.mode == "Whiskey Outpost" || map_tag == "Whiskey Outpost" || master_mode == "Whiskey Outpost")
+ if(SSticker.mode == "Whiskey Outpost" || master_mode == "Whiskey Outpost")
return 1
return 0
@@ -71,6 +71,8 @@
var/list/whiskey_outpost_waves = list()
+ hardcore = TRUE
+
/datum/game_mode/whiskey_outpost/announce()
return 1
@@ -112,15 +114,15 @@
to_world("")
to_world(SPAN_ROUNDBODY("It is the year [game_year - 5] on the planet LV-624, five years before the arrival of the USS Almayer and the 7th 'Falling Falcons' Battalion in the sector"))
to_world(SPAN_ROUNDBODY("The 3rd 'Dust Raiders' Battalion is charged with establishing a USCM prescence in the Tychon's Rift sector"))
- to_world(SPAN_ROUNDBODY("[map_tag], one of the Dust Raider bases being established in the sector, has come under attack from unrecognized alien forces"))
- to_world(SPAN_ROUNDBODY("With casualties mounting and supplies running thin, the Dust Raiders at [map_tag] must survive for an hour to alert the rest of their battalion in the sector"))
+ to_world(SPAN_ROUNDBODY("[SSmapping.configs[GROUND_MAP].map_name], one of the Dust Raider bases being established in the sector, has come under attack from unrecognized alien forces"))
+ to_world(SPAN_ROUNDBODY("With casualties mounting and supplies running thin, the Dust Raiders at [SSmapping.configs[GROUND_MAP].map_name] must survive for an hour to alert the rest of their battalion in the sector"))
to_world(SPAN_ROUNDBODY("Hold out for as long as you can."))
world << sound('sound/effects/siren.ogg')
sleep(10)
switch(map_locale) //Switching it up.
if(0)
- marine_announcement("This is Captain Hans Naiche, commander of the 3rd Battalion 'Dust Raiders' forces here on LV-624. In our attempts to establish a base on this planet, several of our patrols were wiped out by hostile creatures. We're setting up a distress call, but we need you to hold [map_tag] in order for our engineers to set up the relay. We're prepping several M402 mortar units to provide fire support. If they overrun your positon, we will be wiped out with no way to call for help. Hold the line or we all die.", "Captain Naich, 3rd Battalion Command, LV-624 Garrison")
+ marine_announcement("This is Captain Hans Naiche, commander of the 3rd Battalion 'Dust Raiders' forces here on LV-624. In our attempts to establish a base on this planet, several of our patrols were wiped out by hostile creatures. We're setting up a distress call, but we need you to hold [SSmapping.configs[GROUND_MAP].map_name] in order for our engineers to set up the relay. We're prepping several M402 mortar units to provide fire support. If they overrun your positon, we will be wiped out with no way to call for help. Hold the line or we all die.", "Captain Naich, 3rd Battalion Command, LV-624 Garrison")
return ..()
@@ -565,7 +567,7 @@
to_chat(user, "Toss it to get supplies!")
return
- if(user.z != 1)
+ if(!is_ground_level(user.z))
to_chat(user, "You have to be on the ground to use this or it won't transmit.")
return
@@ -682,4 +684,4 @@
var/turf/T = get_turf(src)
if(T)
new /obj/item/paper/crumpled(T)
- qdel(src)
\ No newline at end of file
+ qdel(src)
diff --git a/code/game/gamemodes/colonialmarines/xenovsxeno.dm b/code/game/gamemodes/colonialmarines/xenovsxeno.dm
index ba232c1665cb..60a771ebe012 100644
--- a/code/game/gamemodes/colonialmarines/xenovsxeno.dm
+++ b/code/game/gamemodes/colonialmarines/xenovsxeno.dm
@@ -72,14 +72,14 @@
/* Pre-pre-startup */
/datum/game_mode/xenovs/can_start()
- setup_mapdata(map_tag)
+ setup_mapdata(SSmapping.configs[GROUND_MAP].map_name)
xeno_starting_num = readied_players
if(!initialize_starting_xenomorph_list(hives, TRUE))
return
return TRUE
/datum/game_mode/xenovs/announce()
- to_world("")
+ to_world("")
/* Pre-setup */
/datum/game_mode/xenovs/pre_setup()
@@ -210,7 +210,7 @@
round_checkwin = 0
-/datum/game_mode/xenovs/proc/get_xenos_hive(list/z_levels = SSmapping.levels_by_any_trait(list(ZTRAIT_GROUND, ZTRAIT_LOWORBITT, ZTRAIT_MARINE_MAIN_SHIP)))
+/datum/game_mode/xenovs/proc/get_xenos_hive(list/z_levels = SSmapping.levels_by_any_trait(list(ZTRAIT_GROUND, ZTRAIT_LOWORBIT, ZTRAIT_MARINE_MAIN_SHIP)))
var/list/list/hivenumbers = list()
for(var/datum/hive_status/H in GLOB.hive_datum)
hivenumbers += list(H.name = list())
@@ -292,7 +292,7 @@
log_game("Round end result: [round_finished]")
to_world("")
- to_world(SPAN_ROUNDBODY("Thus ends the story of the battling hives on [map_tag]. [round_finished]"))
+ to_world(SPAN_ROUNDBODY("Thus ends the story of the battling hives on [SSmapping.configs[GROUND_MAP].map_name]. [round_finished]"))
to_world(SPAN_ROUNDBODY("The game-mode was: [master_mode]!"))
to_world(SPAN_ROUNDBODY("End of Round Grief (EORG) is an IMMEDIATE 3 hour ban with no warnings, see rule #3 for more details."))
diff --git a/code/game/gamemodes/events/power_failure.dm b/code/game/gamemodes/events/power_failure.dm
index a2372c050b1b..4f8c652fea99 100644
--- a/code/game/gamemodes/events/power_failure.dm
+++ b/code/game/gamemodes/events/power_failure.dm
@@ -1,7 +1,9 @@
/proc/power_failure(var/announce = 1)
+ var/ship_zlevels = SSmapping.levels_by_trait(ZTRAIT_MARINE_MAIN_SHIP)
+
for(var/obj/structure/machinery/power/smes/S in machines)
- if(S.z != 3) // Ship only
+ if(!is_mainship_level(S.z))
continue
S.last_charge = S.charge
S.last_output = S.output
@@ -13,10 +15,10 @@
S.power_change()
for(var/obj/structure/machinery/power/apc/C in machines)
- if(C.cell && is_mainship_level(C.z))
+ if(!is_mainship_level(C.z) && C.cell)
C.cell.charge = 0
- playsound_z(SSmapping.levels_by_trait(ZTRAIT_MARINE_MAIN_SHIP), 'sound/effects/powerloss.ogg')
+ playsound_z(ship_zlevels, 'sound/effects/powerloss.ogg')
sleep(100)
if(announce)
@@ -24,7 +26,7 @@
/proc/power_restore(var/announce = 1)
for(var/obj/structure/machinery/power/smes/S in machines)
- if(S.z != 3)
+ if(!is_mainship_level(S.z))
continue
S.charge = S.capacity
S.output = S.output_level_max
@@ -43,7 +45,7 @@
/proc/power_restore_quick(var/announce = 1)
for(var/obj/structure/machinery/power/smes/S in machines)
- if(S.z != 3) // Ship only
+ if(!is_mainship_level(S.z)) // Ship only
continue
S.charge = S.capacity
S.output = S.output_level_max
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index e38905ed82bc..521084ce3ea7 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -32,6 +32,8 @@ var/global/cas_tracking_id_increment = 0 //this var used to assign unique tracki
var/datum/entity/round_stats/round_stats = null
var/list/roles_to_roll
+
+ var/hardcore = FALSE
/datum/game_mode/proc/announce() //to be calles when round starts
to_world("Notice: [src] did not define announce()")
@@ -98,7 +100,7 @@ var/global/cas_tracking_id_increment = 0 //this var used to assign unique tracki
log_game("Round end result: [round_finished]")
to_world("")
- to_world(SPAN_ROUNDBODY("Thus ends the story of the brave men and women of the [MAIN_SHIP_NAME] and their struggle on [map_tag]."))
+ to_world(SPAN_ROUNDBODY("Thus ends the story of the brave men and women of the [MAIN_SHIP_NAME] and their struggle on [SSmapping.configs[GROUND_MAP].map_name]."))
to_world(SPAN_ROUNDBODY("The game-mode was: [master_mode]!"))
to_world(SPAN_ROUNDBODY("End of Round Grief (EORG) is an IMMEDIATE 3 hour ban with no warnings, see rule #3 for more details."))
@@ -209,10 +211,6 @@ var/global/cas_tracking_id_increment = 0 //this var used to assign unique tracki
heads += player.mind
return heads
-/datum/game_mode/New()
- if(!map_tag)
- to_world("MT001: No mapping tag set, tell a coder. [map_tag]")
-
//////////////////////////
//Reports player logouts//
//////////////////////////
@@ -282,7 +280,7 @@ proc/display_roundstart_logout_report()
round_stats.name = operation_name
round_stats.real_time_start = world.realtime
var/datum/entity/map_stats/new_map = new()
- new_map.name = map_tag
+ new_map.name = SSmapping.configs[GROUND_MAP].map_name
new_map.linked_round = round_stats
new_map.death_stats_list = round_stats.death_stats_list
round_stats.game_mode = name
diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm
deleted file mode 100644
index 984384ffa070..000000000000
--- a/code/game/gamemodes/gameticker.dm
+++ /dev/null
@@ -1,311 +0,0 @@
-//var/global/datum/controller/gameticker/ticker = new()
-
-
-
-/datum/controller/gameticker
- var/const/restart_timeout = 600
- var/current_state = GAME_STATE_PREGAME
-
- var/hide_mode = FALSE
- var/datum/game_mode/mode = null
- var/post_game = FALSE
- var/event_time = null
- var/event = FALSE
-
- var/login_music // music played in pregame lobby
-
- var/list/datum/mind/minds = list()//The people in the game. Used for objective tracking.
-
- var/random_players = 0 // if set to nonzero, ALL players who latejoin or declare-ready join will have random appearances/genders
-
- var/pregame_timeleft = 0
- var/toweractive = FALSE
- var/delay_end = FALSE //if set to nonzero, the round will not restart on it's own
- var/automatic_delay_end = FALSE
-
- var/round_end_announced = FALSE // Spam Prevention. Announce round end only once.
- var/datum/mind/liaison = null
-
-/datum/controller/gameticker/proc/pregame()
- login_music = pick(
- "sound/music/1.ogg",
- "sound/music/2.ogg",
- "sound/music/3.ogg",
- "sound/music/4.ogg",
- "sound/music/5.ogg",
- "sound/music/6.ogg")
- do
- pregame_timeleft = PREROUND_TIME
- if(round_statistics)
- to_world("[SPAN_BLUE("[round_statistics.name]")]")
- to_world(SPAN_NOTICE("Welcome to the pre-game lobby of Colonial Marines!"))
- to_world(SPAN_NOTICE("Please, setup your character and select ready. Game will start in [pregame_timeleft] seconds."))
- while(current_state == GAME_STATE_PREGAME)
- for(var/i=0, i<10, i++)
- sleep(1)
- vote.process()
- if(going)
- pregame_timeleft--
- if(pregame_timeleft == CONFIG_GET(number/vote_autogamemode_timeleft))
- if(!vote.time_remaining)
- vote.autogamemode() //Quit calling this over and over and over and over.
- while(vote.time_remaining)
- for(var/i=0, i<10, i++)
- sleep(1)
- vote.process()
- if(pregame_timeleft <= 0)
- current_state = GAME_STATE_SETTING_UP
- while (!setup())
-
-
-/datum/controller/gameticker/proc/setup()
- //Create and announce mode
- if(master_mode=="secret")
- hide_mode = 1
- var/list/datum/game_mode/runnable_modes
- if((master_mode=="random") || (master_mode=="secret"))
- //runnable_modes = config.get_runnable_modes()
- if (runnable_modes.len==0)
- current_state = GAME_STATE_PREGAME
- to_world("Unable to choose playable game mode. Reverting to pre-game lobby.")
- return 0
- if(secret_force_mode != "secret")
- var/datum/game_mode/M = config.pick_mode(secret_force_mode)
- if(M.can_start())
- mode = config.pick_mode(secret_force_mode)
- RoleAuthority.reset_roles()
- if(!mode)
- mode = pickweight(runnable_modes)
- if(mode)
- var/mtype = src.mode.type
- mode = new mtype
- else
- if(map_tag == MAP_WHISKEY_OUTPOST)
- mode = config.pick_mode("Whiskey Outpost")
- RoleAuthority.replace_jobs(src.mode.roles_for_mode)
- else
- mode = config.pick_mode(master_mode)
- if (!mode.can_start())
- to_world("Unable to start [mode.name]. Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby.")
- QDEL_NULL(mode)
- current_state = GAME_STATE_PREGAME
- RoleAuthority.reset_roles()
- return 0
-
- var/can_continue = src.mode.pre_setup()//Setup special modes
- if(!can_continue)
- QDEL_NULL(mode)
- current_state = GAME_STATE_PREGAME
- to_world("Error setting up [master_mode]. Reverting to pre-game lobby.")
- RoleAuthority.reset_roles()
- return 0
-
- if(hide_mode)
- var/list/modes = new
- for (var/datum/game_mode/M in runnable_modes)
- modes+=M.name
- modes = sortList(modes)
- to_world("The current game mode is - Secret!")
- to_world("Possibilities: [english_list(modes)]")
- else
- src.mode.announce()
-
- //Configure mode and assign player to special mode stuff
- if (!(mode.flags_round_type & MODE_NO_SPAWN))
- if(mode.flags_round_type & MODE_NEW_SPAWN)
- var/roles_to_roll = null
- if(length(mode.roles_to_roll))
- roles_to_roll = mode.roles_to_roll
- RoleAuthority.setup_candidates_and_roles(roles_to_roll) //Distribute jobs
- create_characters() // Create and equip characters
- else
- var/roles_to_roll = null
- if(length(mode.roles_to_roll))
- roles_to_roll = mode.roles_to_roll
- RoleAuthority.setup_candidates_and_roles(roles_to_roll) //Distribute jobs
- old_create_characters() //Create player characters and transfer them
- equip_characters()
-
- collect_minds()
- GLOB.data_core.manifest()
-
- spawn(2)
- mode.initialize_emergency_calls()
-
- current_state = GAME_STATE_PLAYING
-
- for(var/mob/new_player/np in GLOB.new_player_list)
- np.new_player_panel_proc(TRUE)
-
- run_mapdaemon_batch()
- begin_game_recording()
-
- if((master_mode == "Distress Signal") && SSevents)
- SSevents.Initialize()
-
- //here to initialize the random events nicely at round start
- setup_economy()
-
- shuttle_controller.setup_shuttle_docks()
-
- spawn(0)//Forking here so we dont have to wait for this to finish
- mode.post_setup()
- //Cleanup some stuff
- if(round_statistics)
- to_world(SPAN_BLUE("Welcome to [round_statistics.name]"))
- to_world(SPAN_BLUE("Enjoy the game!"))
-
- if(CONFIG_GET(flag/autooocmute))
- to_world(SPAN_DANGER("The OOC channel has been globally disabled due to round start!"))
- ooc_allowed = !( ooc_allowed )
-
- supply_controller.process() //Start the supply shuttle regenerating points -- TLE
-
- Master.SetRunLevel(RUNLEVEL_GAME)
-
- spawn(MINUTES_5)
- for(var/i in GLOB.closet_list) //Set up special equipment for lockers and vendors, depending on gamemode
- var/obj/structure/closet/C = i
- C.select_gamemode_equipment(mode.type)
- for(var/obj/structure/machinery/vending/V in machines)
- V.select_gamemode_equipment(mode.type)
-
- return 1
-
-/datum/controller/gameticker/proc/create_characters()
- if(!RoleAuthority)
- return
-
- for(var/mob/new_player/player in GLOB.player_list)
- if(!player || !player.ready || !player.mind || !player.job)
- continue
-
- INVOKE_ASYNC(src, .proc/spawn_and_equip_char, player)
-
-/datum/controller/gameticker/proc/spawn_and_equip_char(var/mob/new_player/player)
- var/datum/job/J = RoleAuthority.roles_for_mode[player.job]
- var/mob/M = J.spawn_in_player(player)
- if(istype(M))
- J.equip_job(M)
- EquipCustomItems(M)
-
- if(M.client)
- var/client/C = M.client
- if(C.player_data && C.player_data.playtime_loaded && length(C.player_data.playtimes) == 0)
- msg_admin_niche("NEW PLAYER: [key_name(player, 1, 1, 0)] (?). IP: [player.lastKnownIP], CID: [player.computer_id]")
-
- QDEL_IN(player, 5)
-
-/datum/controller/gameticker/proc/old_create_characters()
- for(var/mob/new_player/player in GLOB.player_list)
- if(!(player && player.ready && player.mind))
- continue
-
- if(!player.job && !player.mind.roundstart_picked)
- continue
-
- player.create_character()
- qdel(player)
-
-/datum/controller/gameticker/proc/collect_minds()
- for(var/mob/living/player in GLOB.alive_mob_list)
- if(player.mind)
- SSticker.minds += player.mind
-
-/datum/controller/gameticker/proc/equip_characters()
- var/captainless=1
- if(mode && istype(mode,/datum/game_mode/huntergames)) // || istype(mode,/datum/game_mode/whiskey_outpost)
- return
-
- for(var/mob/living/carbon/human/player in GLOB.human_mob_list)
- if(player.mind)
- if(player.job == "Commanding Officers")
- captainless = FALSE
- if(player.job)
- RoleAuthority.equip_role(player, RoleAuthority.roles_by_name[player.job])
- EquipCustomItems(player)
- if(player.client)
- var/client/C = player.client
- if(C.player_data && C.player_data.playtime_loaded && length(C.player_data.playtimes) == 0)
- msg_admin_niche("NEW PLAYER: [key_name(player, 1, 1, 0)] (?). IP: [player.lastKnownIP], CID: [player.computer_id]")
- if(captainless)
- for(var/mob/M in GLOB.player_list)
- if(!istype(M,/mob/new_player))
- to_chat(M, "Marine commanding officer position not forced on anyone.")
-
-/datum/controller/gameticker/process()
- if(current_state != GAME_STATE_PLAYING)
- return 0
-
- mode.process()
-
- var/game_finished = 0
- var/mode_finished = 0
- if (CONFIG_GET(flag/continous_rounds))
- if(EvacuationAuthority.dest_status == NUKE_EXPLOSION_FINISHED || EvacuationAuthority.dest_status == NUKE_EXPLOSION_GROUND_FINISHED) game_finished = 1
- mode_finished = (!post_game && mode.check_finished())
- else
- game_finished = (mode.check_finished() /* || (emergency_shuttle.returned() && emergency_shuttle.evac == 1)*/)
- mode_finished = game_finished
-
- if(!EvacuationAuthority.dest_status != NUKE_EXPLOSION_IN_PROGRESS && game_finished && (mode_finished || post_game))
- current_state = GAME_STATE_FINISHED
-
- spawn(1)
- declare_completion()
-
- spawn(50)
- end_game_recording()
-
- if (EvacuationAuthority.dest_status == NUKE_EXPLOSION_FINISHED || EvacuationAuthority.dest_status == NUKE_EXPLOSION_GROUND_FINISHED)
- log_game("Round ended by nuke")
- else
- log_game("Round ended by proper completion")
-
- if(CONFIG_GET(flag/autooocmute) && !ooc_allowed)
- to_world(SPAN_DANGER("The OOC channel has been globally enabled due to round end!"))
- ooc_allowed = 1
-
- if(!delay_end && !automatic_delay_end)
- sleep(restart_timeout)
- if(!delay_end && !automatic_delay_end)
- world.Reboot()
- else
- to_world({"
- [SPAN_CENTERBOLD("An admin has delayed the round end.")]
-
- "})
- else
- to_world({"
- [SPAN_CENTERBOLD("An admin has delayed the round end.")]
-
- "})
-
- else if (mode_finished)
- post_game = TRUE
-
- mode.cleanup()
-
- //call a transfer shuttle vote
- spawn(50)
- if(!round_end_announced) // Spam Prevention. Now it should announce only once.
- to_world(SPAN_WARNING("The round has ended!"))
- round_end_announced = TRUE
-
- return 1
-
-/datum/controller/gameticker/proc/calculate_end_statistics()
- mode.calculate_end_statistics()
-
-/datum/controller/gameticker/proc/declare_completion()
- mode.declare_completion()//To declare normal completion.
-
- //calls auto_declare_completion_* for all modes
- for(var/handler in typesof(/datum/game_mode/proc))
- if (findtext("[handler]","auto_declare_completion_"))
- call(mode, handler)()
-
- return 1
-
-/world/proc/has_round_started()
- return SSticker.current_state >= GAME_STATE_PLAYING
diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm
index 0e33052b4f5a..335bf8193db7 100644
--- a/code/game/jobs/access.dm
+++ b/code/game/jobs/access.dm
@@ -46,26 +46,29 @@
/obj/proc/check_access(obj/item/I)
//These generations have been moved out of /obj/New() because they were slowing down the creation of objects that never even used the access system.
gen_access()
- var/i
if(!islist(req_access)) return 1//something's very wrong
var/L[] = req_access
if(!L.len && (!req_one_access || !req_one_access.len)) return 1//no requirements
if(!I) return
- var/A[] = I.GetAccess()
- for(i in req_access)
- if(!(i in A)) return//doesn't have this access
+ var/list/A = I.GetAccess()
+ for(var/i in req_access)
+ if(!(i in A))
+ return FALSE//doesn't have this access
if(req_one_access && req_one_access.len)
- for(i in req_one_access)
- if(i in A) return 1//has an access from the single access list
- return
- return 1
+ for(var/i in req_one_access)
+ if(i in A)
+ return TRUE//has an access from the single access list
+ return FALSE
+ return TRUE
/obj/proc/check_access_list(L[])
gen_access()
if(!req_access && !req_one_access) return 1
if(!islist(req_access)) return 1
+ if(!req_access.len && !islist(req_one_access))
+ return TRUE
if(!req_access.len && (!req_one_access || !req_one_access.len)) return 1
if(!islist(L)) return
var/i
diff --git a/code/game/jobs/job/civilians/other/survivors.dm b/code/game/jobs/job/civilians/other/survivors.dm
index 84092e545cec..d49047b42620 100644
--- a/code/game/jobs/job/civilians/other/survivors.dm
+++ b/code/game/jobs/job/civilians/other/survivors.dm
@@ -47,15 +47,7 @@
to_chat(H, line)
else
to_chat(H, "You are a survivor!
")
- switch(map_tag)
- if(MAP_PRISON_STATION)
- to_chat(H, SPAN_NOTICE(" You are a survivor of the attack on Fiorina Orbital Penitentiary. You worked or lived on the prison station, and managed to avoid the alien attacks... until now."))
- if(MAP_CORSAT)
- to_chat(H, SPAN_NOTICE("You are a survivor of the containment breach on the Corporate Orbital Research Station for Advanced Technology (CORSAT). You worked or lived on the station, and managed to avoid the alien attacks... until now."))
- if(MAP_ICE_COLONY)
- to_chat(H, SPAN_NOTICE("You are a survivor of the attack on the ice habitat. You worked or lived on the colony, and managed to avoid the alien attacks... until now."))
- else
- to_chat(H, SPAN_NOTICE("You are a survivor of the attack on the colony. You worked or lived in the archaeology colony, and managed to avoid the alien attacks... until now."))
+ to_chat(H, SPAN_NOTICE(SSmapping.configs[GROUND_MAP].survivor_message))
to_chat(H, SPAN_NOTICE("You are fully aware of the xenomorph threat and are able to use this knowledge as you see fit."))
to_chat(H, SPAN_NOTICE("You are NOT aware of the marines or their intentions. "))
@@ -104,66 +96,7 @@
return TRUE
/datum/job/civilian/survivor/proc/survivor_old_equipment(var/mob/living/carbon/human/H)
- var/list/survivor_types
- switch(map_tag)
- if(MAP_PRISON_STATION)
- survivor_types = list(
- "Survivor - Scientist",
- "Survivor - Doctor",
- "Survivor - Corporate Liaison",
- "Survivor - Security",
- "Survivor - Prisoner",
- "Survivor - Prisoner",
- "Survivor - Gang Leader",
- "Survivor - Engineer"
- )
- if(MAP_LV_624, MAP_BIG_RED,MAP_DESERT_DAM, MAP_KUTJEVO)
- survivor_types = list(
- "Survivor - Scientist",
- "Survivor - Doctor",
- "Survivor - Chef",
- "Survivor - Chaplain",
- "Survivor - Miner",
- "Survivor - Engineer",
- "Survivor - Trucker",
- "Survivor - Colonial Marshall",
- )
- if(MAP_ICE_COLONY)
- survivor_types = list(
- "Survivor - Scientist",
- "Survivor - Doctor",
- "Survivor - Security",
- "Survivor - Trucker",
- "Survivor - Engineer"
- )
- if (MAP_SOROKYNE_STRATA)
- survivor_types = list(
- "Survivor - Scientist",
- "Survivor - Doctor",
- "Survivor - Security",
- "Survivor - Engineer"
- )
- if(MAP_CORSAT)
- survivor_types = list(
- "Survivor - Scientist",
- "Survivor - Scientist",
- "Survivor - Scientist",
- "Survivor - Doctor",
- "Survivor - Security",
- "Survivor - Corporate Liaison",
- "Survivor - Engineer"
- )
- else
- survivor_types = list(
- "Survivor - Scientist",
- "Survivor - Doctor",
- "Survivor - Chef",
- "Survivor - Chaplain",
- "Survivor - Miner",
- "Survivor - Colonial Marshall",
- "Survivor - Engineer"
- )
-
+ var/list/survivor_types = SSmapping.configs[GROUND_MAP].survivor_types
arm_equipment(H, pick(survivor_types), FALSE, TRUE)
/datum/job/civilian/survivor/synth
diff --git a/code/game/jobs/job/command/auxiliary/senior.dm b/code/game/jobs/job/command/auxiliary/senior.dm
index 0d0504b0aeb3..d83bd927208e 100644
--- a/code/game/jobs/job/command/auxiliary/senior.dm
+++ b/code/game/jobs/job/command/auxiliary/senior.dm
@@ -9,7 +9,7 @@
return ..()
/datum/job/command/senior/announce_entry_message(mob/living/carbon/human/H)
- if(flags_startup_parameters & ROLE_ADD_TO_MODE && map_tag != MAP_WHISKEY_OUTPOST)
+ if(flags_startup_parameters & ROLE_ADD_TO_MODE && SSmapping.configs[GROUND_MAP].map_name != MAP_WHISKEY_OUTPOST)
addtimer(CALLBACK(GLOBAL_PROC, .proc/ai_announcement, "Attention all hands, [H.get_paygrade(0)] [H.real_name] on deck!"), 1.5 SECONDS)
..()
diff --git a/code/game/jobs/job/command/cic/captain.dm b/code/game/jobs/job/command/cic/captain.dm
index 209076456ad6..e6bfdaac88aa 100644
--- a/code/game/jobs/job/command/cic/captain.dm
+++ b/code/game/jobs/job/command/cic/captain.dm
@@ -32,7 +32,7 @@
return ..()
/datum/job/command/commander/announce_entry_message(mob/living/carbon/human/H)
- if(flags_startup_parameters & ROLE_ADD_TO_MODE && map_tag != MAP_WHISKEY_OUTPOST)
+ if(flags_startup_parameters & ROLE_ADD_TO_MODE && SSmapping.configs[GROUND_MAP].map_name != MAP_WHISKEY_OUTPOST)
addtimer(CALLBACK(src, .proc/do_announce_entry_message, H), 1.5 SECONDS)
..()
diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm
index d6099193ac85..ca7c74bed6af 100644
--- a/code/game/machinery/OpTable.dm
+++ b/code/game/machinery/OpTable.dm
@@ -25,8 +25,8 @@
var/obj/structure/machinery/computer/operating/computer = null
-/obj/structure/machinery/optable/New()
- ..()
+/obj/structure/machinery/optable/Initialize()
+ . = ..()
for(dir in list(NORTH,EAST,SOUTH,WEST))
computer = locate(/obj/structure/machinery/computer/operating, get_step(src, dir))
if (computer)
diff --git a/code/game/machinery/air_alarm.dm b/code/game/machinery/air_alarm.dm
index ad7da7cc760c..f4c736ae1380 100644
--- a/code/game/machinery/air_alarm.dm
+++ b/code/game/machinery/air_alarm.dm
@@ -108,8 +108,8 @@
-/obj/structure/machinery/alarm/New(var/loc, var/direction, var/building = 0)
- ..()
+/obj/structure/machinery/alarm/Initialize(mapload, var/direction, var/building = 0)
+ . = ..()
if(building)
if(loc)
diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm
index 77b03b530f68..4fd658b81998 100644
--- a/code/game/machinery/camera/presets.dm
+++ b/code/game/machinery/camera/presets.dm
@@ -31,12 +31,13 @@
unslashable = TRUE
unacidable = TRUE
- New(loc, laser_name)
- ..()
- if(!c_tag && laser_name)
- var/area/A = get_area(src)
- c_tag = "[laser_name] ([A.name])"
+/obj/structure/machinery/camera/laser_cam/Initialize(mapload, laser_name)
+ . = ..()
+ if(!c_tag && laser_name)
+ var/area/A = get_area(src)
+ c_tag = "[laser_name] ([A.name])"
+/obj/structure/machinery/camera/laser_cam
emp_act(severity)
return //immune to EMPs, just in case
@@ -46,8 +47,8 @@
// ALL UPGRADES
-/obj/structure/machinery/camera/all/New()
- ..()
+/obj/structure/machinery/camera/all/Initialize(mapload, ...)
+ . = ..()
upgradeEmpProof()
upgradeXRay()
upgradeMotion()
@@ -72,19 +73,18 @@
var/number = 0 //camera number in area
//This camera type automatically sets it's name to whatever the area that it's in is called.
-/obj/structure/machinery/camera/autoname/New()
- ..()
- spawn(10)
- number = 1
- var/area/A = get_area(src)
- if(A)
- for(var/obj/structure/machinery/camera/autoname/C in machines)
- if(C == src) continue
- var/area/CA = get_area(C)
- if(CA.type == A.type)
- if(C.number)
- number = max(number, C.number+1)
- c_tag = "[A.name] #[number]"
+/obj/structure/machinery/camera/autoname/Initialize(mapload, ...)
+ . = ..()
+ number = 1
+ var/area/A = get_area(src)
+ if(A)
+ for(var/obj/structure/machinery/camera/autoname/C in machines)
+ if(C == src) continue
+ var/area/CA = get_area(C)
+ if(CA.type == A.type)
+ if(C.number)
+ number = max(number, C.number+1)
+ c_tag = "[A.name] #[number]"
//cameras installed inside the dropships, accessible via both cockpit monitor and Almayer camera computers
/obj/structure/machinery/camera/autoname/almayer/dropship_one
@@ -102,7 +102,7 @@
unslashable = TRUE
unacidable = TRUE
network = list("almayer", "containment")
-
+
/obj/structure/machinery/camera/autoname/almayer/containment/attack_alien(mob/living/carbon/Xenomorph/M)
return
@@ -182,4 +182,4 @@
network = list("security_cameras")
/obj/structure/machinery/camera/autoname/dam/medical_cameras
- network = list("medical_cameras")
\ No newline at end of file
+ network = list("medical_cameras")
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index 250c88c8b7a5..96234652c8a7 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -9,8 +9,8 @@
//Disk stuff.
-/obj/item/disk/data/New()
- ..()
+/obj/item/disk/data/Initialize()
+ . = ..()
var/diskcolor = pick(0,1,2)
src.icon_state = "datadisk[diskcolor]"
@@ -49,8 +49,8 @@
name = "Diskette Box"
icon_state = "disk_kit"
-/obj/item/storage/box/disks/New()
- ..()
+/obj/item/storage/box/disks/Initialize()
+ . = ..()
new /obj/item/disk/data(src)
new /obj/item/disk/data(src)
new /obj/item/disk/data(src)
diff --git a/code/game/machinery/computer/area_air_control.dm b/code/game/machinery/computer/area_air_control.dm
index a841d4f0a2f3..ee0caf97f4c0 100644
--- a/code/game/machinery/computer/area_air_control.dm
+++ b/code/game/machinery/computer/area_air_control.dm
@@ -175,4 +175,4 @@
if(!found)
status = "ERROR: No scrubber found!"
- src.updateUsrDialog()
\ No newline at end of file
+ src.updateUsrDialog()
diff --git a/code/game/machinery/computer/camera_console.dm b/code/game/machinery/computer/camera_console.dm
index 52fcd375018d..5f8fa74b796d 100644
--- a/code/game/machinery/computer/camera_console.dm
+++ b/code/game/machinery/computer/camera_console.dm
@@ -46,8 +46,8 @@
return attack_hand(user)
/obj/structure/machinery/computer/security/attack_hand(mob/user)
- if(z > 6)
- to_chat(user, SPAN_DANGER("Unable to establish a connection: \black You're too far away from the station!"))
+ if(is_admin_level(z))
+ to_chat(user, SPAN_DANGER("Unable to establish a connection: \black You're too far away from the ship!"))
return
if(inoperable())
return
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index 5d5324065df4..0f170df56c66 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -13,8 +13,8 @@
var/processing = FALSE //Set to true if computer needs to do /process()
var/exproof = 0
-/obj/structure/machinery/computer/New()
- ..()
+/obj/structure/machinery/computer/Initialize()
+ . = ..()
if(processing)
start_processing()
diff --git a/code/game/machinery/computer/emails.dm b/code/game/machinery/computer/emails.dm
index 67abb8b006e2..fe895788366e 100644
--- a/code/game/machinery/computer/emails.dm
+++ b/code/game/machinery/computer/emails.dm
@@ -12,8 +12,8 @@
var/selected_mail
-/obj/structure/machinery/computer/emails/New()
- ..()
+/obj/structure/machinery/computer/emails/Initialize()
+ . = ..()
email_list = list()
var/list/L = typesof(email_type) - email_type
var/email_amt = rand(2,4)
diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm
index 0684e0f2211e..96973a86cc5c 100644
--- a/code/game/machinery/cryo.dm
+++ b/code/game/machinery/cryo.dm
@@ -18,8 +18,8 @@
var/mob/living/carbon/occupant = null
var/obj/item/reagent_container/glass/beaker = null
-/obj/structure/machinery/cryo_cell/New()
- ..()
+/obj/structure/machinery/cryo_cell/Initialize()
+ . = ..()
start_processing()
/obj/structure/machinery/cryo_cell/process()
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index 4957285ed57f..70b3b21720a8 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -146,13 +146,12 @@ GLOBAL_LIST_INIT(frozen_items, list(SQUAD_NAME_1 = list(), SQUAD_NAME_2 = list()
orient_right = 1
icon_state = "cryo_rear-r"
-/obj/structure/cryofeed/New()
-
+/obj/structure/cryofeed/Initialize()
+ . = ..()
if(orient_right)
icon_state = "cryo_rear-r"
else
icon_state = "cryo_rear"
- ..()
diff --git a/code/game/machinery/door_display/door_display.dm b/code/game/machinery/door_display/door_display.dm
index 1cddfdf51e0c..a88553ff83cb 100644
--- a/code/game/machinery/door_display/door_display.dm
+++ b/code/game/machinery/door_display/door_display.dm
@@ -21,9 +21,13 @@
maptext_height = 26
maptext_width = 32
-/obj/structure/machinery/door_display/New()
- ..()
- addtimer(CALLBACK(src, .proc/get_targets))
+/obj/structure/machinery/door_display/Initialize()
+ . = ..()
+ return INITIALIZE_HINT_LATELOAD
+
+/obj/structure/machinery/door_display/LateInitialize()
+ . = ..()
+ get_targets()
/obj/structure/machinery/door_display/proc/get_targets()
for(var/obj/structure/machinery/door/D in machines)
@@ -249,7 +253,7 @@
//Room Divider
if(has_wall_divider)
data += "
Containment Divider
"
-
+
data += "
Close Display"
data += "