Unit Test rework & Master/Ticker update (#17912)

* Unit Test rework & Master/Ticker update

* Fixes and working unit testing

* Fixes

* Test fixes and FA update

* Fixed runtimes

* Radio subsystem

* move that glob wherever later

* ident

* CIBUILDING compile option

* Fixed runtimes

* Some changes to the workflow

* CI Split

* More split

* Pathing

* Linters and Annotators

* ci dir fix

* Missing undef fixed

* Enable grep checks

* More test conversions

* More split

* Correct file

* Removes unneeded inputs

* oop

* More dependency changes

* More conversions

* Conversion fixes

* Fixes

* Some assert fixes

* Corrects start gate

* Converted some README.dms to README.mds

* Removes duplicate proc

* Removes unused defines

* Example configs

* fix dll access viol by double calling

* Post-rebase fixes

* Cleans up names global list

* Undef restart counter

* More code/game/ cleanup

* Statpanel update

* Skybox

* add

* Fix ticker

* Roundend fix

* Persistence dependency update

* Reordering

* Reordering

* Reordering

* Initstage fix

* .

* .

* Reorder

* Reorder

* Circle

* Mobs

* Air

* Test fix

* CI Script Fix

* Configs

* More ticker stuff

* This is now in 'reboot world'

* Restart world announcements

* no glob in PreInit

* to define

* Update

* Removed old include

* Make this file normal again

* moved

* test

* shared unit testing objects

* Updates batched_spritesheets and universal_icon

* .

* job data debug

* rm that

* init order

* show us

* .

* i wonder

* .

* .

* urg

* do we not have a job ID?

* .

* rm sleep for now

* updated rust-g linux binaries

* binaries update 2

* binaries update 3

* testing something

* change that

* test something

* .

* .

* .

* locavar

* test

* move that

* .

* debug

* don't run this test

* strack trace it

* cleaner

* .

* .

* cras again

* also comment this out

* return to official rust g

* Update robot_icons.dm

* monitor the generation

* .

---------

Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
Selis
2025-08-10 01:37:23 +02:00
committed by GitHub
co-authored by Kashargul
parent 5e54e17ebd
commit f4bf017921
382 changed files with 10193 additions and 4421 deletions
+42 -163
View File
@@ -1,178 +1,57 @@
name: CI
name: CI Suite
on:
pull_request:
branches:
- master
- "project/**"
merge_group:
branches:
- master
env:
BASENAME: "vorestation"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
start_gate:
if: ( !contains(github.event.head_commit.message, '[ci skip]') )
name: Start Gate
runs-on: ubuntu-24.04
steps:
- name: Mandatory Empty Step
run: exit 0
run_linters:
if: ( !contains(github.event.head_commit.message, '[ci skip]') )
name: Run Linters
runs-on: ubuntu-24.04
concurrency:
group: run_linters-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
# Caches
- name: Setup Bun
uses: ./.github/actions/setup_bun
- name: Restore Bootstrap cache
uses: actions/cache@v4
with:
path: tools/bootstrap/.cache
key: ${{ runner.os }}-bootstrap-${{ hashFiles('tools/requirements.txt') }}
restore-keys: |
${{ runner.os }}-bootstrap-
- name: Restore Rust cache
uses: actions/cache@v4
with:
path: ~/.cargo
key: ${{ runner.os }}-rust-${{ hashFiles('tools/ci/ci_dependencies.sh')}}
restore-keys: |
${{ runner.os }}-rust-
- name: Restore Cutter cache
uses: actions/cache@v4
with:
path: tools/icon_cutter/cache
key: ${{ runner.os }}-cutter-${{ hashFiles('dependencies.sh') }}
# End Caches
- name: Install Tools
run: |
pip3 install setuptools
bash tools/ci/install_ripgrep.sh
bash tools/ci/install_spaceman_dmm.sh dmm-tools
tools/bootstrap/python -c ''
- name: Run Validation Tests
run: bash tools/ci/validate_files.sh
- name: Run Define Sanity Checks
run: tools/bootstrap/python -m define_sanity.check
- name: Run DMI Tests
run: tools/bootstrap/python -m dmi.test
- name: Run Map Checks
run: |
tools/bootstrap/python -m tools.maplint.source
tools/bootstrap/python -m mapmerge2.dmm_test
- name: Run TGUI Checks
run: tools/build/build.sh --ci lint tgui-test
- name: Run Nanomap Checks
run: tools/github-actions/nanomap-renderer-invoker.sh --testing
needs: start_gate
uses: ./.github/workflows/run_linters.yml
dreamchecker:
if: ( !contains(github.event.head_commit.message, '[ci skip]') )
name: DreamChecker
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Restore SpacemanDMM Cache
uses: actions/cache@v4
with:
path: ~/SpacemanDMM
key: ${{ runner.os }}-dreamchecker-${{ hashFiles('dependencies.sh')}}
restore-keys: ${{ runner.os }}-dreamchecker
- name: Install Dependencies
run: |
tools/ci/install_spaceman_dmm.sh dreamchecker
- name: Run Linter
id: linter
run: |
~/dreamchecker > ${GITHUB_WORKSPACE}/output-annotations.txt 2>&1
- name: Annotate Linter
uses: yogstation13/DreamAnnotate@v2
if: always()
with:
outputFile: output-annotations.txt
odlint:
name: Lint with OpenDream
runs-on: ubuntu-22.04
steps:
- uses: actions/setup-dotnet@v4
with:
dotnet-version: 9
- uses: actions/checkout@v4
- uses: robinraju/release-downloader@v1.12
with:
repository: "OpenDreamProject/OpenDream"
tag: "latest"
fileName: "DMCompiler_linux-x64.tar.gz"
extract: true
- run: ./DMCompiler_linux-x64/DMCompiler --suppress-unimplemented vorestation.dme
unit_tests:
timeout-minutes: 30
if: ( !contains(github.event.head_commit.message, '[ci skip]') )
strategy:
matrix:
map: ["USE_MAP_TETHER", "USE_MAP_STELLARDELIGHT", "USE_MAP_GROUNDBASE"]
# name: Integration Tests (${{ matrix.map }})
run_all_tests:
name: Integration Tests
# needs: ['run_linters', 'dreamchecker']
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Ensure +x on CI directory
run: |
chmod -R +x ./tools/ci
- name: Restore BYOND from Cache
uses: ./.github/actions/restore_or_install_byond
with:
major: ${{ inputs.major }}
minor: ${{ inputs.minor }}
- name: Install RUST_G Dependencies
run: |
sudo dpkg --add-architecture i386
sudo apt update || true
sudo apt install zlib1g-dev:i386
ldd librust_g.so
ldd libbapi_dmm_reader.so
ldd libverdigris.so
- name: Unit Tests
run: tools/ci/compile_and_run.sh
env:
EXTRA_ARGS: "-DUNIT_TEST -D${{ matrix.map }}"
RUN: "1"
needs: start_gate
uses: ./.github/workflows/perform_regular_version_tests.yml
with:
maps: '{"paths":["USE_MAP_TETHER","USE_MAP_STELLARDELIGHT","USE_MAP_GROUNDBASE"]}'
max_required_byond_client: 516
extra_map_tests:
if: ( !contains(github.event.head_commit.message, '[ci skip]') )
name: Map Tests
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Ensure +x on CI directory
run: |
chmod -R +x ./tools/ci
- name: Restore BYOND from Cache
uses: ./.github/actions/restore_or_install_byond
with:
major: ${{ inputs.major }}
minor: ${{ inputs.minor }}
- name: Compile POIs
run: tools/ci/compile_and_run.sh
env:
EXTRA_ARGS: "-DMAP_TEST"
RUN: "0"
- name: Compile away missions
run: tools/ci/compile_and_run.sh
env:
EXTRA_ARGS: "-DAWAY_MISSION_TEST -DUSE_MAP_TETHER" # Only Tether has support for all away missions
RUN: "0"
run_extra_map_tests:
name: Extra Map Tests
needs: start_gate
uses: ./.github/workflows/run_extra_map_tests.yml
tests_successful:
if: ( !contains(github.event.head_commit.message, '[ci skip]') )
name: Integration Tests
needs: ["run_linters", "dreamchecker", "unit_tests", "extra_map_tests"]
completion_gate: # Serves as a non-moving target for branch rulesets
if: always() && !cancelled()
name: Completion Gate
needs:
[
run_all_tests,
run_extra_map_tests,
run_linters,
]
runs-on: ubuntu-24.04
steps:
- name: Report Success
run: |
echo "Jobs Successful!"
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
with:
jobs: ${{ toJSON(needs) }}
@@ -0,0 +1,24 @@
name: Run Regular BYOND Version Tests
on:
workflow_call:
inputs:
maps:
required: true
type: string
max_required_byond_client:
required: true
type: string
jobs:
run:
uses: ./.github/workflows/run_integration_tests.yml
strategy:
fail-fast: false
matrix:
map: ${{ fromJSON(inputs.maps).paths }}
with:
map: ${{ matrix.map }}
max_required_byond_client: ${{ inputs.max_required_byond_client }}
+51
View File
@@ -0,0 +1,51 @@
name: Run Extra Map Tests
on:
workflow_call:
inputs:
major:
required: false
type: string
minor:
required: false
type: string
jobs:
run_extra_map_tests:
# If `inputs.major` is specified, this will output `Run Tests (major.minor; map; max)`.
# For example, `Run Tests (515.1627; runtimestation; 515)`.
#
# Otherwise, it will output `Run Tests (map; max)`.
# For example, `Run Tests (runtimestation; 515)`.
name: Run Extra Map Tests (${{ inputs.major && format('{0}.{1}; ', inputs.major, inputs.minor) || '' }})
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- name: Ensure +x on CI directory
run: |
chmod -R +x ./tools/ci
- name: Restore BYOND from Cache
uses: ./.github/actions/restore_or_install_byond
with:
major: ${{ inputs.major }}
minor: ${{ inputs.minor }}
- name: Install RUST_G Dependencies
run: |
sudo dpkg --add-architecture i386
sudo apt update || true
sudo apt install zlib1g-dev:i386
ldd librust_g.so
ldd libbapi_dmm_reader.so
ldd libverdigris.so
- name: Compile POIs
run: tools/ci/compile_and_run.sh
env:
EXTRA_ARGS: "-DMAP_TEST"
RUN: "0"
- name: Compile away missions
run: tools/ci/compile_and_run.sh
env:
EXTRA_ARGS: "-DAWAY_MISSION_TEST -DUSE_MAP_TETHER" # Only Tether has support for all away missions
RUN: "0"
@@ -0,0 +1,82 @@
name: Run Integration Tests
on:
workflow_call:
inputs:
map:
required: true
type: string
major:
required: false
type: string
minor:
required: false
type: string
max_required_byond_client:
required: true
type: string
jobs:
run_integration_tests:
# If `inputs.major` is specified, this will output `Run Tests (major.minor; map; max)`.
# For example, `Run Tests (515.1627; runtimestation; 515)`.
#
# Otherwise, it will output `Run Tests (map; max)`.
# For example, `Run Tests (runtimestation; 515)`.
name: Run Tests (${{ inputs.major && format('{0}.{1}; ', inputs.major, inputs.minor) || '' }}${{ inputs.map }}; ${{ inputs.max_required_byond_client }})
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- name: Ensure +x on CI directory
run: |
chmod -R +x ./tools/ci
- name: Restore BYOND from Cache
uses: ./.github/actions/restore_or_install_byond
with:
major: ${{ inputs.major }}
minor: ${{ inputs.minor }}
- name: Install RUST_G Dependencies
run: |
sudo dpkg --add-architecture i386
sudo apt update || true
sudo apt install zlib1g-dev:i386
ldd librust_g.so
ldd libbapi_dmm_reader.so
ldd libverdigris.so
- name: Unit Tests
id: run_tests
run: tools/ci/compile_and_run.sh
env:
EXTRA_ARGS: "-DUNIT_TESTS -D${{ inputs.map }}"
RUN: "1"
- name: On test fail, write a step summary
if: always() && steps.run_tests.outcome == 'failure'
run: |
# Get a JSON array of failed unit tests
FAILED_UNIT_TESTS=$(jq 'to_entries | map(.value | select(.status == 1))' data/unit_tests.json)
FAIL_COUNT=$(echo $FAILED_UNIT_TESTS | jq 'length')
echo "# Test failures" >> $GITHUB_STEP_SUMMARY
echo "$FAIL_COUNT tests failed." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
for i in $( seq $FAIL_COUNT ); do
CURRENT_FAIL=$(echo $FAILED_UNIT_TESTS | jq --arg i $i '.[($i | tonumber) - 1]')
TEST=$(echo $CURRENT_FAIL | jq --raw-output '.name')
echo "### $TEST" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo $CURRENT_FAIL | jq --raw-output '.message' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
done
- name: Check client Compatibility
if: always() && steps.compile_tests.outcome == 'success'
uses: tgstation/byond-client-compatibility-check@v3
with:
dmb-location: vorestation.dmb
max-required-client-version: ${{inputs.max_required_byond_client}}
+111
View File
@@ -0,0 +1,111 @@
name: Run Linters
on:
workflow_call:
jobs:
linters:
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
# Caches
- name: Restore SpacemanDMM cache
uses: actions/cache@v4
with:
path: ~/SpacemanDMM
key: ${{ runner.os }}-spacemandmm-${{ hashFiles('dependencies.sh') }}
restore-keys: |
${{ runner.os }}-spacemandmm-
- name: Setup Bun
uses: ./.github/actions/setup_bun
- name: Restore Bootstrap cache
uses: actions/cache@v4
with:
path: tools/bootstrap/.cache
key: ${{ runner.os }}-bootstrap-${{ hashFiles('tools/requirements.txt') }}
restore-keys: |
${{ runner.os }}-bootstrap-
- name: Restore Rust cache
uses: actions/cache@v4
with:
path: ~/.cargo
key: ${{ runner.os }}-rust-${{ hashFiles('tools/ci/ci_dependencies.sh')}}
restore-keys: |
${{ runner.os }}-rust-
- name: Restore Cutter cache
uses: actions/cache@v4
with:
path: tools/icon_cutter/cache
key: ${{ runner.os }}-cutter-${{ hashFiles('dependencies.sh') }}
# End Caches
- name: Setup .NET SDK
uses: actions/setup-dotnet@v4.2.0
with:
dotnet-version: 9.x
- name: Install OpenDream
uses: robinraju/release-downloader@v1.12
with:
repository: "OpenDreamProject/OpenDream"
tag: "latest"
fileName: "DMCompiler_linux-x64.tar.gz"
extract: true
- name: Install Tools
run: |
pip3 install setuptools
bash tools/ci/install_spaceman_dmm.sh dreamchecker
bash tools/ci/install_ripgrep.sh
tools/bootstrap/python -c ''
- name: Give Linters A Go
id: linter-setup
run: ":"
- name: Ensure genesis_call.dme is unchanged
if: steps.linter-setup.conclusion == 'success' && !cancelled()
run: bash tools/ci/check_genesis.sh
- name: Run Grep Checks
if: steps.linter-setup.conclusion == 'success' && !cancelled()
run: bash tools/ci/check_grep.sh
#- name: Ticked File Enforcement
# if: steps.linter-setup.conclusion == 'success' && !cancelled()
# run: |
# tools/bootstrap/python tools/ticked_file_enforcement/ticked_file_enforcement.py < tools/ticked_file_enforcement/schemas/tgstation_dme.json
# tools/bootstrap/python tools/ticked_file_enforcement/ticked_file_enforcement.py < tools/ticked_file_enforcement/schemas/unit_tests.json
- name: Run Define Sanity Checks
run: tools/bootstrap/python -m define_sanity.check
- name: Run DreamChecker
if: steps.linter-setup.conclusion == 'success' && !cancelled()
shell: bash
run: ~/dreamchecker 2>&1 | bash tools/ci/annotate_dm.sh
- name: Run OpenDream
if: steps.linter-setup.conclusion == 'success' && !cancelled()
run: ./DMCompiler_linux-x64/DMCompiler vorestation.dme --suppress-unimplemented --define=CIBUILDING | bash tools/ci/annotate_od.sh
- name: Run Map Checks
if: steps.linter-setup.conclusion == 'success' && !cancelled()
run: |
tools/bootstrap/python -m mapmerge2.dmm_test
tools/bootstrap/python -m tools.maplint.source
- name: Check Cutter
if: steps.linter-setup.conclusion == 'success' && !cancelled()
run: tools/bootstrap/python -m tools.icon_cutter.check
- name: Run DMI Tests
if: steps.linter-setup.conclusion == 'success' && !cancelled()
run: tools/bootstrap/python -m dmi.test
#- name: Check File Directories
# if: steps.linter-setup.conclusion == 'success' && !cancelled()
# run: bash tools/ci/check_filedirs.sh tgstation.dme
- name: Check Changelogs
if: steps.linter-setup.conclusion == 'success' && !cancelled()
run: bash tools/ci/check_changelogs.sh
- name: Check Miscellaneous Files
if: steps.linter-setup.conclusion == 'success' && !cancelled()
run: bash tools/ci/check_misc.sh
- name: Run TGUI Checks
if: steps.linter-setup.conclusion == 'success' && !cancelled()
run: tools/build/build.sh --ci lint tgui-test
- name: Run Nanomap Checks
run: tools/github-actions/nanomap-renderer-invoker.sh --testing
+11 -5
View File
@@ -1,13 +1,19 @@
###Files and folders specified here will never be tracked.
#Ignore compiled files and other files generated during compilation.
*.dmb
*.rsc
*.m.dme
*.test.dme
*.lk
*.int
*.backup
#ignore misc BYOND files
Thumbs.db
vchat.db
vchat.db*
*.log
*.int
*.rsc
*.dmb
*.lk
*.backup
*.before
*.pyc
*.pid
+1 -1
View File
@@ -75,7 +75,7 @@
if("To Kill")
to_chat(user, span_boldwarning("Your wish is granted, but at a terrible cost..."))
to_chat(user, span_warning("The Wish Granter punishes you for your wickedness, claiming your soul and warping your body to match the darkness in your heart."))
ticker.mode.traitors += user.mind
SSticker.mode.traitors += user.mind
user.mind.special_role = "traitor"
var/datum/objective/hijack/hijack = new
hijack.owner = user.mind
@@ -169,10 +169,10 @@
//Radio remote control
/obj/machinery/atmospherics/binary/dp_vent_pump/proc/set_frequency(new_frequency)
radio_controller.remove_object(src, frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
if(frequency)
radio_connection = radio_controller.add_object(src, frequency, radio_filter = RADIO_ATMOSIA)
radio_connection = SSradio.add_object(src, frequency, radio_filter = RADIO_ATMOSIA)
/obj/machinery/atmospherics/binary/dp_vent_pump/proc/broadcast_status()
if(!radio_connection)
@@ -144,10 +144,10 @@
//Radio remote control
/obj/machinery/atmospherics/binary/passive_gate/proc/set_frequency(new_frequency)
radio_controller.remove_object(src, frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
if(frequency)
radio_connection = radio_controller.add_object(src, frequency, radio_filter = RADIO_ATMOSIA)
radio_connection = SSradio.add_object(src, frequency, radio_filter = RADIO_ATMOSIA)
/obj/machinery/atmospherics/binary/passive_gate/proc/broadcast_status()
if(!radio_connection)
@@ -121,10 +121,10 @@ Thus, the two variables affect pump operation are set in New():
//Radio remote control
/obj/machinery/atmospherics/binary/pump/proc/set_frequency(new_frequency)
radio_controller.remove_object(src, frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
if(frequency)
radio_connection = radio_controller.add_object(src, frequency, radio_filter = RADIO_ATMOSIA)
radio_connection = SSradio.add_object(src, frequency, radio_filter = RADIO_ATMOSIA)
/obj/machinery/atmospherics/binary/pump/proc/broadcast_status()
if(!radio_connection)
@@ -34,10 +34,10 @@
var/datum/radio_frequency/radio_connection
/obj/machinery/atmospherics/trinary/atmos_filter/proc/set_frequency(new_frequency)
radio_controller.remove_object(src, frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
if(frequency)
radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
/obj/machinery/atmospherics/trinary/atmos_filter/Initialize(mapload)
. = ..()
+2 -2
View File
@@ -295,10 +295,10 @@
//Radio remote control
/obj/machinery/atmospherics/tvalve/digital/proc/set_frequency(new_frequency)
radio_controller.remove_object(src, frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
if(frequency)
radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
@@ -100,10 +100,10 @@
flick("inject", src)
/obj/machinery/atmospherics/unary/outlet_injector/proc/set_frequency(new_frequency)
radio_controller.remove_object(src, frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
if(frequency)
radio_connection = radio_controller.add_object(src, frequency)
radio_connection = SSradio.add_object(src, frequency)
/obj/machinery/atmospherics/unary/outlet_injector/proc/broadcast_status()
if(!radio_connection)
@@ -90,9 +90,9 @@
add_underlay(T,, dir)
/obj/machinery/atmospherics/unary/vent_scrubber/proc/set_frequency(new_frequency)
radio_controller.remove_object(src, frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
radio_connection = radio_controller.add_object(src, frequency, radio_filter_in)
radio_connection = SSradio.add_object(src, frequency, radio_filter_in)
/obj/machinery/atmospherics/unary/vent_scrubber/proc/broadcast_status()
if(!radio_connection)
+2 -2
View File
@@ -258,10 +258,10 @@
icon_state = "valve[open]nopower"
/obj/machinery/atmospherics/valve/digital/proc/set_frequency(new_frequency)
radio_controller.remove_object(src, frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
if(frequency)
radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
/obj/machinery/atmospherics/valve/digital/Initialize(mapload)
. = ..()
+3 -7
View File
@@ -1,19 +1,17 @@
/*
Zone Air System:
# Zone Air System
This air system divides the station into impermeable areas called zones.
When something happens, i.e. a door opening or a wall being taken down,
zones equalize and eventually merge. Making an airtight area closes the connection again.
Control Flow:
## Control Flow:
Every air tick:
Marked turfs are updated with update_air_properties(), followed by post_update_air_properties().
Edges, including those generated by connections in the previous step, are processed. This is where gas is exchanged.
Fire is processed.
Marked zones have their air archived.
Important Functions:
## Important Functions:
SSair.mark_for_update(turf)
When stuff happens, call this. It works on everything. You basically don't need to worry about any other
@@ -24,5 +22,3 @@ Notes for people who used ZAS before:
To get the zones that are connected to a zone, use this loop:
for(var/connection_edge/zone/edge in zone.edges)
var/zone/connected_zone = edge.get_connected_zone(zone)
*/
+32 -11
View File
@@ -1,5 +1,4 @@
#define MC_TICK_CHECK ( ( TICK_USAGE > Master.current_ticklimit || src.state != SS_RUNNING ) ? pause() : 0 )
#define CURRENT_RUNLEVEL (2 ** (Master.current_runlevel - 1))
#define MC_SPLIT_TICK_INIT(phase_count) var/original_tick_limit = Master.current_ticklimit; var/split_tick_phases = ##phase_count
#define MC_SPLIT_TICK \
@@ -30,7 +29,14 @@
#define NEW_SS_GLOBAL(varname) if(varname != src){if(istype(varname)){Recover();qdel(varname);}varname = src;}
#define START_PROCESSING(Processor, Datum) if (!(Datum.datum_flags & DF_ISPROCESSING)) {Datum.datum_flags |= DF_ISPROCESSING;Processor.processing += Datum}
#define STOP_PROCESSING(Processor, Datum) Datum.datum_flags &= ~DF_ISPROCESSING;Processor.processing -= Datum
#define STOP_PROCESSING(Processor, Datum) Datum.datum_flags &= ~DF_ISPROCESSING;Processor.processing -= Datum;Processor.currentrun -= Datum
/// Returns true if the MC is initialized and running.
/// Optional argument init_stage controls what stage the mc must have initialized to count as initialized. Defaults to INITSTAGE_MAX if not specified.
#define MC_RUNNING(INIT_STAGE...) (Master && Master.processing > 0 && Master.current_runlevel && Master.init_stage_completed >= (max(min(INITSTAGE_MAX, ##INIT_STAGE), 1)))
#define MC_LOOP_RTN_NEWSTAGES 1
#define MC_LOOP_RTN_GRACEFUL_EXIT 2
//! SubSystem flags (Please design any new flags so that the default is off, to make adding flags to subsystems easier)
@@ -65,17 +71,26 @@
/// This flag overrides SS_KEEP_TIMING
#define SS_POST_FIRE_TIMING 64
/// If this subsystem doesn't initialize, it should not report as a hard error in CI.
/// This should be used for subsystems that are flaky for complicated reasons, such as
/// the Lua subsystem, which relies on auxtools, which is unstable.
/// It should not be used simply to silence CI.
#define SS_OK_TO_FAIL_INIT 128
//! SUBSYSTEM STATES
#define SS_IDLE 0 /// aint doing shit.
#define SS_QUEUED 1 /// queued to run
#define SS_RUNNING 2 /// actively running
#define SS_PAUSED 3 /// paused by mc_tick_check
#define SS_SLEEPING 4 /// fire() slept.
#define SS_PAUSING 5 /// in the middle of pausing
#define SS_IDLE 0 /// ain't doing shit.
#define SS_QUEUED 1 /// queued to run
#define SS_RUNNING 2 /// actively running
#define SS_PAUSED 3 /// paused by mc_tick_check
#define SS_SLEEPING 4 /// fire() slept.
#define SS_PAUSING 5 /// in the middle of pausing
// Subsystem init stages
#define INITSTAGE_EARLY 1 //! Early init stuff that doesn't need to wait for mapload
#define INITSTAGE_MAIN 2 //! Main init stage
#define INITSTAGE_MAX 2 //! Highest initstage.
#define INITSTAGE_FIRST 1
#define INITSTAGE_EARLY 2 //! Early init stuff that doesn't need to wait for mapload
#define INITSTAGE_MAIN 3 //! Main init stage
#define INITSTAGE_LAST 4
#define INITSTAGE_MAX 4 //! Highest initstage.
#define SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/##X);\
/datum/controller/subsystem/##X/New(){\
@@ -108,6 +123,10 @@
/datum/controller/subsystem/verb_manager/##X/fire() {..() /*just so it shows up on the profiler*/} \
/datum/controller/subsystem/verb_manager/##X
/////// OLD DEFINES
// Boilerplate code for multi-step processors. See machines.dm for example use.
#define INTERNAL_PROCESS_STEP(this_step, initial_step, proc_to_call, cost_var, next_step)\
if(current_step == this_step || (initial_step && !resumed)) /* So we start at step 1 if not resumed.*/ {\
@@ -120,3 +139,5 @@ if(current_step == this_step || (initial_step && !resumed)) /* So we start at st
resumed = 0;\
current_step = next_step;\
}
#define CURRENT_RUNLEVEL (2 ** (Master.current_runlevel - 1))
+5 -1
View File
@@ -18,7 +18,11 @@
// CI will override these as appropriate
// #define MAP_TEST 0
// #define AWAY_MISSION_TEST 0
// #define UNIT_TEST 0
// #define UNIT_TESTS 1
#if defined(CIBUILDING) && !defined(OPENDREAM)
#define UNIT_TESTS
#endif
// Comment/Uncomment this to turn off/on shuttle code debugging logs
#define DEBUG_SHUTTLES
+6
View File
@@ -206,6 +206,12 @@ What is the naming convention for planes or layers?
#define PLANE_ADMIN3 99 //Purely for shenanigans (above HUD)
///Plane of the "splash" icon used that shows on the lobby screen
#define SPLASHSCREEN_PLANE 100
///cinematics are "below" the splash screen
#define CINEMATIC_LAYER -1
//////////////////////////
/atom/proc/hud_layerise()
+1 -1
View File
@@ -929,6 +929,6 @@
#define COMSIG_HOSE_FORCEPUMP "hose_force_pump"
//Unittest data update
#ifdef UNIT_TEST
#ifdef UNIT_TESTS
#define COMSIG_UNITTEST_DATA "unittest_send_data"
#endif
@@ -3,5 +3,26 @@
// All signals send the source datum of the signal as the first argument
///Subsystem signals
///From base of datum/controller/subsystem/Initialize
///From base of /datum/controller/master/init_subsystem()
#define COMSIG_SUBSYSTEM_POST_INITIALIZE "subsystem_post_initialize"
///Called when the ticker enters the pre-game phase
#define COMSIG_TICKER_ENTER_PREGAME "comsig_ticker_enter_pregame"
///Called when the ticker sets up the game for start
#define COMSIG_TICKER_ENTER_SETTING_UP "comsig_ticker_enter_setting_up"
///Called when the ticker fails to set up the game for start
#define COMSIG_TICKER_ERROR_SETTING_UP "comsig_ticker_error_setting_up"
/// Called when the round has started, but before GAME_STATE_PLAYING.
#define COMSIG_TICKER_ROUND_STARTING "comsig_ticker_round_starting"
// Point of interest signals
/// Sent from base of /datum/controller/subsystem/points_of_interest/proc/on_poi_element_added : (atom/new_poi)
#define COMSIG_ADDED_POINT_OF_INTEREST "added_point_of_interest"
/// Sent from base of /datum/controller/subsystem/points_of_interest/proc/on_poi_element_removed : (atom/old_poi)
#define COMSIG_REMOVED_POINT_OF_INTEREST "removed_point_of_interest"
///Sent after awards are saved in the database (/datum/controller/subsystem/achievements/save_achievements_to_db)
#define COMSIG_ACHIEVEMENTS_SAVED_TO_DB "achievements_saved_to_db"
File diff suppressed because it is too large Load Diff
-7
View File
@@ -1,10 +1,3 @@
// Ticker game states, turns out these are equivilent to runlevels1
#define GAME_STATE_INIT 0 // RUNLEVEL_INIT
#define GAME_STATE_PREGAME 1 // RUNLEVEL_LOBBY
#define GAME_STATE_SETTING_UP 2 // RUNLEVEL_SETUP
#define GAME_STATE_PLAYING 3 // RUNLEVEL_GAME
#define GAME_STATE_FINISHED 4 // RUNLEVEL_POSTGAME
//End game state, to manage round end.
#define END_GAME_NOT_OVER 1 // Still playing normally
#define END_GAME_MODE_FINISHED 2 // Mode has finished but game has not, wait for game to end too.
+2
View File
@@ -90,3 +90,5 @@ GLOBAL_VAR_INIT(refid_filter, TYPEID(filter(type="angular_blur")))
#define isnum_safe(x) ( isnum((x)) && !isnan((x)) && !isinf((x)) )
#define ismopable(A) (A && (A.plane <= OBJ_PLANE)) //If something can be cleaned by floor-cleaning devices such as mops or clean bots
#define isfloorturf(A) (istype(A, /turf/simulated/floor))
+8
View File
@@ -1,3 +1,11 @@
/*ALL MOB-RELATED DEFINES THAT DON'T BELONG IN ANOTHER FILE GO HERE*/
//Misc mob defines
//Ready states at roundstart for mob/dead/new_player
#define PLAYER_NOT_READY 0
#define PLAYER_READY_TO_PLAY 1
// /mob/var/stat things.
#define CONSCIOUS 0
#define UNCONSCIOUS 1
+3
View File
@@ -168,6 +168,9 @@
*/
#define rustg_dmi_inject_metadata(path, metadata) RUSTG_CALL(RUST_G, "dmi_inject_metadata")(path, metadata)
#define rustg_create_qr_code_png(path, data) RUSTG_CALL(RUST_G, "create_qr_code_png")(path, data)
#define rustg_create_qr_code_svg(data) RUSTG_CALL(RUST_G, "create_qr_code_svg")(data)
#define rustg_file_read(fname) RUSTG_CALL(RUST_G, "file_read")(fname)
#define rustg_file_exists(fname) (RUSTG_CALL(RUST_G, "file_exists")(fname) == "true")
#define rustg_file_write(text, fname) RUSTG_CALL(RUST_G, "file_write")(text, fname)
+36 -71
View File
@@ -84,24 +84,6 @@
}\
}
// SS runlevels
#define RUNLEVEL_INIT 0 // "Initialize Only" - Used for subsystems that should never be fired (Should also have SS_NO_FIRE set)
#define RUNLEVEL_LOBBY 1 // Initial runlevel before setup. Returns to here if setup fails.
#define RUNLEVEL_SETUP 2 // While the gamemode setup is running. I.E gameticker.setup()
#define RUNLEVEL_GAME 4 // After successful game ticker setup, while the round is running.
#define RUNLEVEL_POSTGAME 8 // When round completes but before reboot
#define RUNLEVELS_DEFAULT (RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME)
GLOBAL_LIST_INIT(runlevel_flags, list(
RUNLEVEL_LOBBY,
RUNLEVEL_SETUP,
RUNLEVEL_GAME,
RUNLEVEL_POSTGAME
))
#define RUNLEVEL_FLAG_TO_INDEX(flag) (log(2, flag) + 1) // Convert from the runlevel bitfield constants to index in runlevel_flags list
//! ### SS initialization hints
/**
* Negative values indicate a failure or warning of some kind, positive are good.
@@ -120,59 +102,8 @@ GLOBAL_LIST_INIT(runlevel_flags, list(
/// If your system doesn't need to be initialized (by being disabled or something)
#define SS_INIT_NO_NEED 3
//! ### SS initialization load orders
// Subsystem init_order, from highest priority to lowest priority
// Subsystems shutdown in the reverse of the order they initialize in
// The numbers just define the ordering, they are meaningless otherwise.
#define INIT_ORDER_SERVER_MAINT 93
#define INIT_ORDER_ADMIN_VERBS 84 // needs to be pretty high, admins can't do much without it
#define INIT_ORDER_LOBBY 82
#define INIT_ORDER_WEBHOOKS 50
#define INIT_ORDER_SQLITE 41
#define INIT_ORDER_GARBAGE 40
#define INIT_ORDER_DBCORE 39
#define INIT_ORDER_MEDIA_TRACKS 38 // Gotta get that lobby music up, yo
#define INIT_ORDER_INPUT 37
#define INIT_ORDER_CHEMISTRY 35
#define INIT_ORDER_ROBOT_SPRITES 34
#define INIT_ORDER_VIS 32
#define INIT_ORDER_MAPPING 25
#define INIT_ORDER_RESEARCH 24
#define INIT_ORDER_SOUNDS 23
#define INIT_ORDER_INSTRUMENTS 22
#define INIT_ORDER_DECALS 20
#define INIT_ORDER_PLANTS 19 // Must initialize before atoms.
#define INIT_ORDER_PLANETS 18
#define INIT_ORDER_JOB 17
#define INIT_ORDER_ALARM 16 // Must initialize before atoms.
#define INIT_ORDER_TRANSCORE 15
#define INIT_ORDER_ATOMS 14
#define INIT_ORDER_HOLOMAPS 13
#define INIT_ORDER_POIS 12
#define INIT_ORDER_MACHINES 10
#define INIT_ORDER_STARMOVER 4
#define INIT_ORDER_SHUTTLES 3
#define INIT_ORDER_TIMER 1
#define INIT_ORDER_DEFAULT 0
#define INIT_ORDER_LIGHTING 0
#define INIT_ORDER_AIR -1
#define INIT_ORDER_ASSETS -5
#define INIT_ORDER_NIGHTSHIFT -6
#define INIT_ORDER_OVERLAY -7
#define INIT_ORDER_XENOARCH -20
#define INIT_ORDER_CIRCUIT -21
#define INIT_ORDER_AI -22
#define INIT_ORDER_AI_FAST -23
#define INIT_ORDER_GAME_MASTER -24
#define INIT_ORDER_PERSISTENCE -25
#define INIT_ORDER_SKYBOX -30 //Visual only, irrelevant to gameplay, but needs to be late enough to have overmap populated fully
#define INIT_ORDER_TICKER -50
#define INIT_ORDER_MAPRENAME -60 //Initiating after Ticker to ensure everything is loaded and everything we rely on us working
#define INIT_ORDER_WIKI -61
#define INIT_ORDER_ATC -70
#define INIT_ORDER_LOOT -80
#define INIT_ORDER_STATPANELS -98
#define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init.
/// Successfully initialized, BUT do not announce it to players (generally to hide game mechanics it would otherwise spoil)
#define SS_INIT_NO_MESSAGE 4
// Subsystem fire priority, from lowest to highest priority
// If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child)
@@ -193,6 +124,7 @@ GLOBAL_LIST_INIT(runlevel_flags, list(
#define FIRE_PRIORITY_AI 10
#define FIRE_PRIORITY_STARMOVER 11
#define FIRE_PRIORITY_GARBAGE 15
#define FIRE_PRIORITY_DATABASE 16
#define FIRE_PRIORITY_ASSETS 20
#define FIRE_PRIORITY_POIS 20
#define FIRE_PRIORITY_ALARM 20
@@ -217,6 +149,36 @@ GLOBAL_LIST_INIT(runlevel_flags, list(
#define FIRE_PRIORITY_DELAYED_VERBS 950
#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost.
// SS runlevels
#define RUNLEVEL_LOBBY (1<<0)
#define RUNLEVEL_SETUP (1<<1)
#define RUNLEVEL_GAME (1<<2)
#define RUNLEVEL_POSTGAME (1<<3)
#define RUNLEVELS_DEFAULT (RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME)
//SSticker.current_state values
/// Game is loading
#define GAME_STATE_STARTUP 0
/// Game is loaded and in pregame lobby
#define GAME_STATE_PREGAME 1
/// Game is attempting to start the round
#define GAME_STATE_SETTING_UP 2
/// Game has round in progress
#define GAME_STATE_PLAYING 3
/// Game has round finished
#define GAME_STATE_FINISHED 4
// Used for SSticker.force_ending
/// Default, round is not being forced to end.
#define END_ROUND_AS_NORMAL 0
/// End the round now as normal
#define FORCE_END_ROUND 1
/// For admin forcing roundend, can be used to distinguish the two
#define ADMIN_FORCE_END_ROUND 2
/**
Create a new timer and add it to the queue.
* Arguments:
@@ -227,5 +189,8 @@ GLOBAL_LIST_INIT(runlevel_flags, list(
*/
#define addtimer(args...) _addtimer(args, file = __FILE__, line = __LINE__)
// The change in the world's time from the subsystem's last fire in seconds.
#define DELTA_WORLD_TIME(ss) ((world.time - ss.last_fire) * 0.1)
/// The timer key used to know how long subsystem initialization takes
#define SS_INIT_TIMER_KEY "ss_init"
+98
View File
@@ -34,3 +34,101 @@
#define MS2DS(T) ((T) MILLISECONDS)
#define DS2MS(T) ((T) * 100)
/*Timezones*/
/// Line Islands Time
#define TIMEZONE_LINT 14
// Chatham Daylight Time
#define TIMEZONE_CHADT 13.75
/// Tokelau Time
#define TIMEZONE_TKT 13
/// Tonga Time
#define TIMEZONE_TOT 13
/// New Zealand Daylight Time
#define TIMEZONE_NZDT 13
/// New Zealand Standard Time
#define TIMEZONE_NZST 12
/// Norfolk Time
#define TIMEZONE_NFT 11
/// Lord Howe Standard Time
#define TIMEZONE_LHST 10.5
/// Australian Eastern Standard Time
#define TIMEZONE_AEST 10
/// Australian Central Standard Time
#define TIMEZONE_ACST 9.5
/// Australian Central Western Standard Time
#define TIMEZONE_ACWST 8.75
/// Australian Western Standard Time
#define TIMEZONE_AWST 8
/// Christmas Island Time
#define TIMEZONE_CXT 7
/// Cocos Islands Time
#define TIMEZONE_CCT 6.5
/// Central European Summer Time
#define TIMEZONE_CEST 2
/// Coordinated Universal Time
#define TIMEZONE_UTC 0
/// Eastern Daylight Time
#define TIMEZONE_EDT -4
/// Eastern Standard Time
#define TIMEZONE_EST -5
/// Central Daylight Time
#define TIMEZONE_CDT -5
/// Central Standard Time
#define TIMEZONE_CST -6
/// Mountain Daylight Time
#define TIMEZONE_MDT -6
/// Mountain Standard Time
#define TIMEZONE_MST -7
/// Pacific Daylight Time
#define TIMEZONE_PDT -7
/// Pacific Standard Time
#define TIMEZONE_PST -8
/// Alaska Daylight Time
#define TIMEZONE_AKDT -8
/// Alaska Standard Time
#define TIMEZONE_AKST -9
/// Hawaii-Aleutian Daylight Time
#define TIMEZONE_HDT -9
/// Hawaii Standard Time
#define TIMEZONE_HST -10
/// Cook Island Time
#define TIMEZONE_CKT -10
/// Niue Time
#define TIMEZONE_NUT -11
/// Anywhere on Earth
#define TIMEZONE_ANYWHERE_ON_EARTH -12
/// in the grim darkness of the thirteenth space station there is no timezones, since they break IC game times. Use this for all IC/round time values
#define NO_TIMEZONE 0
+5
View File
@@ -0,0 +1,5 @@
/// File path used for the "enable tracy next round" functionality
#define TRACY_ENABLE_PATH "data/enable_tracy"
/// The DLL path for byond-tracy.
#define TRACY_DLL_PATH (world.system_type == MS_WINDOWS ? "prof.dll" : "./libprof.so")
+3
View File
@@ -28,6 +28,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
*/
#define TRAIT_XENO_HOST "xeno_host" //Tracks whether we're gonna be a baby alien's mummy.
#define TRAIT_MIMING "miming" //Tracks whether you're a mime or not.
/// "Magic" trait that blocks the mob from moving or interacting with anything. Used for transient stuff like mob transformations or incorporality in special cases.
/// Will block movement, `Life()` (!!!), and other stuff based on the mob.
#define TRAIT_NO_TRANSFORM "block_transformations"
/*
#define TRAIT_STUNIMMUNE "stun_immunity"
#define TRAIT_STUNRESISTANCE "stun_resistance"
+3
View File
@@ -38,3 +38,6 @@
locate(max(CENTER.x-(H_RADIUS),1), max(CENTER.y-(V_RADIUS),1), CENTER.z), \
locate(min(CENTER.x+(H_RADIUS),world.maxx), min(CENTER.y+(V_RADIUS),world.maxy), CENTER.z) \
)
///Returns all turfs in a zlevel
#define Z_TURFS(ZLEVEL) block(1, 1, ZLEVEL, world.maxx, world.maxy, ZLEVEL)
-5
View File
@@ -1,5 +0,0 @@
#define ASCII_ESC ascii2text(27)
#define ASCII_RED "[ASCII_ESC]\[31m"
#define ASCII_GREEN "[ASCII_ESC]\[32m"
#define ASCII_YELLOW "[ASCII_ESC]\[33m"
#define ASCII_RESET "[ASCII_ESC]\[0m"
+2
View File
@@ -83,3 +83,5 @@ GLOBAL_DATUM_INIT(buildmode_hud, /icon, icon('icons/misc/buildmode.dmi'))
//Keyed list for caching icons so you don't need to make them for records, IDs, etc all separately.
//Could be useful for AI impersonation or something at some point?
GLOBAL_LIST_EMPTY(cached_character_icons)
GLOBAL_VAR_INIT(triai, FALSE)
+4
View File
@@ -0,0 +1,4 @@
/// Cache of the states of icon files
GLOBAL_LIST_EMPTY(icon_states_cache)
/// Cache of the states of icon files, stored associatively with TRUE for lookup
GLOBAL_LIST_EMPTY(icon_states_cache_lookup)
+3 -1
View File
@@ -1,8 +1,10 @@
#define ALL_POSSIBLE_DIRS list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST) // Use this define as Subsystem PreInit comes after GLOB
GLOBAL_LIST_INIT(cardinal, list(NORTH, SOUTH, EAST, WEST))
GLOBAL_LIST_INIT(cardinalz, list(NORTH, SOUTH, EAST, WEST, UP, DOWN))
GLOBAL_LIST_INIT(cornerdirs, list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST))
GLOBAL_LIST_INIT(cornerdirsz, list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST, NORTH|UP, EAST|UP, WEST|UP, SOUTH|UP, NORTH|DOWN, EAST|DOWN, WEST|DOWN, SOUTH|DOWN))
GLOBAL_LIST_INIT(alldirs, list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST))
GLOBAL_LIST_INIT(alldirs, ALL_POSSIBLE_DIRS)
GLOBAL_LIST_INIT(reverse_dir, list( // reverse_dir[dir] = reverse of dir
2, 1, 3, 8, 10, 9, 11, 4, 6, 5, 7, 12, 14, 13, 15,
32, 34, 33, 35, 40, 42, 41, 43, 36, 38, 37, 39, 44, 46, 45, 47,
+16
View File
@@ -0,0 +1,16 @@
GLOBAL_LIST_INIT(ai_names, world.file2list("strings/names/ai.txt"))
GLOBAL_LIST_INIT(wizard_first, world.file2list("strings/names/wizardfirst.txt"))
GLOBAL_LIST_INIT(wizard_second, world.file2list("strings/names/wizardsecond.txt"))
GLOBAL_LIST_INIT(ninja_titles, world.file2list("strings/names/ninjatitle.txt"))
GLOBAL_LIST_INIT(ninja_names, world.file2list("strings/names/ninjaname.txt"))
GLOBAL_LIST_INIT(commando_names, world.file2list("strings/names/death_commando.txt"))
GLOBAL_LIST_INIT(first_names, world.file2list("strings/names/first.txt"))
GLOBAL_LIST_INIT(first_names_male, world.file2list("strings/names/first_male.txt"))
GLOBAL_LIST_INIT(first_names_female, world.file2list("strings/names/first_female.txt"))
GLOBAL_LIST_INIT(last_names, world.file2list("strings/names/last.txt"))
GLOBAL_LIST_INIT(clown_names, world.file2list("strings/names/clown.txt"))
GLOBAL_LIST_INIT(verbs, world.file2list("strings/names/verbs.txt"))
GLOBAL_LIST_INIT(adjectives, world.file2list("strings/names/adjectives.txt"))
//loaded on startup because of "
//would include in rsc if ' was used
+184
View File
@@ -0,0 +1,184 @@
/*
Frequency range: 1200 to 1600
Radiochat range: 1441 to 1489 (most devices refuse to be tune to other frequency, even during mapmaking)
Radio:
1459 - standard radio chat
1351 - Science
1353 - Command
1355 - Medical
1357 - Engineering
1359 - Security
1341 - deathsquad
1443 - Confession Intercom
1347 - Cargo techs
1349 - Service people
Devices:
1451 - tracking implant
1457 - RSD default
On the map:
1311 for prison shuttle console (in fact, it is not used)
1433 for engine components
1435 for status displays
1437 for atmospherics/fire alerts
1439 for air pumps, air scrubbers, atmo control
1441 for atmospherics - supply tanks
1443 for atmospherics - distribution loop/mixed air tank
1445 for bot nav beacons
1447 for mulebot, secbot and ed209 control
1449 for airlock controls, electropack, magnets
1451 for toxin lab access
1453 for engineering access
1455 for AI access
*/
var/const/RADIO_LOW_FREQ = 1200
var/const/PUBLIC_LOW_FREQ = 1441
var/const/PUBLIC_HIGH_FREQ = 1489
var/const/RADIO_HIGH_FREQ = 1600
var/const/BOT_FREQ = 1447
var/const/COMM_FREQ = 1353
var/const/ERT_FREQ = 1345
var/const/AI_FREQ = 1343
var/const/DTH_FREQ = 1341
var/const/SYND_FREQ = 1213
var/const/RAID_FREQ = 1277
var/const/ENT_FREQ = 1461 //entertainment frequency. This is not a diona exclusive frequency.
// department channels
var/const/PUB_FREQ = 1459
var/const/SEC_FREQ = 1359
var/const/ENG_FREQ = 1357
var/const/MED_FREQ = 1355
var/const/SCI_FREQ = 1351
var/const/SRV_FREQ = 1349
var/const/SUP_FREQ = 1347
var/const/EXP_FREQ = 1361
// internal department channels
var/const/MED_I_FREQ = 1485
var/const/SEC_I_FREQ = 1475
var/const/TALON_FREQ = 1363 //VOREStation Add
var/const/CSN_FREQ = 1365 //VOREStation Add
var/list/radiochannels = list(
CHANNEL_COMMON = PUB_FREQ,
CHANNEL_SCIENCE = SCI_FREQ,
CHANNEL_COMMAND = COMM_FREQ,
CHANNEL_MEDICAL = MED_FREQ,
CHANNEL_ENGINEERING = ENG_FREQ,
CHANNEL_SECURITY = SEC_FREQ,
CHANNEL_RESPONSE_TEAM = ERT_FREQ,
CHANNEL_SPECIAL_OPS = DTH_FREQ,
CHANNEL_MERCENARY = SYND_FREQ,
CHANNEL_RAIDER = RAID_FREQ,
CHANNEL_SUPPLY = SUP_FREQ,
CHANNEL_SERVICE = SRV_FREQ,
CHANNEL_EXPLORATION = EXP_FREQ,
CHANNEL_AI_PRIVATE = AI_FREQ,
CHANNEL_ENTERTAINMENT = ENT_FREQ,
CHANNEL_MEDICAL_1 = MED_I_FREQ,
CHANNEL_SECURITY_1 = SEC_I_FREQ,
CHANNEL_TALON = TALON_FREQ, //VOREStation Add
CHANNEL_CASINO = CSN_FREQ,
)
// Hey, if anyone ever needs to update tgui/packages/tgui/constants.js with new radio channels
// I've kept this around just for you.
/* /client/verb/generate_tgui_radio_constants()
set name = "Generate TGUI Radio Constants"
set category = "Generate TGUI Radio Constants"
var/list/channel_info = list()
for(var/i in RADIO_LOW_FREQ to RADIO_HIGH_FREQ)
for(var/key in radiochannels)
if(i == radiochannels[key])
channel_info.Add(list(list("name" = key, "freq" = i, "color" = frequency_span_class(i))))
for(var/list/channel in channel_info)
switch(channel["color"])
if("deadsay") channel["color"] = "#530FAD"
if("radio") channel["color"] = "#008000"
if("deptradio") channel["color"] = "#ff00ff"
if("newscaster") channel["color"] = "#750000"
if("comradio") channel["color"] = "#193A7A"
if("syndradio") channel["color"] = "#6D3F40"
if("centradio") channel["color"] = "#5C5C8A"
if("airadio") channel["color"] = "#FF00FF"
if("entradio") channel["color"] = "#339966"
if("secradio") channel["color"] = "#A30000"
if("engradio") channel["color"] = "#A66300"
if("medradio") channel["color"] = "#008160"
if("sciradio") channel["color"] = "#993399"
if("supradio") channel["color"] = "#5F4519"
if("srvradio") channel["color"] = "#6eaa2c"
if("expradio") channel["color"] = "#555555"
to_chat(src, json_encode(channel_info)) */
// central command channels, i.e deathsquid & response teams
var/list/CENT_FREQS = list(ERT_FREQ, DTH_FREQ)
// Antag channels, i.e. Syndicate
var/list/ANTAG_FREQS = list(SYND_FREQ, RAID_FREQ)
//Department channels, arranged lexically
var/list/DEPT_FREQS = list(AI_FREQ, COMM_FREQ, ENG_FREQ, ENT_FREQ, MED_FREQ, SEC_FREQ, SCI_FREQ, SRV_FREQ, SUP_FREQ)
var/list/OFFMAP_FREQS = list(TALON_FREQ, CSN_FREQ) //VOREStation Add
/proc/frequency_span_class(var/frequency)
// Antags!
if (frequency in ANTAG_FREQS)
return "syndradio"
// CentCom channels (deathsquid and ert)
if(frequency in CENT_FREQS)
return "centradio"
// command channel
if(frequency == COMM_FREQ)
return "comradio"
// AI private channel
if(frequency == AI_FREQ)
return "airadio"
// department radio formatting (poorly optimized, ugh)
if(frequency == SEC_FREQ)
return "secradio"
if (frequency == ENG_FREQ)
return "engradio"
if(frequency == SCI_FREQ)
return "sciradio"
if(frequency == MED_FREQ)
return "medradio"
if(frequency == SUP_FREQ) // cargo
return "supradio"
if(frequency == SRV_FREQ) // service
return "srvradio"
if(frequency == EXP_FREQ) // explorer
return "expradio"
if(frequency == ENT_FREQ) // entertainment
return "entradio"
if(frequency in DEPT_FREQS)
return "deptradio"
//VOREStation Add
if(frequency in OFFMAP_FREQS)
return "expradio"
//VOREStation Add End
return "radio"
/* filters */
//When devices register with the radio controller, they might register under a certain filter.
//Other devices can then choose to send signals to only those devices that belong to a particular filter.
//This is done for performance, so we don't send signals to lots of machines unnecessarily.
//This filter is special because devices belonging to default also recieve signals sent to any other filter.
var/const/RADIO_DEFAULT = "radio_default"
var/const/RADIO_TO_AIRALARM = "radio_airalarm" //air alarms
var/const/RADIO_FROM_AIRALARM = "radio_airalarm_rcvr" //devices interested in recieving signals from air alarms
var/const/RADIO_CHAT = "radio_telecoms"
var/const/RADIO_ATMOSIA = "radio_atmos"
var/const/RADIO_NAVBEACONS = "radio_navbeacon"
var/const/RADIO_AIRLOCK = "radio_airlock"
var/const/RADIO_SECBOT = "radio_secbot"
var/const/RADIO_MULEBOT = "radio_mulebot"
var/const/RADIO_MAGNETS = "radio_magnet"
+29
View File
@@ -1017,3 +1017,32 @@ GLOBAL_LIST_EMPTY(json_cache)
///uses sort_list() but uses the var's name specifically. This should probably be using mergeAtom() instead
/proc/sort_names(list/list_to_sort, order=1)
return sortTim(list_to_sort.Copy(), order >= 0 ? GLOBAL_PROC_REF(cmp_name_asc) : GLOBAL_PROC_REF(cmp_name_dsc))
/// Compares 2 lists, returns TRUE if they are the same
/proc/deep_compare_list(list/list_1, list/list_2)
if(list_1 == list_2)
return TRUE
if(!islist(list_1) || !islist(list_2))
return FALSE
if(list_1.len != list_2.len)
return FALSE
for(var/i in 1 to list_1.len)
var/key_1 = list_1[i]
var/key_2 = list_2[i]
if (islist(key_1) && islist(key_2))
if(!deep_compare_list(key_1, key_2))
return FALSE
else if(key_1 != key_2)
return FALSE
if(istext(key_1) || islist(key_1) || ispath(key_1) || isdatum(key_1) || key_1 == world)
var/value_1 = list_1[key_1]
var/value_2 = list_2[key_1]
if (islist(value_1) && islist(value_2))
if(!deep_compare_list(value_1, value_2))
return FALSE
else if(value_1 != value_2)
return FALSE
return TRUE
+8 -3
View File
@@ -647,10 +647,15 @@
/proc/SecondsToTicks(var/seconds)
return seconds * 10
/proc/window_flash(var/client_or_usr)
if (!client_or_usr)
///Flash the window of a player
/proc/window_flash(client/flashed_client, ignorepref = FALSE)
if(ismob(flashed_client))
var/mob/player_mob = flashed_client
if(player_mob.client)
flashed_client = player_mob.client
if(!flashed_client || (!flashed_client.prefs.read_preference(/datum/preference/toggle/window_flashing) && !ignorepref))
return
winset(client_or_usr, "mainwindow", "flash=5")
winset(flashed_client, "mainwindow", "flash=5")
/**
* Get a bounding box of a list of atoms.
+42
View File
@@ -815,6 +815,26 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
var/icon/I = getFlatIcon(thing, force_south = force_south)
return icon2html(I, target, sourceonly = sourceonly)
/// Returns rustg-parsed metadata for an icon, universal icon, or DMI file, using cached values where possible
/// Returns null if passed object is not a filepath or icon with a valid DMI file
/proc/icon_metadata(file)
var/static/list/icon_metadata_cache = list()
if(istype(file, /datum/universal_icon))
var/datum/universal_icon/u_icon = file
file = u_icon.icon_file
var/file_string = "[file]"
if(!istext(file) && !(isfile(file) && length(file_string)))
return null
var/list/cached_metadata = icon_metadata_cache[file_string]
if(islist(cached_metadata))
return cached_metadata
var/list/metadata_result = rustg_dmi_read_metadata(file_string)
if(!islist(metadata_result) || !length(metadata_result))
CRASH("Error while reading DMI metadata for path '[file_string]': [metadata_result]")
else
icon_metadata_cache[file_string] = metadata_result
return metadata_result
/// Checks whether a given icon state exists in a given icon file. If `file` and `state` both exist,
/// this will return `TRUE` - otherwise, it will return `FALSE`.
///
@@ -836,3 +856,25 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
icon_states_cache[file][istate] = TRUE
return !isnull(icon_states_cache[file][state])
/// Cached, rustg-based alternative to icon_states()
/proc/icon_states_fast(file)
if(isnull(file))
return null
if(isnull(GLOB.icon_states_cache[file]))
compile_icon_states_cache(file)
return GLOB.icon_states_cache[file]
/proc/compile_icon_states_cache(file)
GLOB.icon_states_cache[file] = list()
GLOB.icon_states_cache_lookup[file] = list()
// Try to use rustg first
var/list/metadata = icon_metadata(file)
if(islist(metadata) && islist(metadata["states"]))
for(var/list/state_data as anything in metadata["states"])
GLOB.icon_states_cache[file] += state_data["name"]
GLOB.icon_states_cache_lookup[file][state_data["name"]] = TRUE
else // Otherwise, we have to use the slower BYOND proc
for(var/istate in icon_states(file))
GLOB.icon_states_cache[file] += istate
GLOB.icon_states_cache_lookup[file][istate] = TRUE
+1 -1
View File
@@ -177,7 +177,7 @@
WRITE_LOG(GLOB.diary, "TOPIC: [text]")
/proc/log_unit_test(text)
to_world_log("## UNIT_TEST: [text]")
to_world_log("## UNIT_TESTS: [text]")
#ifdef REFERENCE_TRACKING_LOG
#define log_reftracker(msg) WRITE_LOG(GLOB.diary, "## REF SEARCH [msg]")
+2 -2
View File
@@ -93,9 +93,9 @@
if(!current_species || current_species.name_language == null)
if(gender==FEMALE)
return capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names))
return capitalize(pick(GLOB.first_names_female)) + " " + capitalize(pick(GLOB.last_names))
else
return capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names))
return capitalize(pick(GLOB.first_names_male)) + " " + capitalize(pick(GLOB.last_names))
else
return current_species.get_random_name(gender)
+4 -4
View File
@@ -195,9 +195,9 @@ GLOBAL_VAR(syndicate_code_response) //Code response for traitors.
if(names.len&&prob(70))
code_phrase += pick(names)
else
code_phrase += pick(pick(first_names_male,first_names_female))
code_phrase += pick(pick(GLOB.first_names_male, GLOB.first_names_female))
code_phrase += " "
code_phrase += pick(last_names)
code_phrase += pick(GLOB.last_names)
if(2)
code_phrase += pick(GLOB.joblist)//Returns a job.
safety -= 1
@@ -213,9 +213,9 @@ GLOBAL_VAR(syndicate_code_response) //Code response for traitors.
if(1)
code_phrase += pick(nouns)
if(2)
code_phrase += pick(adjectives)
code_phrase += pick(GLOB.adjectives)
if(3)
code_phrase += pick(verbs)
code_phrase += pick(GLOB.verbs)
if(words==1)
code_phrase += "."
else
+106
View File
@@ -0,0 +1,106 @@
/datum/controller/subsystem/ticker/proc/declare_completion(was_forced = END_ROUND_AS_NORMAL)
set waitfor = FALSE
for(var/datum/callback/roundend_callbacks as anything in round_end_events)
roundend_callbacks.InvokeAsync()
LAZYCLEARLIST(round_end_events)
to_world(span_filter_system("<br><br><br><H1>A round of [mode.name] has ended!</H1>"))
for(var/mob/Player in GLOB.player_list)
if(Player.mind && !isnewplayer(Player))
if(Player.stat != DEAD)
var/turf/playerTurf = get_turf(Player)
if(emergency_shuttle.departed && emergency_shuttle.evac)
if(isNotAdminLevel(playerTurf.z))
to_chat(Player, span_filter_system(span_blue(span_bold("You survived the round, but remained on [station_name()] as [Player.real_name]."))))
else
to_chat(Player, span_filter_system(span_green(span_bold("You managed to survive the events on [station_name()] as [Player.real_name]."))))
else if(isAdminLevel(playerTurf.z))
to_chat(Player, span_filter_system(span_green(span_bold("You successfully underwent crew transfer after events on [station_name()] as [Player.real_name]."))))
else if(issilicon(Player))
to_chat(Player, span_filter_system(span_green(span_bold("You remain operational after the events on [station_name()] as [Player.real_name]."))))
else
to_chat(Player, span_filter_system(span_blue(span_bold("You missed the crew transfer after the events on [station_name()] as [Player.real_name]."))))
else
if(isobserver(Player))
var/mob/observer/dead/O = Player
if(!O.started_as_observer)
to_chat(Player, span_filter_system(span_red(span_bold("You did not survive the events on [station_name()]..."))))
else
to_chat(Player, span_filter_system(span_red(span_bold("You did not survive the events on [station_name()]..."))))
to_world(span_filter_system("<br>"))
for (var/mob/living/silicon/ai/aiPlayer in GLOB.mob_list)
if (aiPlayer.stat != 2)
to_world(span_filter_system(span_bold("[aiPlayer.name]'s laws at the end of the round were:"))) // VOREStation edit
else
to_world(span_filter_system(span_bold("[aiPlayer.name]'s laws when it was deactivated were:"))) // VOREStation edit
aiPlayer.show_laws(1)
if (aiPlayer.connected_robots.len)
var/robolist = span_bold("The AI's loyal minions were:") + " "
for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots)
robolist += "[robo.name][robo.stat?" (Deactivated), ":", "]" // VOREStation edit
to_world(span_filter_system("[robolist]"))
var/dronecount = 0
for (var/mob/living/silicon/robot/robo in GLOB.mob_list)
if(istype(robo, /mob/living/silicon/robot/platform))
var/mob/living/silicon/robot/platform/tank = robo
if(!tank.has_had_player)
continue
if(istype(robo,/mob/living/silicon/robot/drone) && !istype(robo,/mob/living/silicon/robot/drone/swarm))
dronecount++
continue
if (!robo.connected_ai)
if (robo.stat != 2)
to_world(span_filter_system(span_bold("[robo.name] survived as an AI-less stationbound synthetic! Its laws were:"))) // VOREStation edit
else
to_world(span_filter_system(span_bold("[robo.name] was unable to survive the rigors of being a stationbound synthetic without an AI. Its laws were:"))) // VOREStation edit
if(robo) //How the hell do we lose robo between here and the world messages directly above this?
robo.laws.show_laws(world)
if(dronecount)
to_world(span_filter_system(span_bold("There [dronecount>1 ? "were" : "was"] [dronecount] industrious maintenance [dronecount>1 ? "drones" : "drone"] at the end of this round.")))
mode.declare_completion()//To declare normal completion.
//Ask the event manager to print round end information
SSevents.RoundEnd()
//Print a list of antagonists to the server log
var/list/total_antagonists = list()
//Look into all mobs in world, dead or alive
for(var/datum/mind/Mind in minds)
var/temprole = Mind.special_role
if(temprole) //if they are an antagonist of some sort.
if(temprole in total_antagonists) //If the role exists already, add the name to it
total_antagonists[temprole] += ", [Mind.name]([Mind.key])"
else
total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob
total_antagonists[temprole] += ": [Mind.name]([Mind.key])"
//Now print them all into the log!
log_game("Antagonists at round end were...")
for(var/i in total_antagonists)
log_game("[i]s[total_antagonists[i]].")
SSdbcore.SetRoundEnd()
sleep(5 SECONDS)
ready_for_reboot = TRUE
standard_reboot()
/datum/controller/subsystem/ticker/proc/standard_reboot()
if(ready_for_reboot)
if(mode.station_was_nuked)
Reboot("Station destroyed by Nuclear Device.", "nuke")
else
Reboot("Round ended.", "proper completion")
else
CRASH("Attempted standard reboot without ticker roundend completion")
+4 -1
View File
@@ -13,7 +13,10 @@
// Sorts subsystems by init_order
/proc/cmp_subsystem_init(datum/controller/subsystem/a, datum/controller/subsystem/b)
return initial(b.init_order) - initial(a.init_order) //uses initial() so it can be used on types
return a.init_order - b.init_order
/proc/cmp_subsystem_init_stage(datum/controller/subsystem/a, datum/controller/subsystem/b)
return initial(a.init_stage) - initial(b.init_stage)
// Sorts subsystems by priority
/proc/cmp_subsystem_priority(datum/controller/subsystem/a, datum/controller/subsystem/b)
+12 -6
View File
@@ -121,24 +121,30 @@ GLOBAL_VAR_INIT(round_start_time, 0)
rollovercheck_last_timeofday = world.timeofday
return midnight_rollovers
//Increases delay as the server gets more overloaded,
//as sleeps aren't cheap and sleeping only to wake up and sleep again is wasteful
///Increases delay as the server gets more overloaded, as sleeps aren't cheap and sleeping only to wake up and sleep again is wasteful
#define DELTA_CALC max(((max(TICK_USAGE, world.cpu) / 100) * max(Master.sleep_delta-1,1)), 1)
//returns the number of ticks slept
///returns the number of ticks slept
/proc/stoplag(initial_delay)
if (!Master || !(Master.current_runlevel & RUNLEVELS_DEFAULT))
if (!Master || Master.init_stage_completed < INITSTAGE_MAX)
sleep(world.tick_lag)
return 1
if (!initial_delay)
initial_delay = world.tick_lag
// Unit tests are not the normal environemnt. The mc can get absolutely thigh crushed, and sleeping procs running for ages is much more common
// We don't want spurious hard deletes off this, so let's only sleep for the requested period of time here yeah?
#ifdef UNIT_TESTS
sleep(initial_delay)
return CEILING(DS2TICKS(initial_delay), 1)
#else
. = 0
var/i = DS2TICKS(initial_delay)
do
. += CEILING(i*DELTA_CALC, 1)
sleep(i*world.tick_lag*DELTA_CALC)
. += CEILING(i * DELTA_CALC, 1)
sleep(i * world.tick_lag * DELTA_CALC)
i *= 2
while (TICK_USAGE > min(TICK_LIMIT_TO_RUN, Master.current_ticklimit))
#endif
#undef DELTA_CALC
+1 -1
View File
@@ -194,7 +194,7 @@
if(is_incorporeal())
return 0
if(!ticker)
if(!SSticker)
to_chat(src, "You cannot attack people before the game has started.")
return 0
+9
View File
@@ -143,6 +143,15 @@
show_when_dead = TRUE
plane = PLANE_PLAYER_HUD_ABOVE
/obj/screen/fullscreen/cinematic_backdrop
icon = 'icons/hud/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "flash"
plane = SPLASHSCREEN_PLANE
layer = CINEMATIC_LAYER
color = COLOR_BLACK
show_when_dead = TRUE
/obj/screen/fullscreen/lighting_backdrop
icon = 'icons/mob/screen_gen.dmi'
icon_state = "flash"
+1 -1
View File
@@ -79,7 +79,7 @@ ADMIN_VERB(debug_controller, R_DEBUG, "Debug Controller", "Debug the various per
//Goon PS stuff, and other yet-to-be-subsystem things.
options["LEGACY: master_controller"] = master_controller
options["LEGACY: job_master"] = job_master
options["LEGACY: radio_controller"] = radio_controller
options["LEGACY: SSradio"] = SSradio
options["LEGACY: emergency_shuttle"] = emergency_shuttle
options["LEGACY: paiController"] = paiController
options["LEGACY: cameranet"] = cameranet
-394
View File
@@ -1,394 +0,0 @@
/*
HOW IT WORKS
The radio_controller is a global object maintaining all radio transmissions, think about it as about "ether".
Note that walkie-talkie, intercoms and headsets handle transmission using nonstandard way.
procs:
add_object(obj/device as obj, var/new_frequency as num, var/radio_filter as text|null = null)
Adds listening object.
parameters:
device - device receiving signals, must have proc receive_signal (see description below).
one device may listen several frequencies, but not same frequency twice.
new_frequency - see possibly frequencies below;
radio_filter - thing for optimization. Optional, but recommended.
All filters should be consolidated in this file, see defines later.
Device without listening filter will receive all signals (on specified frequency).
Device with filter will receive any signals sent without filter.
Device with filter will not receive any signals sent with different filter.
returns:
Reference to frequency object.
remove_object (obj/device, old_frequency)
Obliviously, after calling this proc, device will not receive any signals on old_frequency.
Other frequencies will left unaffected.
return_frequency(var/frequency as num)
returns:
Reference to frequency object. Use it if you need to send and do not need to listen.
radio_frequency is a global object maintaining list of devices that listening specific frequency.
procs:
post_signal(obj/source as obj|null, datum/signal/signal, var/radio_filter as text|null = null, var/range as num|null = null)
Sends signal to all devices that wants such signal.
parameters:
source - object, emitted signal. Usually, devices will not receive their own signals.
signal - see description below.
radio_filter - described above.
range - radius of regular byond's square circle on that z-level. null means everywhere, on all z-levels.
obj/proc/receive_signal(datum/signal/signal, var/receive_method as num, var/receive_param)
Handler from received signals. By default does nothing. Define your own for your object.
Avoid of sending signals directly from this proc, use spawn(-1). DO NOT use sleep() here or call procs that sleep please. If you must, use spawn()
parameters:
signal - see description below. Extract all needed data from the signal before doing sleep(), spawn() or return!
receive_method - may be TRANSMISSION_WIRE or TRANSMISSION_RADIO.
TRANSMISSION_WIRE is currently unused.
receive_param - for TRANSMISSION_RADIO here comes frequency.
datum/signal
vars:
source
an object that emitted signal. Used for debug and bearing.
data
list with transmitting data. Usual use pattern:
data["msg"] = "hello world"
encryption
Some number symbolizing "encryption key".
Note that game actually do not use any cryptography here.
If receiving object don't know right key, it must ignore encrypted signal in its receive_signal.
*/
/*
Frequency range: 1200 to 1600
Radiochat range: 1441 to 1489 (most devices refuse to be tune to other frequency, even during mapmaking)
Radio:
1459 - standard radio chat
1351 - Science
1353 - Command
1355 - Medical
1357 - Engineering
1359 - Security
1341 - deathsquad
1443 - Confession Intercom
1347 - Cargo techs
1349 - Service people
Devices:
1451 - tracking implant
1457 - RSD default
On the map:
1311 for prison shuttle console (in fact, it is not used)
1433 for engine components
1435 for status displays
1437 for atmospherics/fire alerts
1439 for air pumps, air scrubbers, atmo control
1441 for atmospherics - supply tanks
1443 for atmospherics - distribution loop/mixed air tank
1445 for bot nav beacons
1447 for mulebot, secbot and ed209 control
1449 for airlock controls, electropack, magnets
1451 for toxin lab access
1453 for engineering access
1455 for AI access
*/
var/const/RADIO_LOW_FREQ = 1200
var/const/PUBLIC_LOW_FREQ = 1441
var/const/PUBLIC_HIGH_FREQ = 1489
var/const/RADIO_HIGH_FREQ = 1600
var/const/BOT_FREQ = 1447
var/const/COMM_FREQ = 1353
var/const/ERT_FREQ = 1345
var/const/AI_FREQ = 1343
var/const/DTH_FREQ = 1341
var/const/SYND_FREQ = 1213
var/const/RAID_FREQ = 1277
var/const/ENT_FREQ = 1461 //entertainment frequency. This is not a diona exclusive frequency.
// department channels
var/const/PUB_FREQ = 1459
var/const/SEC_FREQ = 1359
var/const/ENG_FREQ = 1357
var/const/MED_FREQ = 1355
var/const/SCI_FREQ = 1351
var/const/SRV_FREQ = 1349
var/const/SUP_FREQ = 1347
var/const/EXP_FREQ = 1361
// internal department channels
var/const/MED_I_FREQ = 1485
var/const/SEC_I_FREQ = 1475
var/const/TALON_FREQ = 1363 //VOREStation Add
var/const/CSN_FREQ = 1365 //VOREStation Add
var/list/radiochannels = list(
CHANNEL_COMMON = PUB_FREQ,
CHANNEL_SCIENCE = SCI_FREQ,
CHANNEL_COMMAND = COMM_FREQ,
CHANNEL_MEDICAL = MED_FREQ,
CHANNEL_ENGINEERING = ENG_FREQ,
CHANNEL_SECURITY = SEC_FREQ,
CHANNEL_RESPONSE_TEAM = ERT_FREQ,
CHANNEL_SPECIAL_OPS = DTH_FREQ,
CHANNEL_MERCENARY = SYND_FREQ,
CHANNEL_RAIDER = RAID_FREQ,
CHANNEL_SUPPLY = SUP_FREQ,
CHANNEL_SERVICE = SRV_FREQ,
CHANNEL_EXPLORATION = EXP_FREQ,
CHANNEL_AI_PRIVATE = AI_FREQ,
CHANNEL_ENTERTAINMENT = ENT_FREQ,
CHANNEL_MEDICAL_1 = MED_I_FREQ,
CHANNEL_SECURITY_1 = SEC_I_FREQ,
CHANNEL_TALON = TALON_FREQ, //VOREStation Add
CHANNEL_CASINO = CSN_FREQ,
)
// Hey, if anyone ever needs to update tgui/packages/tgui/constants.js with new radio channels
// I've kept this around just for you.
/* /client/verb/generate_tgui_radio_constants()
set name = "Generate TGUI Radio Constants"
set category = "Generate TGUI Radio Constants"
var/list/channel_info = list()
for(var/i in RADIO_LOW_FREQ to RADIO_HIGH_FREQ)
for(var/key in radiochannels)
if(i == radiochannels[key])
channel_info.Add(list(list("name" = key, "freq" = i, "color" = frequency_span_class(i))))
for(var/list/channel in channel_info)
switch(channel["color"])
if("deadsay") channel["color"] = "#530FAD"
if("radio") channel["color"] = "#008000"
if("deptradio") channel["color"] = "#ff00ff"
if("newscaster") channel["color"] = "#750000"
if("comradio") channel["color"] = "#193A7A"
if("syndradio") channel["color"] = "#6D3F40"
if("centradio") channel["color"] = "#5C5C8A"
if("airadio") channel["color"] = "#FF00FF"
if("entradio") channel["color"] = "#339966"
if("secradio") channel["color"] = "#A30000"
if("engradio") channel["color"] = "#A66300"
if("medradio") channel["color"] = "#008160"
if("sciradio") channel["color"] = "#993399"
if("supradio") channel["color"] = "#5F4519"
if("srvradio") channel["color"] = "#6eaa2c"
if("expradio") channel["color"] = "#555555"
to_chat(src, json_encode(channel_info)) */
// central command channels, i.e deathsquid & response teams
var/list/CENT_FREQS = list(ERT_FREQ, DTH_FREQ)
// Antag channels, i.e. Syndicate
var/list/ANTAG_FREQS = list(SYND_FREQ, RAID_FREQ)
//Department channels, arranged lexically
var/list/DEPT_FREQS = list(AI_FREQ, COMM_FREQ, ENG_FREQ, ENT_FREQ, MED_FREQ, SEC_FREQ, SCI_FREQ, SRV_FREQ, SUP_FREQ)
var/list/OFFMAP_FREQS = list(TALON_FREQ, CSN_FREQ) //VOREStation Add
/proc/frequency_span_class(var/frequency)
// Antags!
if (frequency in ANTAG_FREQS)
return "syndradio"
// CentCom channels (deathsquid and ert)
if(frequency in CENT_FREQS)
return "centradio"
// command channel
if(frequency == COMM_FREQ)
return "comradio"
// AI private channel
if(frequency == AI_FREQ)
return "airadio"
// department radio formatting (poorly optimized, ugh)
if(frequency == SEC_FREQ)
return "secradio"
if (frequency == ENG_FREQ)
return "engradio"
if(frequency == SCI_FREQ)
return "sciradio"
if(frequency == MED_FREQ)
return "medradio"
if(frequency == SUP_FREQ) // cargo
return "supradio"
if(frequency == SRV_FREQ) // service
return "srvradio"
if(frequency == EXP_FREQ) // explorer
return "expradio"
if(frequency == ENT_FREQ) // entertainment
return "entradio"
if(frequency in DEPT_FREQS)
return "deptradio"
//VOREStation Add
if(frequency in OFFMAP_FREQS)
return "expradio"
//VOREStation Add End
return "radio"
/* filters */
//When devices register with the radio controller, they might register under a certain filter.
//Other devices can then choose to send signals to only those devices that belong to a particular filter.
//This is done for performance, so we don't send signals to lots of machines unnecessarily.
//This filter is special because devices belonging to default also recieve signals sent to any other filter.
var/const/RADIO_DEFAULT = "radio_default"
var/const/RADIO_TO_AIRALARM = "radio_airalarm" //air alarms
var/const/RADIO_FROM_AIRALARM = "radio_airalarm_rcvr" //devices interested in recieving signals from air alarms
var/const/RADIO_CHAT = "radio_telecoms"
var/const/RADIO_ATMOSIA = "radio_atmos"
var/const/RADIO_NAVBEACONS = "radio_navbeacon"
var/const/RADIO_AIRLOCK = "radio_airlock"
var/const/RADIO_SECBOT = "radio_secbot"
var/const/RADIO_MULEBOT = "radio_mulebot"
var/const/RADIO_MAGNETS = "radio_magnet"
var/global/datum/controller/radio/radio_controller
/hook/startup/proc/createRadioController()
radio_controller = new /datum/controller/radio()
return 1
//callback used by objects to react to incoming radio signals
/obj/proc/receive_signal(datum/signal/signal, receive_method, receive_param)
return null
//The global radio controller
/datum/controller/radio
var/list/datum/radio_frequency/frequencies = list()
/datum/controller/radio/proc/add_object(obj/device as obj, var/new_frequency as num, var/radio_filter = null as text|null)
var/f_text = num2text(new_frequency)
var/datum/radio_frequency/frequency = frequencies[f_text]
if(!frequency)
frequency = new
frequency.frequency = new_frequency
frequencies[f_text] = frequency
frequency.add_listener(device, radio_filter)
return frequency
/datum/controller/radio/proc/remove_object(obj/device, old_frequency)
var/f_text = num2text(old_frequency)
var/datum/radio_frequency/frequency = frequencies[f_text]
if(frequency)
frequency.remove_listener(device)
if(frequency.devices.len == 0)
qdel(frequency)
frequencies -= f_text
return 1
/datum/controller/radio/proc/return_frequency(var/new_frequency as num)
var/f_text = num2text(new_frequency)
var/datum/radio_frequency/frequency = frequencies[f_text]
if(!frequency)
frequency = new
frequency.frequency = new_frequency
frequencies[f_text] = frequency
return frequency
/datum/radio_frequency
var/frequency as num
var/list/list/obj/devices = list()
/datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, var/radio_filter = null as text|null, var/range = null as num|null)
var/turf/start_point
if(range)
start_point = get_turf(source)
if(!start_point)
qdel(signal)
return 0
if (radio_filter)
send_to_filter(source, signal, radio_filter, start_point, range)
send_to_filter(source, signal, RADIO_DEFAULT, start_point, range)
else
//Broadcast the signal to everyone!
for (var/next_filter in devices)
send_to_filter(source, signal, next_filter, start_point, range)
//Sends a signal to all machines belonging to a given filter. Should be called by post_signal()
/datum/radio_frequency/proc/send_to_filter(obj/source, datum/signal/signal, var/radio_filter, var/turf/start_point = null, var/range = null)
if (range && !start_point)
return
for(var/obj/device in devices[radio_filter])
if(device == source)
continue
if(range)
var/turf/end_point = get_turf(device)
if(!end_point)
continue
if(start_point.z!=end_point.z || get_dist(start_point, end_point) > range)
continue
device.receive_signal(signal, TRANSMISSION_RADIO, frequency)
/datum/radio_frequency/proc/add_listener(obj/device as obj, var/radio_filter as text|null)
if (!radio_filter)
radio_filter = RADIO_DEFAULT
//log_admin("add_listener(device=[device],radio_filter=[radio_filter]) frequency=[frequency]")
var/list/obj/devices_line = devices[radio_filter]
if (!devices_line)
devices_line = new
devices[radio_filter] = devices_line
devices_line+=device
// var/list/obj/devices_line___ = devices[filter_str]
// var/l = devices_line___.len
//log_admin("DEBUG: devices_line.len=[devices_line.len]")
//log_admin("DEBUG: devices(filter_str).len=[l]")
/datum/radio_frequency/proc/remove_listener(obj/device)
for (var/devices_filter in devices)
var/list/devices_line = devices[devices_filter]
devices_line-=device
while (null in devices_line)
devices_line -= null
if (devices_line.len==0)
devices -= devices_filter
/datum/signal
var/obj/source
var/transmission_method = 0 //unused at the moment
//0 = wire
//1 = radio transmission
//2 = subspace transmission
var/list/data = list()
var/encryption
var/frequency = 0
/datum/signal/proc/copy_from(datum/signal/model)
source = model.source
transmission_method = model.transmission_method
data = model.data
encryption = model.encryption
frequency = model.frequency
/datum/signal/proc/debug_print()
if (source)
. = "signal = {source = '[source]' ([source:x],[source:y],[source:z])\n"
else
. = "signal = {source = '[source]' ()\n"
for (var/i in data)
. += "data\[\"[i]\"\] = \"[data[i]]\"\n"
if(islist(data[i]))
var/list/L = data[i]
for(var/t in L)
. += "data\[\"[i]\"\] list has: [t]"
@@ -24,6 +24,9 @@
/// If the configuration is loaded
var/loaded = FALSE
/// If a reload is in progress
var/reload_in_progress = FALSE
/// A regex that matches words blocked IC
var/static/regex/ic_filter_regex
@@ -64,13 +67,23 @@
var/static/list/configuration_errors
/datum/controller/configuration/proc/admin_reload()
if(IsAdminAdvancedProcCall())
if(IsAdminAdvancedProcCall() || !PreConfigReload())
return
log_admin("[key_name_admin(usr)] has forcefully reloaded the configuration from disk.")
message_admins("[key_name_admin(usr)] has forcefully reloaded the configuration from disk.")
full_wipe()
Load(world.params[OVERRIDE_CONFIG_DIRECTORY_PARAMETER])
/datum/controller/configuration/proc/PreConfigReload()
if(reload_in_progress)
to_chat(usr, span_warning("Another user is already reloading the config!"))
return FALSE
reload_in_progress = TRUE
world.TgsTriggerEvent("tg-PreConfigReload", wait_for_completion = TRUE)
reload_in_progress = FALSE
return TRUE
/datum/controller/configuration/proc/Load(_directory)
if(IsAdminAdvancedProcCall()) //If admin proccall is detected down the line it will horribly break everything.
return
@@ -34,6 +34,8 @@
/datum/config_entry/number/walk_speed
default = 0
/datum/config_entry/flag/force_random_names
///Mob specific modifiers. NOTE: These will affect different mob types in different ways
/datum/config_entry/number/human_delay
default = 0
@@ -1,6 +1,18 @@
/// server name (the name of the game window)
/datum/config_entry/string/servername
/// Countdown between lobby and the round starting.
/datum/config_entry/number/lobby_countdown
default = 120
integer = FALSE
min_val = 0
/// Post round murder death kill countdown.
/datum/config_entry/number/round_end_countdown
default = 25
integer = FALSE
min_val = 0
/// generate numeric suffix based on server port
/datum/config_entry/flag/server_suffix
@@ -222,9 +234,6 @@
// var/static/Tickcomp = 0 // FIXME: Unused
/// use socket_talk to communicate with other processes
/datum/config_entry/flag/socket_talk
// var/static/list/resource_urls = null // FIXME: Unused
/// Ghosts can turn on Antagovision to see a HUD of who is the bad guys this round.
@@ -787,6 +796,60 @@
/datum/config_entry/flag/discord_ahelps_all
default = FALSE
/datum/config_entry/number/mc_tick_rate/base_mc_tick_rate
integer = FALSE
default = 1
/datum/config_entry/number/mc_tick_rate/high_pop_mc_tick_rate
integer = FALSE
default = 1.1
/datum/config_entry/number/mc_tick_rate/high_pop_mc_mode_amount
default = 65
/datum/config_entry/number/mc_tick_rate/disable_high_pop_mc_mode_amount
default = 60
/datum/config_entry/number/mc_tick_rate
abstract_type = /datum/config_entry/number/mc_tick_rate
/datum/config_entry/number/mc_tick_rate/ValidateAndSet(str_val)
. = ..()
if (.)
Master.UpdateTickRate()
/datum/config_entry/flag/resume_after_initializations
/datum/config_entry/flag/resume_after_initializations/ValidateAndSet(str_val)
. = ..()
if(. && MC_RUNNING())
world.sleep_offline = !config_entry_value
/datum/config_entry/number/rounds_until_hard_restart
default = -1
min_val = 0
/datum/config_entry/flag/auto_profile
/datum/config_entry/number/profiler_interval
default = 300 SECONDS
/datum/config_entry/number/drift_dump_threshold
default = 4 SECONDS
/datum/config_entry/number/drift_profile_delay
default = 15 SECONDS
/datum/config_entry/flag/forbid_all_profiling
/datum/config_entry/flag/forbid_admin_profiling
/datum/config_entry/flag/toast_notification_on_init
/// If admins with +DEBUG can initialize byond-tracy midround.
/datum/config_entry/flag/allow_tracy_start
protection = CONFIG_ENTRY_LOCKED
/// If admins with +DEBUG can queue byond-tracy to run the next round.
/datum/config_entry/flag/allow_tracy_queue
protection = CONFIG_ENTRY_LOCKED
@@ -161,8 +161,8 @@
/datum/emergency_shuttle_controller/proc/get_shuttle_prep_time()
// During mutiny rounds, the shuttle takes twice as long.
if(ticker && ticker.mode)
return SHUTTLE_PREPTIME * ticker.mode.shuttle_delay
if(SSticker && SSticker.mode)
return SHUTTLE_PREPTIME * SSticker.mode.shuttle_delay
return SHUTTLE_PREPTIME
+4 -1
View File
@@ -24,6 +24,9 @@ GLOBAL_REAL(Failsafe, /datum/controller/failsafe)
var/running = TRUE
/datum/controller/failsafe/New()
// Ensure usr is null, to prevent any potential weirdness resulting from the failsafe having a usr if it's manually restarted.
usr = null
// Highlander-style: there can only be one! Kill off the old and replace it with the new.
if(Failsafe != src)
if(istype(Failsafe))
@@ -149,7 +152,7 @@ GLOBAL_REAL(Failsafe, /datum/controller/failsafe)
/proc/recover_all_SS_and_recreate_master()
del(Master)
var/list/subsytem_types = subtypesof(/datum/controller/subsystem)
sortTim(subsytem_types, GLOBAL_PROC_REF(cmp_subsystem_init))
sortTim(subsytem_types, GLOBAL_PROC_REF(cmp_subsystem_init_stage))
for(var/I in subsytem_types)
new I
. = Recreate_MC()
+25 -21
View File
@@ -1,9 +1,10 @@
// See initialization order in /code/game/world.dm
GLOBAL_REAL(GLOB, /datum/controller/global_vars)
/datum/controller/global_vars
name = "Global Variables"
var/list/gvars_datum_protected_varlist
var/static/list/gvars_datum_protected_varlist
var/list/gvars_datum_in_built_vars
var/list/gvars_datum_init_order
@@ -13,30 +14,24 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
GLOB = src
var/datum/controller/exclude_these = new
gvars_datum_in_built_vars = exclude_these.vars + list("gvars_datum_protected_varlist", "gvars_datum_in_built_vars", "gvars_datum_init_order")
// I know this is dumb but the nested vars list hangs a ref to the datum. This fixes that
// I have an issue report open, lummox has not responded. It might be a FeaTuRE
// Sooo we gotta be dumb
var/list/controller_vars = exclude_these.vars.Copy()
controller_vars["vars"] = null
gvars_datum_in_built_vars = controller_vars + list(NAMEOF(src, gvars_datum_protected_varlist), NAMEOF(src, gvars_datum_in_built_vars), NAMEOF(src, gvars_datum_init_order))
log_world("[vars.len - gvars_datum_in_built_vars.len] global variables")
QDEL_IN(exclude_these, 0) //signal logging isn't ready
Initialize(exclude_these)
Initialize()
/datum/controller/global_vars/Destroy(force)
stack_trace("There was an attempt to qdel the global vars holder!")
if(!force)
return QDEL_HINT_LETMELIVE
QDEL_NULL(statclick)
gvars_datum_protected_varlist.Cut()
gvars_datum_in_built_vars.Cut()
GLOB = null
return ..()
// This is done to prevent an exploit where admins can get around protected vars
SHOULD_CALL_PARENT(FALSE)
return QDEL_HINT_IWILLGC
/datum/controller/global_vars/stat_entry(msg)
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
msg = "GLOB: [statclick.update("Edit")]"
msg = "Edit"
return msg
/datum/controller/global_vars/vv_edit_var(var_name, var_value)
@@ -44,6 +39,14 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
return FALSE
return ..()
/*
/datum/controller/global_vars/vv_get_var(var_name)
switch(var_name)
if (NAMEOF(src, vars))
return debug_variable(var_name, list(), 0, src)
return debug_variable(var_name, vars[var_name], 0, src, display_flags = VV_ALWAYS_CONTRACT_LIST)
*/
/datum/controller/global_vars/Initialize()
gvars_datum_init_order = list()
gvars_datum_protected_varlist = list(NAMEOF(src, gvars_datum_protected_varlist) = TRUE)
@@ -55,8 +58,8 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
var/list/expected_global_procs = vars - gvars_datum_in_built_vars
for(var/I in global_procs)
expected_global_procs -= replacetext("[I]", "InitGlobal", "")
var/english_missing = expected_global_procs.Join(", ")
log_world("Missing procs: [english_missing]")
log_world("Missing procs: [expected_global_procs.Join(", ")]")
for(var/I in global_procs)
var/start_tick = world.time
call(src, I)()
@@ -64,4 +67,5 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
if(end_tick - start_tick)
warning("Global [replacetext("[I]", "InitGlobal", "")] slept during initialization!")
// Someone make it so this call isn't necessary
populate_legacy_globals()
+507 -202
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -42,7 +42,7 @@ var/global/last_tick_duration = 0
transfer_controller = new
admin_notice(span_danger("Initializations complete."), R_DEBUG)
// #if UNIT_TEST
// #if UNIT_TESTS
// # define CHECK_SLEEP_MASTER // For unit tests we don't care about a smooth lobby screen experience. We care about speed.
// #else
// # define CHECK_SLEEP_MASTER if(++initialized_objects > 500) { initialized_objects=0;sleep(world.tick_lag); }
+86 -46
View File
@@ -13,27 +13,48 @@
/// Name of the subsystem - you must change this
name = "fire coderbus"
/// Order of initialization. Higher numbers are initialized first, lower numbers later. Use or create defines such as [INIT_ORDER_DEFAULT] so we can see the order in one file.
var/init_order = INIT_ORDER_DEFAULT
/// Determines which subsystems this subsystem is dependant on to initialize. Will initialize after all specified subsystems.
/// If init_stage is earlier than a dependent subsystem, will throw an error and push the init stage forward to that subsystem.
/// Usage: Put the typepaths of the subsystems that need to init before this one in this list.
var/list/dependencies = list()
/// The inverse of the dependencies. Can be set manually, but will also get evaluated at runtime. Turns into a list of instances at runtime.
/// Usage: Put the typepaths of the subsystems that need to init after this one in this list.
var/list/dependents
/// ID of the subsystem. Set automatically when the dependency graph is evaluated. Used primarily in determining order.
var/ordering_id = 0
/// Do not modify. Automatically set when the dependency graph is evaluated. Similar to ordering_id, but evaluated after init_stage.
var/init_order = 0
/// Time to wait (in deciseconds) between each call to fire(). Must be a positive integer.
var/wait = 20
/// Priority Weight: When mutiple subsystems need to run in the same tick, higher priority subsystems will be given a higher share of the tick before MC_TICK_CHECK triggers a sleep, higher priority subsystems also run before lower priority subsystems.
/// Priority Weight: When multiple subsystems need to run in the same tick, higher priority subsystems will be given a higher share of the tick before MC_TICK_CHECK triggers a sleep, higher priority subsystems also run before lower priority subsystems
var/priority = FIRE_PRIORITY_DEFAULT
/// [Subsystem Flags][SS_NO_INIT] to control binary behavior. Flags must be set at compile time or before preinit finishes to take full effect. (You can also restart the mc to force them to process again)
var/flags = NONE
/// This var is set to TRUE after the subsystem has been initialized.
var/subsystem_initialized = FALSE
/// Which stage does this subsystem init at. Earlier stages can fire while later stages init.
var/init_stage = INITSTAGE_MAIN
/// This var is set to `INITIALIZATION_INNEW_REGULAR` after the subsystem has been initialized.
var/initialized = FALSE
/// Set to 0 to prevent fire() calls, mostly for admin use or subsystems that may be resumed later
/// use the [SS_NO_FIRE] flag instead for systems that never fire to keep it from even being added to list that is checked every tick
var/can_fire = TRUE
///Bitmap of what game states can this subsystem fire at. See [RUNLEVELS_DEFAULT] for more details.
var/runlevels = RUNLEVELS_DEFAULT
var/runlevels = RUNLEVELS_DEFAULT //points of the game at which the SS can fire
/**
* boolean set by admins. if TRUE then this subsystem will stop the world profiler after ignite() returns and start it again when called.
* used so that you can audit a specific subsystem or group of subsystems' synchronous call chain.
*/
var/profiler_focused = FALSE
/*
* The following variables are managed by the MC and should not be modified directly.
@@ -54,6 +75,9 @@
/// Running average of the amount of tick usage (in percents of a game tick) the subsystem has spent past its allocated time without pausing
var/tick_overrun = 0
/// Flat list of usage and time, every odd index is a log time, every even index is a usage
var/list/rolling_usage = list()
/// How much of a tick (in percents of a tick) were we allocated last fire.
var/tick_allocation_last = 0
@@ -78,6 +102,9 @@
/// Tracks the amount of completed runs for the subsystem
var/times_fired = 0
/// How many fires have we been requested to postpone
var/postponed_fires = 0
/// Time the subsystem entered the queue, (for timing and priority reasons)
var/queued_time = 0
@@ -92,9 +119,13 @@
/// Previous subsystem in the queue of subsystems to run this tick
var/datum/controller/subsystem/queue_prev
/// String to store an applicable error message for a subsystem crashing, used to help debug crashes in contexts such as Continuous Integration/Unit Tests
var/initialization_failure_message = null
//Do not blindly add vars here to the bottom, put it where it goes above
//If your var only has two values, put it in as a flag.
//Do not override
///datum/controller/subsystem/New()
@@ -107,7 +138,7 @@
///This is used so the mc knows when the subsystem sleeps. do not override.
/datum/controller/subsystem/proc/ignite(resumed = FALSE)
SHOULD_NOT_OVERRIDE(TRUE)
set waitfor = 0
set waitfor = FALSE
. = SS_IDLE
tick_allocation_last = Master.current_ticklimit-(TICK_USAGE)
@@ -131,7 +162,7 @@
///Sleeping in here prevents future fires until returned.
/datum/controller/subsystem/proc/fire(resumed = FALSE)
flags |= SS_NO_FIRE
throw EXCEPTION("Subsystem [src]([type]) does not fire() but did not set the SS_NO_FIRE flag. Please add the SS_NO_FIRE flag to any subsystem that doesn't fire so it doesn't get added to the processing list and waste cpu.")
CRASH("Subsystem [src]([type]) does not fire() but did not set the SS_NO_FIRE flag. Please add the SS_NO_FIRE flag to any subsystem that doesn't fire so it doesn't get added to the processing list and waste cpu.")
/datum/controller/subsystem/Destroy()
dequeue()
@@ -141,6 +172,31 @@
Master.subsystems -= src
return ..()
/** Update next_fire for the next run.
* reset_time (bool) - Ignore things that would normally alter the next fire, like tick_overrun, and last_fire. (also resets postpone)
*/
/datum/controller/subsystem/proc/update_nextfire(reset_time = FALSE)
var/queue_node_flags = flags
if (reset_time)
postponed_fires = 0
if (queue_node_flags & SS_TICKER)
next_fire = world.time + (world.tick_lag * wait)
else
next_fire = world.time + wait
return
if (queue_node_flags & SS_TICKER)
next_fire = world.time + (world.tick_lag * wait)
else if (queue_node_flags & SS_POST_FIRE_TIMING)
next_fire = world.time + wait + (world.tick_lag * (tick_overrun/100))
else if (queue_node_flags & SS_KEEP_TIMING)
next_fire += wait
else
next_fire = queued_time + wait + (world.tick_lag * (tick_overrun/100))
///Queue it to run.
/// (we loop thru a linked list until we get to the end or find the right point)
/// (this lets us sort our run order correctly without having to re-sort the entire already sorted list)
@@ -155,8 +211,8 @@
queue_node_priority = queue_node.queued_priority
queue_node_flags = queue_node.flags
if (queue_node_flags & SS_TICKER)
if (!(SS_flags & SS_TICKER))
if (queue_node_flags & (SS_TICKER|SS_BACKGROUND) == SS_TICKER)
if ((SS_flags & (SS_TICKER|SS_BACKGROUND)) != SS_TICKER)
continue
if (queue_node_priority < SS_priority)
break
@@ -207,9 +263,9 @@
queue_next.queue_prev = queue_prev
if (queue_prev)
queue_prev.queue_next = queue_next
if (src == Master.queue_tail)
if (Master && (src == Master.queue_tail))
Master.queue_tail = queue_prev
if (src == Master.queue_head)
if (Master && (src == Master.queue_head))
Master.queue_head = queue_next
queued_time = 0
if (state == SS_QUEUED)
@@ -228,14 +284,13 @@
/datum/controller/subsystem/proc/OnConfigLoad()
/**
* Used to initialize the subsystem. This is expected to be overriden by subtypes.
* Used to initialize the subsystem. This is expected to be overridden by subtypes.
*/
/datum/controller/subsystem/Initialize()
return SS_INIT_NONE
//hook for printing stats to the "MC" statuspanel for admins to see performance and related stats etc.
/datum/controller/subsystem/stat_entry(msg)
if(can_fire && !(SS_NO_FIRE & flags))
if(can_fire && !(SS_NO_FIRE & flags) && init_stage <= Master.init_stage_completed)
msg = "[round(cost,1)]ms|[round(tick_usage,1)]%([round(tick_overrun,1)]%)|[round(ticks,0.1)]\t[msg]"
else
msg = "OFFLINE\t[msg]"
@@ -254,45 +309,30 @@
if (SS_IDLE)
. = " "
//could be used to postpone a costly subsystem for (default one) var/cycles, cycles
//for instance, during cpu intensive operations like explosions
/// Causes the next "cycle" fires to be missed. Effect is accumulative but can reset by calling update_nextfire(reset_time = TRUE)
/datum/controller/subsystem/proc/postpone(cycles = 1)
if(next_fire - world.time < wait)
next_fire += (wait*cycles)
if (can_fire && cycles >= 1)
postponed_fires += cycles
/// Prunes out of date entries in our rolling usage list
/datum/controller/subsystem/proc/prune_rolling_usage()
var/list/rolling_usage = src.rolling_usage
var/cut_to = 0
while(cut_to + 2 <= length(rolling_usage) && rolling_usage[cut_to + 1] < DS2TICKS(world.time - Master.rolling_usage_length))
cut_to += 2
if(cut_to)
rolling_usage.Cut(1, cut_to + 1)
//usually called via datum/controller/subsystem/New() when replacing a subsystem (i.e. due to a recurring crash)
//should attempt to salvage what it can from the old instance of subsystem
/datum/controller/subsystem/Recover()
// Suspends this subsystem from being queued for running. If already in the queue, sleeps until idle. Returns FALSE if the subsystem was already suspended.
/datum/controller/subsystem/proc/suspend()
. = (can_fire > 0) // Return true if we were previously runnable, false if previously suspended.
can_fire = FALSE
// Safely sleep in a loop until the subsystem is idle, (or its been un-suspended somehow)
while(can_fire <= 0 && state != SS_IDLE)
stoplag() // Safely sleep in a loop until
// Wakes a suspended subsystem.
/datum/controller/subsystem/proc/wake()
can_fire = TRUE
// This subsystem has destabilized the game and is being put on warning. At this point there may be
// an opportunity to clean up the subsystem or check it for errors in ways that would otherwise be too slow.
// You should log the errors/cleanup results, so you can fix the problem rather than using this as a crutch.
/datum/controller/subsystem/proc/fail()
var/msg = "[name] subsystem being blamed for MC failure"
log_world(msg)
log_game(msg)
// DO NOT ATTEMPT RECOVERY. Only log debugging info. You should leave the subsystem as it is.
// Attempting recovery here could make things worse, create hard recursions with the MC disabling it every run, etc.
/datum/controller/subsystem/proc/critfail()
var/msg = "[name] subsystem received final blame for MC failure"
log_world(msg)
log_game(msg)
/datum/controller/subsystem/vv_edit_var(var_name, var_value)
switch (var_name)
if (NAMEOF(src, can_fire))
//this is so the subsystem doesn't rapid fire to make up missed ticks causing more lag
if (var_value)
update_nextfire(reset_time = TRUE)
if (NAMEOF(src, queued_priority)) //editing this breaks things.
return FALSE
. = ..()
+1 -1
View File
@@ -3,7 +3,7 @@ GENERAL_PROTECT_DATUM(/datum/controller/subsystem/admin_verbs)
SUBSYSTEM_DEF(admin_verbs)
name = "Admin Verbs"
flags = SS_NO_FIRE
//init_stage = INITSTAGE_EARLY
init_stage = INITSTAGE_EARLY
/// A list of all admin verbs indexed by their type.
var/list/datum/admin_verb/admin_verbs_by_type = list()
/// A list of all admin verbs indexed by their visibility flag.
+5 -1
View File
@@ -1,11 +1,15 @@
SUBSYSTEM_DEF(ai)
name = "AI"
init_order = INIT_ORDER_AI
priority = FIRE_PRIORITY_AI
wait = 2 SECONDS
flags = SS_NO_INIT
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
dependencies = list(
/datum/controller/subsystem/air,
/datum/controller/subsystem/mobs
)
var/list/processing = list()
var/list/currentrun = list()
+4 -1
View File
@@ -1,11 +1,14 @@
SUBSYSTEM_DEF(aifast)
name = "AI (Fast)"
init_order = INIT_ORDER_AI_FAST
priority = FIRE_PRIORITY_AI
wait = 0.25 SECONDS // Every quarter second
flags = SS_NO_INIT
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
dependencies = list(
/datum/controller/subsystem/ai
)
var/list/processing = list()
var/list/currentrun = list()
+3 -1
View File
@@ -65,7 +65,9 @@ Class Procs:
SUBSYSTEM_DEF(air)
name = "Air"
init_order = INIT_ORDER_AIR
dependencies = list(
/datum/controller/subsystem/atoms
)
priority = FIRE_PRIORITY_AIR
wait = 2 SECONDS // seconds (We probably can speed this up actually)
flags = SS_BACKGROUND // TODO - Should this really be background? It might be important.
+1 -1
View File
@@ -6,7 +6,7 @@ SUBSYSTEM_DEF(atc)
priority = FIRE_PRIORITY_ATC
runlevels = RUNLEVEL_GAME
wait = 2 SECONDS
init_order = INIT_ORDER_ATC
init_stage = INITSTAGE_LAST
flags = SS_BACKGROUND
VAR_PRIVATE/next_tick = 0
+5
View File
@@ -16,6 +16,11 @@ SUBSYSTEM_DEF(airflow)
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
priority = FIRE_PRIORITY_AIRFLOW
dependencies = list(
/datum/controller/subsystem/atoms,
/datum/controller/subsystem/air
)
var/list/processing = list()
var/list/currentrun = list()
+3 -1
View File
@@ -2,7 +2,9 @@ SUBSYSTEM_DEF(alarm)
name = "Alarm"
wait = 2 SECONDS
priority = FIRE_PRIORITY_ALARM
init_order = INIT_ORDER_ALARM
dependencies = list(
/datum/controller/subsystem/mapping
)
var/list/datum/alarm/all_handlers
var/tmp/list/currentrun = null
var/static/list/active_alarm_cache = list()
+3 -2
View File
@@ -13,10 +13,11 @@ SUBSYSTEM_DEF(asset_loading)
while(length(generate_queue))
var/datum/asset/to_load = generate_queue[generate_queue.len]
to_load.queued_generation()
if(MC_TICK_CHECK)
return
to_load.queued_generation()
last_queue_len = length(generate_queue)
generate_queue.len--
// We just emptied the queue
+7 -2
View File
@@ -1,6 +1,11 @@
SUBSYSTEM_DEF(assets)
name = "Assets"
init_order = INIT_ORDER_ASSETS
dependencies = list(
/datum/controller/subsystem/holomaps,
/datum/controller/subsystem/robot_sprites
///datum/controller/subsystem/persistent_paintings,
///datum/controller/subsystem/greyscale_previews,
)
flags = SS_NO_FIRE
var/list/datum/asset_cache_item/cache = list()
var/list/preload = list()
@@ -32,7 +37,7 @@ SUBSYSTEM_DEF(assets)
transport.Initialize(cache)
subsystem_initialized = TRUE
initialized = TRUE
return SS_INIT_SUCCESS
/datum/controller/subsystem/assets/Recover()
+21 -13
View File
@@ -1,6 +1,14 @@
SUBSYSTEM_DEF(atoms)
name = "Atoms"
init_order = INIT_ORDER_ATOMS
dependencies = list(
/datum/controller/subsystem/garbage,
/datum/controller/subsystem/mapping,
/datum/controller/subsystem/planets,
/datum/controller/subsystem/transcore,
/datum/controller/subsystem/chemistry,
/datum/controller/subsystem/sounds,
/datum/controller/subsystem/job
)
flags = SS_NO_FIRE
/// A stack of list(source, desired initialized state)
@@ -8,7 +16,7 @@ SUBSYSTEM_DEF(atoms)
var/list/initialized_state = list()
var/base_initialized
var/initialized = INITIALIZATION_INSSATOMS
var/atom_initialized = INITIALIZATION_INSSATOMS
var/list/late_loaders = list()
var/list/BadInitializeCalls = list()
@@ -25,19 +33,19 @@ SUBSYSTEM_DEF(atoms)
var/list/mapload_init_times = list()
#endif
initialized = INITIALIZATION_INSSATOMS
atom_initialized = INITIALIZATION_INSSATOMS
/datum/controller/subsystem/atoms/Initialize()
init_start_time = world.time
initialized = INITIALIZATION_INNEW_MAPLOAD
atom_initialized = INITIALIZATION_INNEW_MAPLOAD
InitializeAtoms()
initialized = INITIALIZATION_INNEW_REGULAR
atom_initialized = INITIALIZATION_INNEW_REGULAR
return SS_INIT_SUCCESS
/datum/controller/subsystem/atoms/proc/InitializeAtoms(list/atoms, list/atoms_to_return)
if(initialized == INITIALIZATION_INSSATOMS)
if(atom_initialized == INITIALIZATION_INSSATOMS)
return
// Generate a unique mapload source for this run of InitializeAtoms
@@ -142,9 +150,9 @@ SUBSYSTEM_DEF(atoms)
/// Accepts a state and a source, the most recent state is used, sources exist to prevent overriding old values accidentally
/datum/controller/subsystem/atoms/proc/set_tracked_initalized(state, source)
if(!length(initialized_state))
base_initialized = initialized
base_initialized = atom_initialized
initialized_state += list(list(source, state))
initialized = state
atom_initialized = state
/datum/controller/subsystem/atoms/proc/clear_tracked_initalize(source)
if(!length(initialized_state))
@@ -155,18 +163,18 @@ SUBSYSTEM_DEF(atoms)
break
if(!length(initialized_state))
initialized = base_initialized
atom_initialized = base_initialized
base_initialized = INITIALIZATION_INNEW_REGULAR
return
initialized = initialized_state[length(initialized_state)][2]
atom_initialized = initialized_state[length(initialized_state)][2]
/// Returns TRUE if anything is currently being initialized
/datum/controller/subsystem/atoms/proc/initializing_something()
return length(initialized_state) > 1
/datum/controller/subsystem/atoms/Recover()
initialized = SSatoms.initialized
if(initialized == INITIALIZATION_INNEW_MAPLOAD)
atom_initialized = SSatoms.atom_initialized
if(atom_initialized == INITIALIZATION_INNEW_MAPLOAD)
InitializeAtoms()
initialized_state = SSatoms.initialized_state
BadInitializeCalls = SSatoms.BadInitializeCalls
@@ -187,7 +195,7 @@ SUBSYSTEM_DEF(atoms)
/// Prepares an atom to be deleted once the atoms SS is initialized.
/datum/controller/subsystem/atoms/proc/prepare_deletion(atom/target)
if (initialized == INITIALIZATION_INNEW_REGULAR)
if (atom_initialized == INITIALIZATION_INNEW_REGULAR)
// Atoms SS has already completed, just kill it now.
qdel(target)
else
@@ -1,6 +1,5 @@
SUBSYSTEM_DEF(character_setup)
name = "Character Setup"
init_order = INIT_ORDER_DEFAULT
priority = FIRE_PRIORITY_CHARSETUP
flags = SS_BACKGROUND | SS_NO_INIT
wait = 1 SECOND
+1 -1
View File
@@ -8,7 +8,7 @@ SUBSYSTEM_DEF(chat)
flags = SS_TICKER|SS_NO_INIT
wait = 1
priority = FIRE_PRIORITY_CHAT
init_order = INIT_ORDER_CHAT
init_stage = INITSTAGE_LAST
/// Assosciates a ckey with a list of messages to send to them.
var/list/list/datum/chat_payload/client_to_payloads = list()
+3 -1
View File
@@ -2,7 +2,9 @@ SUBSYSTEM_DEF(chemistry)
name = "Chemistry"
wait = 20
flags = SS_NO_FIRE
init_order = INIT_ORDER_CHEMISTRY
dependencies = list(
/datum/controller/subsystem/garbage
)
var/list/chemical_reactions = list()
var/list/chemical_reactions_by_product = list()
+5 -1
View File
@@ -4,8 +4,12 @@
//
SUBSYSTEM_DEF(circuit)
name = "Circuit"
init_order = INIT_ORDER_CIRCUIT
flags = SS_NO_FIRE
dependencies = list(
/datum/controller/subsystem/atoms
)
var/list/all_components = list() // Associative list of [component_name]:[component_path] pairs
var/list/cached_components = list() // Associative list of [component_path]:[component] pairs
var/list/all_assemblies = list() // Associative list of [assembly_name]:[assembly_path] pairs
@@ -0,0 +1,207 @@
/*
HOW IT WORKS
The SSradio is a global object maintaining all radio transmissions, think about it as about "ether".
Note that walkie-talkie, intercoms and headsets handle transmission using nonstandard way.
procs:
add_object(obj/device as obj, var/new_frequency as num, var/radio_filter as text|null = null)
Adds listening object.
parameters:
device - device receiving signals, must have proc receive_signal (see description below).
one device may listen several frequencies, but not same frequency twice.
new_frequency - see possibly frequencies below;
radio_filter - thing for optimization. Optional, but recommended.
All filters should be consolidated in this file, see defines later.
Device without listening filter will receive all signals (on specified frequency).
Device with filter will receive any signals sent without filter.
Device with filter will not receive any signals sent with different filter.
returns:
Reference to frequency object.
remove_object (obj/device, old_frequency)
Obliviously, after calling this proc, device will not receive any signals on old_frequency.
Other frequencies will left unaffected.
return_frequency(var/frequency as num)
returns:
Reference to frequency object. Use it if you need to send and do not need to listen.
radio_frequency is a global object maintaining list of devices that listening specific frequency.
procs:
post_signal(obj/source as obj|null, datum/signal/signal, var/radio_filter as text|null = null, var/range as num|null = null)
Sends signal to all devices that wants such signal.
parameters:
source - object, emitted signal. Usually, devices will not receive their own signals.
signal - see description below.
radio_filter - described above.
range - radius of regular byond's square circle on that z-level. null means everywhere, on all z-levels.
obj/proc/receive_signal(datum/signal/signal, var/receive_method as num, var/receive_param)
Handler from received signals. By default does nothing. Define your own for your object.
Avoid of sending signals directly from this proc, use spawn(-1). DO NOT use sleep() here or call procs that sleep please. If you must, use spawn()
parameters:
signal - see description below. Extract all needed data from the signal before doing sleep(), spawn() or return!
receive_method - may be TRANSMISSION_WIRE or TRANSMISSION_RADIO.
TRANSMISSION_WIRE is currently unused.
receive_param - for TRANSMISSION_RADIO here comes frequency.
datum/signal
vars:
source
an object that emitted signal. Used for debug and bearing.
data
list with transmitting data. Usual use pattern:
data["msg"] = "hello world"
encryption
Some number symbolizing "encryption key".
Note that game actually do not use any cryptography here.
If receiving object don't know right key, it must ignore encrypted signal in its receive_signal.
*/
SUBSYSTEM_DEF(radio)
name = "Radio"
flags = SS_NO_FIRE
dependencies = list(
/datum/controller/subsystem/machines
)
var/list/datum/radio_frequency/frequencies = list()
/datum/controller/subsystem/radio/Initialize()
GLOB.autospeaker = new (null, FALSE, null, null, TRUE) //Set up Global Announcer
return SS_INIT_SUCCESS
/datum/controller/subsystem/radio/proc/add_object(obj/device as obj, var/new_frequency as num, var/radio_filter = null as text|null)
var/f_text = num2text(new_frequency)
var/datum/radio_frequency/frequency = frequencies[f_text]
if(!frequency)
frequency = new
frequency.frequency = new_frequency
frequencies[f_text] = frequency
frequency.add_listener(device, radio_filter)
return frequency
/datum/controller/subsystem/radio/proc/remove_object(obj/device, old_frequency)
var/f_text = num2text(old_frequency)
var/datum/radio_frequency/frequency = frequencies[f_text]
if(frequency)
frequency.remove_listener(device)
if(frequency.devices.len == 0)
qdel(frequency)
frequencies -= f_text
return 1
/datum/controller/subsystem/radio/proc/return_frequency(var/new_frequency as num)
var/f_text = num2text(new_frequency)
var/datum/radio_frequency/frequency = frequencies[f_text]
if(!frequency)
frequency = new
frequency.frequency = new_frequency
frequencies[f_text] = frequency
return frequency
//Frequency channels
/datum/radio_frequency
var/frequency as num
var/list/list/obj/devices = list()
/datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, var/radio_filter = null as text|null, var/range = null as num|null)
var/turf/start_point
if(range)
start_point = get_turf(source)
if(!start_point)
qdel(signal)
return 0
if (radio_filter)
send_to_filter(source, signal, radio_filter, start_point, range)
send_to_filter(source, signal, RADIO_DEFAULT, start_point, range)
else
//Broadcast the signal to everyone!
for (var/next_filter in devices)
send_to_filter(source, signal, next_filter, start_point, range)
//Sends a signal to all machines belonging to a given filter. Should be called by post_signal()
/datum/radio_frequency/proc/send_to_filter(obj/source, datum/signal/signal, var/radio_filter, var/turf/start_point = null, var/range = null)
if (range && !start_point)
return
for(var/obj/device in devices[radio_filter])
if(device == source)
continue
if(range)
var/turf/end_point = get_turf(device)
if(!end_point)
continue
if(start_point.z!=end_point.z || get_dist(start_point, end_point) > range)
continue
device.receive_signal(signal, TRANSMISSION_RADIO, frequency)
/datum/radio_frequency/proc/add_listener(obj/device as obj, var/radio_filter as text|null)
if (!radio_filter)
radio_filter = RADIO_DEFAULT
//log_admin("add_listener(device=[device],radio_filter=[radio_filter]) frequency=[frequency]")
var/list/obj/devices_line = devices[radio_filter]
if (!devices_line)
devices_line = new
devices[radio_filter] = devices_line
devices_line+=device
// var/list/obj/devices_line___ = devices[filter_str]
// var/l = devices_line___.len
//log_admin("DEBUG: devices_line.len=[devices_line.len]")
//log_admin("DEBUG: devices(filter_str).len=[l]")
/datum/radio_frequency/proc/remove_listener(obj/device)
for (var/devices_filter in devices)
var/list/devices_line = devices[devices_filter]
devices_line-=device
while (null in devices_line)
devices_line -= null
if (devices_line.len==0)
devices -= devices_filter
/datum/signal
var/obj/source
var/transmission_method = 0 //unused at the moment
//0 = wire
//1 = radio transmission
//2 = subspace transmission
var/list/data = list()
var/encryption
var/frequency = 0
/datum/signal/proc/copy_from(datum/signal/model)
source = model.source
transmission_method = model.transmission_method
data = model.data
encryption = model.encryption
frequency = model.frequency
/datum/signal/proc/debug_print()
if (source)
. = "signal = {source = '[source]' ([source:x],[source:y],[source:z])\n"
else
. = "signal = {source = '[source]' ()\n"
for (var/i in data)
. += "data\[\"[i]\"\] = \"[data[i]]\"\n"
if(islist(data[i]))
var/list/L = data[i]
for(var/t in L)
. += "data\[\"[i]\"\] list has: [t]"
//callback used by objects to react to incoming radio signals
/obj/proc/receive_signal(datum/signal/signal, receive_method, receive_param)
return null
+4 -1
View File
@@ -1,8 +1,10 @@
SUBSYSTEM_DEF(dbcore)
name = "Database"
flags = SS_TICKER
init_stage = INITSTAGE_EARLY
wait = 10 // Not seconds because we're running on SS_TICKER
init_order = INIT_ORDER_DBCORE
runlevels = RUNLEVEL_LOBBY|RUNLEVELS_DEFAULT
priority = FIRE_PRIORITY_DATABASE
var/failed_connection_timeout = 0
@@ -41,6 +43,7 @@ SUBSYSTEM_DEF(dbcore)
//var/db_daemon_started = FALSE
/datum/controller/subsystem/dbcore/Initialize()
Connect()
return SS_INIT_SUCCESS
/datum/controller/subsystem/dbcore/stat_entry(msg)
+1
View File
@@ -1,6 +1,7 @@
SUBSYSTEM_DEF(events)
name = "Events" // VOREStation Edit - This is still the main events subsystem for us.
wait = 2 SECONDS
init_stage = INITSTAGE_LAST
var/tmp/list/currentrun = null
+3
View File
@@ -5,6 +5,9 @@ SUBSYSTEM_DEF(event_ticker)
name = "Events (Ticker)"
wait = 2 SECONDS
runlevels = RUNLEVEL_GAME
dependencies = list(
/datum/controller/subsystem/events
)
// List of `/datum/event2/event`s that are currently active, and receiving process() ticks.
var/list/active_events = list()
+1 -1
View File
@@ -96,7 +96,7 @@ SUBSYSTEM_DEF(game_master)
// These are ran before committing to an event.
// Returns TRUE if the system is allowed to procede, otherwise returns FALSE.
/datum/controller/subsystem/game_master/proc/pre_event_checks(quiet = FALSE)
if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
if(!SSticker || SSticker.current_state != GAME_STATE_PLAYING)
if(!quiet)
log_game_master("Unable to start event: Ticker is nonexistent, or the game is not ongoing.")
return FALSE
+1 -2
View File
@@ -27,8 +27,7 @@ SUBSYSTEM_DEF(garbage)
wait = 2 SECONDS
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND|SS_NO_INIT
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
init_order = INIT_ORDER_GARBAGE
// init_stage = INITSTAGE_EARLY
init_stage = INITSTAGE_FIRST
var/list/collection_timeout = list(GC_FILTER_QUEUE, GC_CHECK_QUEUE, GC_DEL_QUEUE) // deciseconds to wait before moving something up in the queue to the next level
+3 -1
View File
@@ -4,8 +4,10 @@
//
SUBSYSTEM_DEF(holomaps)
name = "HoloMiniMaps"
init_order = INIT_ORDER_HOLOMAPS
flags = SS_NO_FIRE
dependencies = list(
/datum/controller/subsystem/atoms
)
var/static/holomaps_initialized = FALSE
var/static/list/holoMiniMaps = list()
var/static/list/extraMiniMaps = list()
+1 -1
View File
@@ -1,7 +1,7 @@
SUBSYSTEM_DEF(input)
name = "Input"
wait = 1 // SS_TICKER means this runs every tick
init_order = INIT_ORDER_INPUT
init_stage = INITSTAGE_EARLY
flags = SS_TICKER | SS_NO_INIT
priority = FIRE_PRIORITY_INPUT
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
+6 -1
View File
@@ -6,7 +6,12 @@
SUBSYSTEM_DEF(internal_wiki)
name = "Wiki"
wait = 1
init_order = INIT_ORDER_WIKI
//dependencies = list(
// /datum/controller/subsystem/chemistry,
// /datum/controller/subsystem/plants,
// /datum/controller/subsystem/supply
//)
init_stage = INITSTAGE_LAST
flags = SS_NO_FIRE
VAR_PRIVATE/list/pages = list()
+3 -1
View File
@@ -1,6 +1,8 @@
SUBSYSTEM_DEF(job)
name = "Job"
init_order = INIT_ORDER_JOB
dependencies = list(
/datum/controller/subsystem/mapping,
)
flags = SS_NO_FIRE
var/list/occupations = list() //List of all jobs
+6 -4
View File
@@ -1,7 +1,9 @@
SUBSYSTEM_DEF(lighting)
name = "Lighting"
dependencies = list(
/datum/controller/subsystem/machines
)
wait = 1
init_order = INIT_ORDER_LIGHTING
flags = SS_TICKER
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY // Do some work during lobby waiting period. May as well.
var/sun_mult = 1.0
@@ -19,8 +21,8 @@ SUBSYSTEM_DEF(lighting)
/datum/controller/subsystem/lighting/Initialize()
if(!subsystem_initialized)
subsystem_initialized = TRUE
if(!initialized)
initialized = TRUE
create_all_lighting_objects()
for(var/datum/planet/planet in SSplanets.planets)
@@ -177,5 +179,5 @@ SUBSYSTEM_DEF(lighting)
/datum/controller/subsystem/lighting
/datum/controller/subsystem/lighting/Recover()
subsystem_initialized = SSlighting.subsystem_initialized
initialized = SSlighting.initialized
..()
+1 -2
View File
@@ -1,7 +1,6 @@
SUBSYSTEM_DEF(lobby_monitor)
name = "Lobby Art"
init_order = INIT_ORDER_LOBBY
// init_stage = INITSTAGE_EARLY
init_stage = INITSTAGE_EARLY
flags = SS_NO_INIT
wait = 1 SECOND
runlevels = ALL
+3 -1
View File
@@ -9,8 +9,10 @@
SUBSYSTEM_DEF(machines)
name = "Machines"
dependencies = list(
/datum/controller/subsystem/points_of_interest
)
priority = FIRE_PRIORITY_MACHINES
init_order = INIT_ORDER_MACHINES
flags = SS_KEEP_TIMING
runlevels = RUNLEVEL_GAME|RUNLEVEL_POSTGAME
+16 -2
View File
@@ -1,19 +1,32 @@
// Handles map-related tasks, mostly here to ensure it does so after the MC initializes.
SUBSYSTEM_DEF(mapping)
name = "Mapping"
init_order = INIT_ORDER_MAPPING
//dependencies = list(
// /datum/controller/subsystem/job,
///datum/controller/subsystem/processing/station,
// /datum/controller/subsystem/chemistry
// ///datum/controller/subsystem/processing/reagents
//)
dependencies = list(
///datum/controller/subsystem/garbage,
/datum/controller/subsystem/vis_overlays,
/datum/controller/subsystem/chemistry
)
flags = SS_NO_FIRE
var/list/map_templates = list()
var/obj/effect/landmark/engine_loader/engine_loader
var/list/shelter_templates = list()
// TODO: Implement Later
var/datum/map/current_map
/datum/controller/subsystem/mapping/Recover()
flags |= SS_NO_INIT // Make extra sure we don't initialize twice.
shelter_templates = SSmapping.shelter_templates
/datum/controller/subsystem/mapping/Initialize()
if(subsystem_initialized)
if(initialized)
return
world.max_z_changed() // This is to set up the player z-level list, maxz hasn't actually changed (probably)
load_map_templates()
@@ -24,6 +37,7 @@ SUBSYSTEM_DEF(mapping)
// TODO - Other stuff related to maps and areas could be moved here too. Look at /tg
// Lateload Code related to Expedition areas.
if(using_map) // VOREStation Edit: Re-enable this.
current_map = using_map
loadLateMaps()
if(CONFIG_GET(flag/generate_map)) // VOREStation Edit: Re-order this.
+1 -1
View File
@@ -1,7 +1,7 @@
SUBSYSTEM_DEF(media_tracks)
name = "Media Tracks"
flags = SS_NO_FIRE
init_order = INIT_ORDER_MEDIA_TRACKS
init_stage = INITSTAGE_EARLY
/// Every track, including secret
var/list/all_tracks = list()
+8 -10
View File
@@ -12,6 +12,12 @@ SUBSYSTEM_DEF(mobs)
flags = SS_KEEP_TIMING|SS_NO_INIT
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
dependencies = list(
/datum/controller/subsystem/atoms,
/datum/controller/subsystem/points_of_interest,
/datum/controller/subsystem/shuttles
)
var/list/currentrun = list()
var/log_extensively = FALSE
var/list/timelog = list()
@@ -96,22 +102,14 @@ SUBSYSTEM_DEF(mobs)
log_game(msg)
log_world(msg)
/datum/controller/subsystem/mobs/fail()
..()
log_recent()
/datum/controller/subsystem/mobs/critfail()
..()
log_recent()
/datum/controller/subsystem/mobs/proc/report_death(var/mob/living/L)
if(!L)
return
if(!L.key || !L.mind)
return
if(!ticker || !ticker.mode)
if(!SSticker || !SSticker.mode)
return
ticker.mode.check_win()
SSticker.mode.check_win()
// Don't bother with the rest if we've not got a DB to do anything with
if(!CONFIG_GET(flag/enable_stat_tracking) || !CONFIG_GET(flag/sql_enabled))
+3 -1
View File
@@ -1,6 +1,8 @@
SUBSYSTEM_DEF(nightshift)
name = "Night Shift"
init_order = INIT_ORDER_NIGHTSHIFT
dependencies = list(
/datum/controller/subsystem/lighting
)
priority = FIRE_PRIORITY_NIGHTSHIFT
wait = 60 SECONDS
flags = SS_NO_TICK_CHECK
+3 -1
View File
@@ -3,7 +3,9 @@ SUBSYSTEM_DEF(overlays)
flags = SS_TICKER
wait = 1 // SS_TICKER - Ticks
priority = FIRE_PRIORITY_OVERLAYS
init_order = INIT_ORDER_OVERLAY
dependencies = list(
/datum/controller/subsystem/atoms
)
/// The queue of atoms that need overlay updates.
var/static/tmp/list/queue = list()
@@ -4,8 +4,12 @@ Readme at code\modules\awaymissions\overmap_renamer\readme.md
SUBSYSTEM_DEF(overmap_renamer)
name = "Overmap Renamer"
init_order = INIT_ORDER_MAPRENAME //Loaded very late in initializations. Must come before mapping and objs. Uses both as inputs.
runlevels = RUNLEVEL_INIT
//Loaded very late in initializations. Must come before mapping and objs. Uses both as inputs.
init_stage = INITSTAGE_LAST
dependencies = list(
/datum/controller/subsystem/skybox
)
runlevels = RUNLEVEL_SETUP
flags = SS_NO_FIRE
+6 -1
View File
@@ -1,7 +1,12 @@
SUBSYSTEM_DEF(persistence)
name = "Persistence"
init_order = INIT_ORDER_PERSISTENCE
dependencies = list(
/datum/controller/subsystem/mapping,
/datum/controller/subsystem/atoms,
/datum/controller/subsystem/points_of_interest
)
flags = SS_NO_FIRE
var/list/tracking_values = list()
var/list/persistence_datums = list()
+1 -1
View File
@@ -6,7 +6,7 @@
SUBSYSTEM_DEF(ping)
name = "Ping"
priority = FIRE_PRIORITY_PING
// init_stage = INITSTAGE_EARLY
init_stage = INITSTAGE_EARLY
wait = 4 SECONDS
flags = SS_NO_INIT
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
+4 -2
View File
@@ -1,10 +1,12 @@
SUBSYSTEM_DEF(planets)
name = "Planets"
init_order = INIT_ORDER_PLANETS
priority = FIRE_PRIORITY_PLANETS
wait = 2 SECONDS
flags = SS_BACKGROUND
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
dependencies = list(
/datum/controller/subsystem/plants
)
var/static/list/planets = list()
var/static/list/z_to_planet = list()
@@ -75,7 +77,7 @@ SUBSYSTEM_DEF(planets)
if(MC_TICK_CHECK)
return
#ifndef UNIT_TEST // Don't be updating temperatures and such during unit tests
#ifndef UNIT_TESTS // Don't be updating temperatures and such during unit tests
var/list/needs_temp_update = src.needs_temp_update
while(needs_temp_update.len)
var/datum/planet/P = needs_temp_update[needs_temp_update.len]
+3 -1
View File
@@ -2,7 +2,9 @@
SUBSYSTEM_DEF(plants)
name = "Plants"
init_order = INIT_ORDER_PLANTS
dependencies = list(
/datum/controller/subsystem/mapping
)
priority = FIRE_PRIORITY_PLANTS
wait = PLANT_TICK_TIME
+3 -1
View File
@@ -3,8 +3,10 @@ SUBSYSTEM_DEF(points_of_interest)
name = "Points of Interest"
wait = 1 SECONDS
priority = FIRE_PRIORITY_POIS
init_order = INIT_ORDER_POIS
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT //POIs can be loaded mid-round.
dependencies = list(
/datum/controller/subsystem/holomaps
)
var/list/obj/effect/landmark/poi_loader/poi_queue = list()
/datum/controller/subsystem/points_of_interest/Initialize()
@@ -1,7 +1,6 @@
PROCESSING_SUBSYSTEM_DEF(instruments)
name = "Instruments"
wait = 0.5
init_order = INIT_ORDER_INSTRUMENTS
flags = SS_KEEP_TIMING
priority = FIRE_PRIORITY_INSTRUMENTS
/// List of all instrument data, associative id = datum
@@ -96,14 +96,6 @@ SUBSYSTEM_DEF(processing)
log_game(msg)
log_world(msg)
/datum/controller/subsystem/processing/fail()
..()
log_recent()
/datum/controller/subsystem/processing/critfail()
..()
log_recent()
/datum/proc/DebugSubsystemProcess(var/wait, var/times_fired, var/datum/controller/subsystem/processing/subsystem)
subsystem.debug_last_thing = src
var/start_tick = world.time
+69
View File
@@ -0,0 +1,69 @@
SUBSYSTEM_DEF(profiler)
name = "Profiler"
init_stage = INITSTAGE_FIRST
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
wait = 300 SECONDS
var/fetch_cost = 0
var/write_cost = 0
/datum/controller/subsystem/profiler/stat_entry(msg)
msg += "F:[round(fetch_cost,1)]ms"
msg += "|W:[round(write_cost,1)]ms"
return msg
/datum/controller/subsystem/profiler/Initialize()
if(CONFIG_GET(flag/auto_profile))
StartProfiling()
else
StopProfiling() //Stop the early start profiler
wait = CONFIG_GET(number/profiler_interval)
return SS_INIT_SUCCESS
/datum/controller/subsystem/profiler/OnConfigLoad()
if(CONFIG_GET(flag/auto_profile))
StartProfiling()
can_fire = TRUE
else
StopProfiling()
can_fire = FALSE
/datum/controller/subsystem/profiler/fire()
DumpFile()
/datum/controller/subsystem/profiler/Shutdown()
if(CONFIG_GET(flag/auto_profile))
DumpFile(allow_yield = FALSE)
world.Profile(PROFILE_CLEAR, type = "sendmaps")
return ..()
/datum/controller/subsystem/profiler/proc/StartProfiling()
world.Profile(PROFILE_START)
world.Profile(PROFILE_START, type = "sendmaps")
/datum/controller/subsystem/profiler/proc/StopProfiling()
world.Profile(PROFILE_STOP)
world.Profile(PROFILE_STOP, type = "sendmaps")
/datum/controller/subsystem/profiler/proc/DumpFile(allow_yield = TRUE)
var/timer = TICK_USAGE_REAL
var/current_profile_data = world.Profile(PROFILE_REFRESH, format = "json")
var/current_sendmaps_data = world.Profile(PROFILE_REFRESH, type = "sendmaps", format="json")
fetch_cost = MC_AVERAGE(fetch_cost, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
if(allow_yield)
CHECK_TICK
if(!length(current_profile_data)) //Would be nice to have explicit proc to check this
stack_trace("Warning, profiling stopped manually before dump.")
var/prof_file = file("[GLOB.log_directory]/profiler/profiler-[round(world.time * 0.1, 10)].json")
if(fexists(prof_file))
fdel(prof_file)
if(!length(current_sendmaps_data)) //Would be nice to have explicit proc to check this
stack_trace("Warning, sendmaps profiling stopped manually before dump.")
var/sendmaps_file = file("[GLOB.log_directory]/profiler/sendmaps-[round(world.time * 0.1, 10)].json")
if(fexists(sendmaps_file))
fdel(sendmaps_file)
timer = TICK_USAGE_REAL
WRITE_FILE(prof_file, current_profile_data)
WRITE_FILE(sendmaps_file, current_sendmaps_data)
write_cost = MC_AVERAGE(write_cost, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))

Some files were not shown because too many files have changed in this diff Show More