mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2026-08-27 07:08:55 +01:00
Merge branch 'master' of https://github.com/Yawn-Wider/YWPolarisVore into UpstreamMergeApril2020
This commit is contained in:
+12
-12
@@ -1,8 +1,8 @@
|
||||
# Contributing to VOREStation
|
||||
# Contributing to Yawn-Wider
|
||||
|
||||
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
|
||||
|
||||
The following is a set of guidelines for contributing to VOREStation, which is hosted in the [VOREStation Org](https://github.com/VOREStation) on GitHub.
|
||||
The following is a set of guidelines for contributing to Yawn-Wider, which is hosted in the [Yawn-Wider](https://github.com/Yawn-Wider/YWPolarisVore) on GitHub.
|
||||
These are just guidelines, not rules, use your best judgment and feel free to propose changes to this document in a pull request.
|
||||
|
||||
#### Table Of Contents
|
||||
@@ -12,7 +12,7 @@ These are just guidelines, not rules, use your best judgment and feel free to pr
|
||||
|
||||
[How Can I Contribute?](#how-can-i-contribute)
|
||||
* [Your First Code Contribution](#your-first-code-contribution)
|
||||
* [VOREStation Coding Standards](#vorestation-coding-standards)
|
||||
* [Yawn-Wider Coding Standards](#Yawn-Wider-coding-standards)
|
||||
* [Pull Requests](#pull-requests)
|
||||
* [Git Commit Messages](#git-commit-messages)
|
||||
|
||||
@@ -30,20 +30,20 @@ By participating, you are expected to uphold this code.
|
||||
|
||||
### Your First Code Contribution
|
||||
|
||||
Unsure where to begin contributing to VOREStation? You can start by looking through the issues tab.
|
||||
Unsure where to begin contributing to Yawn-Wider? You can start by looking through the issues tab.
|
||||
|
||||
### VOREStation Coding Standards
|
||||
### Yawn-Wider Coding Standards
|
||||
|
||||
Any code submissions that do not meet our coding standards are likely to be rejected, or at the very least, have a maintainer request changes on your PR. Save time and follow these standards from the start.
|
||||
|
||||
* If it is something like a bugfix that Polaris would want (the codebase we use), code it in their code and make the PR to them. We regularly update from them. They would want any general gameplay bugfixes, and things that are obviously intended to work one way, but do not. They do not have any of our fluff species (vulp, akula, fenn, etc) so do not make PRs related to that, or any vore content to them.
|
||||
* Never edit stock Polaris .DMI files. If you are confused about which .DMI files we have added and which were there originally, refer to their repository and and see if they exist (https://github.com/PolarisSS13/Polaris). All PRs with edits to stock .DMI files will be rejected.
|
||||
* If it is something like a bugfix that VoreStation or Polaris would want (the codebases we use), code it in their code and make the PR to them. We regularly update from them. They would want any general gameplay bugfixes, and things that are obviously intended to work one way, but do not. They do not have any of our fluff species (vulp, akula, fenn, etc) so do not make PRs related to that, or any vore content to them.
|
||||
* Never edit stock Polaris or Vore .DMI files. If you are confused about which .DMI files we have added and which were there originally, refer to their repository and and see if they exist (https://github.com/PolarisSS13/Polaris) (https://github.com/VOREStation/VOREStation). All PRs with edits to stock .DMI files might be rejected.
|
||||
* When changing any code in any stock Polaris .DM file, you must mark your changes:
|
||||
* For single-line changes: //VOREStation Edit - "Explanation" (Edit can also be Add for new lines or Removal if you are commenting the line out)
|
||||
* For multi-line additions: //VOREStation Edit - "Explanation" and then at the bottom of your changes, //VOREStation Edit End
|
||||
* For multi-line removals: Use a block comment (/\* xxx \*/) to comment out the existing code block (do not modify whitespace more than necessary) and at the start, it should contain /\* VOREStation Removal - "Reason"
|
||||
* For single-line changes: //Yawn-Wider Edit - "Explanation" (Edit can also be Add for new lines or Removal if you are commenting the line out)
|
||||
* For multi-line additions: //Yawn-Wider Edit - "Explanation" and then at the bottom of your changes, //Yawn-Wider Edit End
|
||||
* For multi-line removals: Use a block comment (/\* xxx \*/) to comment out the existing code block (do not modify whitespace more than necessary) and at the start, it should contain /\* Yawn-Wider Removal - "Reason"
|
||||
* Change whitespace as little as possible. Do not randomly add/remove whitespace.
|
||||
* Any new files should have "_vr" at the end. For example, "life_vr.dm". Just make them in the same location as the file they are related to.
|
||||
* Any new files should have "_yw" at the end. For example, "life_yw.dm". Just make them in the same location as the file they are related to.
|
||||
* Map changes must be in tgm format. See the [Mapmerge2 Readme] for details.
|
||||
|
||||
The `attempt_vr()` proc has been added for your convienence. It allows a many-line change to become a single-line change in the existing Polaris files, preserving mergeability and allowing better code separation while preventing your new code from causing runtimes that stop the original code from running. If you are wanting to inject new procedures into an existing proc, called `update_atoms()` for example, you would create `update_atoms_vr()` in a nearby `_vr.dm` file, and then call to it from a single line in the original `update_atoms()` with `attempt_vr()`.
|
||||
@@ -72,7 +72,7 @@ Then in our `handle_grabs_vr()` proc, if we want to avoid performing the stock g
|
||||
* Use the GitHub magic words "Fixed/Fixes/Fix, Resolved/Resolves/Resolve, Closed/Closes/Close", as in, "Closes #1928", as this will automatically close that issue when the PR is merged if it is a fix for that issue.
|
||||
|
||||
## Licensing
|
||||
VOREStation is licensed under the GNU Affero General Public License version 3, which can be found in full in LICENSE-AGPL3.txt.
|
||||
Yawn-Wider is licensed under the GNU Affero General Public License version 3, which can be found in full in LICENSE-AGPL3.txt.
|
||||
|
||||
Commits with a git authorship date prior to `1420675200 +0000` (2015/01/08 00:00) are licensed under the GNU General Public License version 3, which can be found in full in LICENSE-GPL3.txt.
|
||||
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
##### Labeler ##########################################################################################################
|
||||
# Enable "labeler" for your PR that would add labels to PRs based on the paths that are modified in the PR.
|
||||
# * matches anything but /
|
||||
# ** matches anything including /
|
||||
|
||||
labelPRBasedOnFilePath:
|
||||
# Add 'Type: Map' to any changes to .dmm files
|
||||
"Type: Map":
|
||||
- '**.dmm'
|
||||
|
||||
# Add 'Type: Map' to any changes to image files
|
||||
"Type: Icon":
|
||||
- '**.dmi'
|
||||
- '**.png'
|
||||
- '**.jpg'
|
||||
|
||||
# Add 'Type: Sound' to any change to sound files
|
||||
"Type: Sound":
|
||||
- '**.ogg'
|
||||
- '**.mp3'
|
||||
- '**.wav'
|
||||
|
||||
# Add 'Type: Fluff' to any change to *custom_items*
|
||||
"Type: Fluff":
|
||||
- '**custom_items**'
|
||||
- '**loadout_fluff**'
|
||||
|
||||
# Contains changes to system folders
|
||||
"Type: .git or .github":
|
||||
- '.github/**'
|
||||
- '.git/**'
|
||||
|
||||
##### Greetings ########################################################################################################
|
||||
# Comment to be posted to welcome users when they open their first PR
|
||||
firstPRWelcomeComment: >
|
||||
Thanks for making your first PR! Please make sure you've read the contribution guidelines as well.
|
||||
|
||||
# Comment to be posted to congratulate user on their first merged PR
|
||||
firstPRMergeComment: >
|
||||
Awesome work, congrats on your first merged pull request!
|
||||
|
||||
# Comment to be posted to on first time issues
|
||||
firstIssueWelcomeComment: >
|
||||
Thanks for opening your first issue here! Be sure to follow the issue template!
|
||||
|
||||
###### IssueLink Adder #################################################################################################
|
||||
# Insert Issue (Jira/Github etc) link in PR description based on the Issue ID in PR title.
|
||||
#insertIssueLinkInPrDescription:
|
||||
# # specify the placeholder for the issue link that should be present in the description
|
||||
# descriptionIssuePlaceholderRegexp: "^Issue link: (.*)$"
|
||||
# matchers:
|
||||
# # you can have several matches - for different types of issues
|
||||
# # only the first matching entry is replaced
|
||||
# jiraIssueMatch:
|
||||
# # specify the regexp of issue id that you can find in the title of the PR
|
||||
# # the match groups can be used to build the issue id (${1}, ${2}, etc.).
|
||||
# titleIssueIdRegexp: \[(AIRFLOW-[0-9]{4})\]
|
||||
# # the issue link to be added. ${1}, ${2} ... are replaced with the match groups from the
|
||||
# # title match (remember to use quotes)
|
||||
# descriptionIssueLink: "[${1}](https://issues.apache.org/jira/browse/${1}/)"
|
||||
# docOnlyIssueMatch:
|
||||
# titleIssueIdRegexp: \[(AIRFLOW-X{4})\]
|
||||
# descriptionIssueLink: "`Document only change, no JIRA issue`"
|
||||
|
||||
###### Title Validator #################################################################################################
|
||||
# Verifies if commit/PR titles match the regexp specified
|
||||
#verifyTitles:
|
||||
# # Regular expression that should be matched by titles of commits or PR
|
||||
# titleRegexp: ^\[AIRFLOW-[0-9]{4}\].*$|^\[AIRFLOW-XXXX\].*$
|
||||
# # If set to true, it will always check the PR title (as opposed to the individual commits).
|
||||
# alwaysUsePrTitle: true
|
||||
# # If set to true, it will only check the commit in case there is a single commit.
|
||||
# # In case of multiple commits it will check PR title.
|
||||
# # This reflects the standard behaviour of Github that for `Squash & Merge` GitHub
|
||||
# # uses the PR title rather than commit messages for the squashed commit ¯\_(ツ)_/¯
|
||||
# # For single-commit PRs it takes the squashed commit message from the commit as expected.
|
||||
# #
|
||||
# # If set to false it will check all commit messages. This is useful when you do not squash commits at merge.
|
||||
# validateEitherPrOrSingleCommitTitle: true
|
||||
# # The title the GitHub status should appear from.
|
||||
# statusTitle: "Title Validator"
|
||||
# # A custom message to be displayed when the title passes validation.
|
||||
# successMessage: "Validation successful!"
|
||||
# # A custom message to be displayed when the title fails validation.
|
||||
# # Allows insertion of ${type} (commit/PR), ${title} (the title validated) and ${regex} (the titleRegexp above).
|
||||
# failureMessage: "Wrong ${type} title: ${title}"
|
||||
|
||||
###### PR/Branch Up-To-Date Checker ####################################################################################
|
||||
# Check if the branch is up to date with master when certain files are modified
|
||||
#checkUpToDate:
|
||||
# # The default branch is "master", change the branch if you want to check against a different target branch
|
||||
# targetBranch: master
|
||||
# files:
|
||||
# # File paths that you want to check for
|
||||
# # In this example, it checks if the branch is up to date when alembic migrations are modified in the PR.
|
||||
# # It helps avoid multiple heads in alembic migrations in a collaborative development project.
|
||||
# - airflow/migrations/*
|
||||
# - airflow/migrations/**/*
|
||||
# - airflow/alembic.ini
|
||||
@@ -0,0 +1,17 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 365
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 30
|
||||
# Issues with these labels will never be considered stale
|
||||
#exemptLabels:
|
||||
# - pinned
|
||||
# - security
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: 'Status: No Response'
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
@@ -1,5 +1,7 @@
|
||||
#ignore misc BYOND files
|
||||
Thumbs.db
|
||||
vchat.db
|
||||
vchat.db*
|
||||
*.log
|
||||
*.int
|
||||
*.rsc
|
||||
|
||||
+29
-27
@@ -1,16 +1,11 @@
|
||||
#pretending we're C because otherwise ruby will initialize, even with "language: dm".
|
||||
language: c
|
||||
sudo: false
|
||||
|
||||
env:
|
||||
global:
|
||||
- BYOND_MAJOR="512"
|
||||
- BYOND_MINOR="1488"
|
||||
- MACRO_COUNT=4
|
||||
matrix:
|
||||
- TEST_DEFINE="MAP_TEST" TEST_FILE="code/_map_tests.dm" RUN="0"
|
||||
- TEST_DEFINE="AWAY_MISSION_TEST" TEST_FILE="code/_away_mission_tests.dm" RUN="0"
|
||||
- TEST_DEFINE="UNIT_TEST" TEST_FILE="code/_unit_tests.dm" RUN="1"
|
||||
|
||||
cache:
|
||||
directories:
|
||||
@@ -24,29 +19,36 @@ addons:
|
||||
- libstdc++6:i386
|
||||
- libssl-dev:i386
|
||||
|
||||
before_script:
|
||||
- chmod +x ./install-byond.sh
|
||||
- ./install-byond.sh
|
||||
before_install:
|
||||
- chmod -R +x ./tools/travis
|
||||
|
||||
install:
|
||||
- pip install --user PyYaml -q
|
||||
- pip install --user beautifulsoup4 -q
|
||||
- ./tools/travis/install_byond.sh
|
||||
|
||||
before_script:
|
||||
- shopt -s globstar
|
||||
|
||||
script:
|
||||
- shopt -s globstar
|
||||
- (! grep 'step_[xy]' maps/**/*.dmm)
|
||||
- (! grep -Pn '( |\t|;|{)tag( ?)=' maps/**/*.dmm)
|
||||
- (! find nano/templates/ -type f -exec md5sum {} + | sort | uniq -D -w 32 | grep nano)
|
||||
- (! grep -En "<\s*span\s+class\s*=\s*('[^'>]+|[^'>]+')\s*>" **/*.dm)
|
||||
- (! grep 'maps\\.*test.*' *.dme)
|
||||
- awk -f tools/indentation.awk **/*.dm
|
||||
- md5sum -c - <<< "88490b460c26947f5ec1ab1bb9fa9f17 *html/changelogs/example.yml"
|
||||
- (num=`grep -E '\\\\(red|blue|green|black|b|i[^mc])' **/*.dm | wc -l`; echo "$num escapes (expecting ${MACRO_COUNT} or less)"; [ $num -le ${MACRO_COUNT} ])
|
||||
- source $HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR}/byond/bin/byondsetup
|
||||
- python tools/TagMatcher/tag-matcher.py ../..
|
||||
# Run our test
|
||||
- cp config/example/* config/
|
||||
- echo "#define ${TEST_DEFINE} 1" > ${TEST_FILE}
|
||||
- DreamMaker vorestation.dme
|
||||
- if [ $RUN -eq 1 ]; then DreamDaemon vorestation.dmb -invisible -trusted -core 2>&1 | tee log.txt; fi
|
||||
- if [ $RUN -eq 1 ]; then grep "All Unit Tests Passed" log.txt; fi
|
||||
- ./tools/travis/compile_and_run.sh
|
||||
|
||||
# Build-specific settings
|
||||
jobs:
|
||||
include:
|
||||
- stage: "File Tests" #This is the odd man out, with specific installs and stuff.
|
||||
name: "Validate Files"
|
||||
install: #Need python for some of the tag matching stuff
|
||||
- pip install --user PyYaml -q
|
||||
- pip install --user beautifulsoup4 -q
|
||||
script: ./tools/travis/validate_files.sh
|
||||
addons:
|
||||
apt:
|
||||
packages: ~ # Don't need any packages for this
|
||||
- stage: "Unit Tests"
|
||||
env: TEST_DEFINE="UNIT_TEST" TEST_FILE="code/_unit_tests.dm" RUN="1"
|
||||
name: "Compile normally (unit tests)"
|
||||
- stage: "Isolation Tests"
|
||||
env: TEST_DEFINE="MAP_TEST" TEST_FILE="code/_map_tests.dm" RUN="0"
|
||||
name: "Compile POIs (no run)"
|
||||
- env: TEST_DEFINE="AWAY_MISSION_TEST" TEST_FILE="code/_away_mission_tests.dm" RUN="0"
|
||||
name: "Compile away missions (no run)"
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
|
||||
|
||||
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
|
||||
|
||||
1. Definitions
|
||||
|
||||
"Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License.
|
||||
"Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(g) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License.
|
||||
"Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership.
|
||||
"License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, Noncommercial, ShareAlike.
|
||||
"Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License.
|
||||
"Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast.
|
||||
"Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work.
|
||||
"You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
|
||||
"Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images.
|
||||
"Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium.
|
||||
|
||||
2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws.
|
||||
|
||||
3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:
|
||||
|
||||
to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections;
|
||||
to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified.";
|
||||
to Distribute and Publicly Perform the Work including as incorporated in Collections; and,
|
||||
to Distribute and Publicly Perform Adaptations.
|
||||
|
||||
The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved, including but not limited to the rights described in Section 4(e).
|
||||
|
||||
4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:
|
||||
|
||||
You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(d), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(d), as requested.
|
||||
You may Distribute or Publicly Perform an Adaptation only under: (i) the terms of this License; (ii) a later version of this License with the same License Elements as this License; (iii) a Creative Commons jurisdiction license (either this or a later license version) that contains the same License Elements as this License (e.g., Attribution-NonCommercial-ShareAlike 3.0 US) ("Applicable License"). You must include a copy of, or the URI, for Applicable License with every copy of each Adaptation You Distribute or Publicly Perform. You may not offer or impose any terms on the Adaptation that restrict the terms of the Applicable License or the ability of the recipient of the Adaptation to exercise the rights granted to that recipient under the terms of the Applicable License. You must keep intact all notices that refer to the Applicable License and to the disclaimer of warranties with every copy of the Work as included in the Adaptation You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Adaptation, You may not impose any effective technological measures on the Adaptation that restrict the ability of a recipient of the Adaptation from You to exercise the rights granted to that recipient under the terms of the Applicable License. This Section 4(b) applies to the Adaptation as incorporated in a Collection, but this does not require the Collection apart from the Adaptation itself to be made subject to the terms of the Applicable License.
|
||||
You may not exercise any of the rights granted to You in Section 3 above in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. The exchange of the Work for other copyrighted works by means of digital file-sharing or otherwise shall not be considered to be intended for or directed toward commercial advantage or private monetary compensation, provided there is no payment of any monetary compensation in con-nection with the exchange of copyrighted works.
|
||||
If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and, (iv) consistent with Section 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4(d) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties.
|
||||
|
||||
For the avoidance of doubt:
|
||||
Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License;
|
||||
Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License if Your exercise of such rights is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(c) and otherwise waives the right to collect royalties through any statutory or compulsory licensing scheme; and,
|
||||
Voluntary License Schemes. The Licensor reserves the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License that is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(c).
|
||||
Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise.
|
||||
|
||||
5. Representations, Warranties and Disclaimer
|
||||
|
||||
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING AND TO THE FULLEST EXTENT PERMITTED BY APPLICABLE LAW, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO THIS EXCLUSION MAY NOT APPLY TO YOU.
|
||||
|
||||
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
7. Termination
|
||||
|
||||
This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
|
||||
Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.
|
||||
|
||||
8. Miscellaneous
|
||||
|
||||
Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
|
||||
Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License.
|
||||
If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
|
||||
No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
|
||||
This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.
|
||||
The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law.
|
||||
@@ -1,17 +1,17 @@
|
||||
# VOREStation
|
||||
# Yawn-Wider
|
||||
|
||||
[](http://forthebadge.com) [](http://forthebadge.com) [](http://forthebadge.com)
|
||||
|
||||
[Website](https://vore-station.net) - [Forums](https://forum.vore-station.net/) - [Wiki](https://wiki.vore-station.net/)
|
||||
[Website (we dont have one)](https://www.youtube.com/watch?v=oHg5SJYRHA0) - [Forums](https://yawn-widerstation.proboards.com/) - [Wiki](https://www.yawn.ocry.com/index.php?title=Main_Page) - [Discord](https://discord.gg/Wh27EAY)
|
||||
|
||||
Going to make a Pull Request? Make sure you read the [CONTRIBUTING.md](.github/CONTRIBUTING.md) first!
|
||||
|
||||
VOREStation is a fork of the Polaris code branch, itself a fork of the Baystation12 code branch, for the game Space Station 13.
|
||||
Yawn-Wider is a fork of the VOREStation code branch which is a fork of the Polaris code branch, itself a fork of the Baystation12 code branch, for the game Space Station 13.
|
||||
|
||||
---
|
||||
|
||||
### LICENSE
|
||||
The code for VOREStation is licensed under the [GNU Affero General Public License](http://www.gnu.org/licenses/agpl.html) version 3, which can be found in full in LICENSE-AGPL3.txt.
|
||||
The code for Yawn-Wider is licensed under the [GNU Affero General Public License](http://www.gnu.org/licenses/agpl.html) version 3, which can be found in full in LICENSE-AGPL3.txt.
|
||||
|
||||
Code with a git authorship date prior to `1420675200 +0000` (2015/01/08 00:00) are licensed under the GNU General Public License version 3, which can be found in full in LICENSE-GPL3.txt.
|
||||
|
||||
@@ -21,16 +21,24 @@ If you wish to develop and host this codebase in a closed source manner you may
|
||||
|
||||
See [here](https://www.gnu.org/licenses/why-affero-gpl.html) for more information.
|
||||
|
||||
Any files located in the
|
||||
`vorestation/goon`,
|
||||
`vorestation/icons/goonstation`, or
|
||||
`vorestation/sound/goonstation`
|
||||
directories, or any subdirectories of mentioned directories are licensed under the
|
||||
Creative Commons 3.0 BY-NC-SA license
|
||||
(https://creativecommons.org/licenses/by-nc-sa/3.0)
|
||||
|
||||
All assets including icons and sound are under a [CC BY-SA 3.0](http://creativecommons.org/licenses/by-sa/3.0/) license unless otherwise indicated.
|
||||
|
||||
### GETTING THE CODE
|
||||
The simplest way to obtain the code is using the github .zip feature. If you do this, you won't be able to make a Pull Request later, though. You'll need to use the git method.
|
||||
|
||||
Click [here](https://github.com/VOREStation/VOREStation/archive/master.zip) to get the latest code as a .zip file, then unzip it to wherever you want.
|
||||
Click [here](https://github.com/Yawn-Wider/YWPolarisVore/archive/master.zip) to get the latest code as a .zip file, then unzip it to wherever you want.
|
||||
|
||||
The more complicated and easier to update method is using git. You'll need to download git or some client from [here](http://git-scm.com/). When that's installed, right click in any folder and click on "Git Bash". When that opens, type in:
|
||||
|
||||
git clone https://github.com/VOREStation/VOREStation.git
|
||||
git clone https://github.com/Yawn-Wider/YWPolarisVore.git
|
||||
|
||||
(hint: hold down ctrl and press insert to paste into git bash)
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
set name = "Toggle Debug Messages"
|
||||
set category = "Debug"
|
||||
M.debug = !M.debug
|
||||
usr << "[M]: Debug messages toggled [M.debug? "on" : "off"]."
|
||||
to_chat(usr, "[M]: Debug messages toggled [M.debug? "on" : "off"].")
|
||||
|
||||
//Generalized gas pumping proc.
|
||||
//Moves gas from one gas_mixture to another and returns the amount of power needed (assuming 1 second), or -1 if no gas was pumped.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#define MATERIAL_ALGAE "algae"
|
||||
#define MATERIAL_CARBON "carbon"
|
||||
#define MAT_ALGAE "algae"
|
||||
|
||||
/obj/machinery/atmospherics/binary/algae_farm
|
||||
name = "algae oxygen generator"
|
||||
@@ -10,15 +9,15 @@
|
||||
anchored = 1
|
||||
density = 1
|
||||
power_channel = EQUIP
|
||||
use_power = 1
|
||||
use_power = USE_POWER_IDLE
|
||||
idle_power_usage = 100 // Minimal lights to keep algae alive
|
||||
active_power_usage = 5000 // Powerful grow lights to stimulate oxygen production
|
||||
//power_rating = 7500 //7500 W ~ 10 HP
|
||||
pipe_flags = PIPING_DEFAULT_LAYER_ONLY|PIPING_ONE_PER_TURF
|
||||
|
||||
var/list/stored_material = list(MATERIAL_ALGAE = 0, MATERIAL_CARBON = 0)
|
||||
var/list/stored_material = list(MAT_ALGAE = 0, MAT_GRAPHITE = 0)
|
||||
// Capacity increases with matter bin quality
|
||||
var/list/storage_capacity = list(MATERIAL_ALGAE = 10000, MATERIAL_CARBON = 10000)
|
||||
var/list/storage_capacity = list(MAT_ALGAE = 10000, MAT_GRAPHITE = 10000)
|
||||
// Speed at which we convert CO2 to O2. Increases with manipulator quality
|
||||
var/moles_per_tick = 1
|
||||
// Power required to convert one mole of CO2 to O2 (this is powering the grow lights). Improves with capacitors
|
||||
@@ -35,7 +34,7 @@
|
||||
var/const/output_gas = "oxygen"
|
||||
|
||||
/obj/machinery/atmospherics/binary/algae_farm/filled
|
||||
stored_material = list(MATERIAL_ALGAE = 10000, MATERIAL_CARBON = 0)
|
||||
stored_material = list(MAT_ALGAE = 10000, MAT_GRAPHITE = 0)
|
||||
|
||||
/obj/machinery/atmospherics/binary/algae_farm/New()
|
||||
..()
|
||||
@@ -58,10 +57,10 @@
|
||||
..()
|
||||
recent_moles_transferred = 0
|
||||
|
||||
if(inoperable() || use_power < 2)
|
||||
if(inoperable() || use_power < USE_POWER_ACTIVE)
|
||||
ui_error = null
|
||||
update_icon()
|
||||
if(use_power == 1)
|
||||
if(use_power == USE_POWER_IDLE)
|
||||
last_power_draw = idle_power_usage
|
||||
else
|
||||
last_power_draw = 0
|
||||
@@ -70,17 +69,17 @@
|
||||
last_power_draw = active_power_usage
|
||||
|
||||
// STEP 1 - Check material resources
|
||||
if(stored_material[MATERIAL_ALGAE] < algae_per_mole)
|
||||
ui_error = "Insufficient [material_display_name(MATERIAL_ALGAE)] to process."
|
||||
if(stored_material[MAT_ALGAE] < algae_per_mole)
|
||||
ui_error = "Insufficient [material_display_name(MAT_ALGAE)] to process."
|
||||
update_icon()
|
||||
return
|
||||
if(stored_material[MATERIAL_CARBON] + carbon_per_mole > storage_capacity[MATERIAL_CARBON])
|
||||
ui_error = "[material_display_name(MATERIAL_CARBON)] output storage is full."
|
||||
if(stored_material[MAT_GRAPHITE] + carbon_per_mole > storage_capacity[MAT_GRAPHITE])
|
||||
ui_error = "[material_display_name(MAT_GRAPHITE)] output storage is full."
|
||||
update_icon()
|
||||
return
|
||||
var/moles_to_convert = min(moles_per_tick,\
|
||||
stored_material[MATERIAL_ALGAE] * algae_per_mole,\
|
||||
storage_capacity[MATERIAL_CARBON] - stored_material[MATERIAL_CARBON])
|
||||
stored_material[MAT_ALGAE] * algae_per_mole,\
|
||||
storage_capacity[MAT_GRAPHITE] - stored_material[MAT_GRAPHITE])
|
||||
|
||||
// STEP 2 - Take the CO2 out of the input!
|
||||
var/power_draw = scrub_gas(src, list(input_gas), air1, internal, moles_to_convert)
|
||||
@@ -101,8 +100,8 @@
|
||||
var/converted_moles = min(co2_moles, moles_per_tick)
|
||||
use_power(converted_moles * power_per_mole)
|
||||
last_power_draw += converted_moles * power_per_mole
|
||||
stored_material[MATERIAL_ALGAE] -= converted_moles * algae_per_mole
|
||||
stored_material[MATERIAL_CARBON] += converted_moles * carbon_per_mole
|
||||
stored_material[MAT_ALGAE] -= converted_moles * algae_per_mole
|
||||
stored_material[MAT_GRAPHITE] += converted_moles * carbon_per_mole
|
||||
|
||||
// STEP 5 - Output the converted oxygen. Fow now we output for free!
|
||||
internal.adjust_gas(input_gas, -converted_moles)
|
||||
@@ -114,7 +113,7 @@
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/binary/algae_farm/update_icon()
|
||||
if(inoperable() || !anchored || use_power < 2)
|
||||
if(inoperable() || !anchored || use_power < USE_POWER_ACTIVE)
|
||||
icon_state = "algae-off"
|
||||
else if(recent_moles_transferred >= moles_per_tick)
|
||||
icon_state = "algae-full"
|
||||
@@ -215,13 +214,13 @@
|
||||
|
||||
// Queue management can be done even while busy
|
||||
if(href_list["activate"])
|
||||
update_use_power(2)
|
||||
update_use_power(USE_POWER_ACTIVE)
|
||||
update_icon()
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
if(href_list["deactivate"])
|
||||
update_use_power(1)
|
||||
update_use_power(USE_POWER_IDLE)
|
||||
update_icon()
|
||||
updateUsrDialog()
|
||||
return
|
||||
@@ -275,7 +274,7 @@
|
||||
return 1
|
||||
|
||||
/material/algae
|
||||
name = MATERIAL_ALGAE
|
||||
name = MAT_ALGAE
|
||||
stack_type = /obj/item/stack/material/algae
|
||||
icon_colour = "#557722"
|
||||
shard_type = SHARD_STONE_PIECE
|
||||
@@ -288,29 +287,9 @@
|
||||
name = "algae sheet"
|
||||
icon_state = "sheet-uranium"
|
||||
color = "#557722"
|
||||
default_type = MATERIAL_ALGAE
|
||||
default_type = MAT_ALGAE
|
||||
|
||||
/obj/item/stack/material/algae/ten
|
||||
amount = 10
|
||||
|
||||
/material/carbon
|
||||
name = MATERIAL_CARBON
|
||||
stack_type = /obj/item/stack/material/carbon
|
||||
icon_colour = "#303030"
|
||||
shard_type = SHARD_SPLINTER
|
||||
weight = 5
|
||||
hardness = 20
|
||||
icon_base = "stone"
|
||||
icon_reinf = "reinf_stone"
|
||||
door_icon_base = "stone"
|
||||
sheet_singular_name = "sheet"
|
||||
sheet_plural_name = "sheets"
|
||||
|
||||
/obj/item/stack/material/carbon
|
||||
name = "carbon sheet"
|
||||
icon_state = "sheet-metal"
|
||||
color = "#303030"
|
||||
default_type = MATERIAL_CARBON
|
||||
|
||||
#undef MATERIAL_ALGAE
|
||||
#undef MATERIAL_CARBON
|
||||
#undef MAT_ALGAE
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/obj/machinery/atmospherics/binary
|
||||
dir = SOUTH
|
||||
initialize_directions = SOUTH|NORTH
|
||||
use_power = 1
|
||||
use_power = USE_POWER_IDLE
|
||||
|
||||
var/datum/gas_mixture/air1
|
||||
var/datum/gas_mixture/air2
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
level = 1
|
||||
|
||||
use_power = 0
|
||||
use_power = USE_POWER_OFF
|
||||
idle_power_usage = 150 //internal circuitry, friction losses and stuff
|
||||
power_rating = 7500 //7500 W ~ 10 HP
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
|
||||
/obj/machinery/atmospherics/binary/dp_vent_pump/examine(mob/user)
|
||||
if(..(user, 1))
|
||||
user << "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W"
|
||||
to_chat(user, "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W")
|
||||
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/power_change()
|
||||
@@ -214,10 +214,10 @@
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
|
||||
return 0
|
||||
if(signal.data["power"])
|
||||
use_power = text2num(signal.data["power"])
|
||||
update_use_power(text2num(signal.data["power"]))
|
||||
|
||||
if(signal.data["power_toggle"])
|
||||
use_power = !use_power
|
||||
update_use_power(!use_power)
|
||||
|
||||
if(signal.data["direction"])
|
||||
pump_direction = text2num(signal.data["direction"])
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
name = "pressure regulator"
|
||||
desc = "A one-way air valve that can be used to regulate input or output pressure, and flow rate. Does not require power."
|
||||
|
||||
use_power = 0
|
||||
use_power = USE_POWER_OFF
|
||||
|
||||
var/unlocked = 0 //If 0, then the valve is locked closed, otherwise it is open(-able, it's a one-way valve so it closes if gas would flow backwards).
|
||||
var/target_pressure = ONE_ATMOSPHERE
|
||||
@@ -67,6 +67,8 @@
|
||||
pressure_delta = input_starting_pressure - target_pressure
|
||||
if (REGULATE_OUTPUT)
|
||||
pressure_delta = target_pressure - output_starting_pressure
|
||||
if (REGULATE_NONE)
|
||||
pressure_delta = input_starting_pressure - output_starting_pressure
|
||||
|
||||
//-1 if pump_gas() did not move any gas, >= 0 otherwise
|
||||
var/returnval = -1
|
||||
@@ -82,9 +84,46 @@
|
||||
transfer_moles = min(transfer_moles, calculate_transfer_moles(air2, air1, pressure_delta, (network1)? network1.volume : 0))
|
||||
if (REGULATE_OUTPUT)
|
||||
transfer_moles = min(transfer_moles, calculate_transfer_moles(air1, air2, pressure_delta, (network2)? network2.volume : 0))
|
||||
if (REGULATE_NONE)
|
||||
var/source = air1
|
||||
var/sink = air2
|
||||
// If node1 is a network of more than 1 pipe, we want to transfer from that whole network, otw use just node1, as current
|
||||
if(istype(node1, /obj/machinery/atmospherics/pipe))
|
||||
var/obj/machinery/atmospherics/pipe/p = node1
|
||||
if(istype(p.parent, /datum/pipeline)) // Nested if-blocks to avoid the mystical :
|
||||
var/datum/pipeline/l = p.parent
|
||||
if(istype(l.air, /datum/gas_mixture))
|
||||
source = l.air
|
||||
// If node2 is a network of more than 1 pipe, we want to transfer to that whole network, otw use just node2, as current
|
||||
if(istype(node2, /obj/machinery/atmospherics/pipe))
|
||||
var/obj/machinery/atmospherics/pipe/p = node2
|
||||
if(istype(p.parent, /datum/pipeline))
|
||||
var/datum/pipeline/l = p.parent
|
||||
if(istype(l.air, /datum/gas_mixture))
|
||||
sink = l.air
|
||||
transfer_moles = max(0, calculate_equalize_moles(source, sink)) // Not regulated, don't care about flow rate
|
||||
|
||||
//pump_gas() will return a negative number if no flow occurred
|
||||
returnval = pump_gas_passive(src, air1, air2, transfer_moles)
|
||||
if(regulate_mode == REGULATE_NONE) // ACTUALLY move gases from the whole network, not just the immediate pipes
|
||||
var/source = air1
|
||||
var/sink = air2
|
||||
// If node1 is a network of more than 1 pipe, we want to transfer from that whole network, otw use just node1, as current
|
||||
if(istype(node1, /obj/machinery/atmospherics/pipe))
|
||||
var/obj/machinery/atmospherics/pipe/p = node1
|
||||
if(istype(p.parent, /datum/pipeline)) // Nested if-blocks to avoid the mystical :
|
||||
var/datum/pipeline/l = p.parent
|
||||
if(istype(l.air, /datum/gas_mixture))
|
||||
source = l.air
|
||||
// If node2 is a network of more than 1 pipe, we want to transfer to that whole network, otw use just node2, as current
|
||||
if(istype(node2, /obj/machinery/atmospherics/pipe))
|
||||
var/obj/machinery/atmospherics/pipe/p = node2
|
||||
if(istype(p.parent, /datum/pipeline))
|
||||
var/datum/pipeline/l = p.parent
|
||||
if(istype(l.air, /datum/gas_mixture))
|
||||
sink = l.air
|
||||
returnval = pump_gas_passive(src, source, sink, transfer_moles)
|
||||
else
|
||||
returnval = pump_gas_passive(src, air1, air2, transfer_moles)
|
||||
|
||||
if (returnval >= 0)
|
||||
if(network1)
|
||||
|
||||
@@ -237,10 +237,9 @@
|
||||
var/kin_to_el_ratio = 0.1 //How much kinetic energy will be taken from turbine and converted into electricity
|
||||
var/obj/machinery/atmospherics/pipeturbine/turbine
|
||||
|
||||
/obj/machinery/power/turbinemotor/New()
|
||||
..()
|
||||
spawn(1)
|
||||
updateConnection()
|
||||
/obj/machinery/power/turbinemotor/Initialize()
|
||||
. = ..()
|
||||
updateConnection()
|
||||
|
||||
/obj/machinery/power/turbinemotor/proc/updateConnection()
|
||||
turbine = null
|
||||
|
||||
@@ -26,7 +26,7 @@ Thus, the two variables affect pump operation are set in New():
|
||||
|
||||
//var/max_volume_transfer = 10000
|
||||
|
||||
use_power = 0
|
||||
use_power = USE_POWER_OFF
|
||||
idle_power_usage = 150 //internal circuitry, friction losses and stuff
|
||||
power_rating = 7500 //7500 W ~ 10 HP
|
||||
|
||||
@@ -47,7 +47,7 @@ Thus, the two variables affect pump operation are set in New():
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/on
|
||||
icon_state = "map_on"
|
||||
use_power = 1
|
||||
use_power = USE_POWER_IDLE
|
||||
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/update_icon()
|
||||
@@ -160,12 +160,12 @@ Thus, the two variables affect pump operation are set in New():
|
||||
|
||||
if(signal.data["power"])
|
||||
if(text2num(signal.data["power"]))
|
||||
use_power = 1
|
||||
update_use_power(USE_POWER_IDLE)
|
||||
else
|
||||
use_power = 0
|
||||
update_use_power(USE_POWER_OFF)
|
||||
|
||||
if("power_toggle" in signal.data)
|
||||
use_power = !use_power
|
||||
update_use_power(!use_power)
|
||||
|
||||
if(signal.data["set_output_pressure"])
|
||||
target_pressure = between(
|
||||
@@ -199,7 +199,7 @@ Thus, the two variables affect pump operation are set in New():
|
||||
if(..()) return 1
|
||||
|
||||
if(href_list["power"])
|
||||
use_power = !use_power
|
||||
update_use_power(!use_power)
|
||||
|
||||
switch(href_list["set_press"])
|
||||
if ("min")
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
power_rating = 15000 //15000 W ~ 20 HP
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/high_power/on
|
||||
use_power = 1
|
||||
use_power = USE_POWER_IDLE
|
||||
icon_state = "map_on"
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/high_power/update_icon()
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
var/datum/omni_port/input
|
||||
var/datum/omni_port/output
|
||||
|
||||
use_power = 1
|
||||
use_power = USE_POWER_IDLE
|
||||
idle_power_usage = 150 //internal circuitry, friction losses and stuff
|
||||
power_rating = 7500 //7500 W ~ 10 HP
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/omni/atmos_filter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
usr.set_machine(src)
|
||||
user.set_machine(src)
|
||||
|
||||
var/list/data = new()
|
||||
|
||||
@@ -161,13 +161,13 @@
|
||||
switch(href_list["command"])
|
||||
if("power")
|
||||
if(!configuring)
|
||||
use_power = !use_power
|
||||
update_use_power(!use_power)
|
||||
else
|
||||
use_power = 0
|
||||
update_use_power(USE_POWER_OFF)
|
||||
if("configure")
|
||||
configuring = !configuring
|
||||
if(configuring)
|
||||
use_power = 0
|
||||
update_use_power(USE_POWER_OFF)
|
||||
|
||||
//only allows config changes when in configuring mode ~otherwise you'll get weird pressure stuff going on
|
||||
if(configuring && !use_power)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
icon_state = "map_mixer"
|
||||
pipe_state = "omni_mixer"
|
||||
|
||||
use_power = 1
|
||||
use_power = USE_POWER_IDLE
|
||||
idle_power_usage = 150 //internal circuitry, friction losses and stuff
|
||||
power_rating = 3700 //3700 W ~ 5 HP
|
||||
|
||||
@@ -178,13 +178,13 @@
|
||||
switch(href_list["command"])
|
||||
if("power")
|
||||
if(!configuring)
|
||||
use_power = !use_power
|
||||
update_use_power(!use_power)
|
||||
else
|
||||
use_power = 0
|
||||
update_use_power(USE_POWER_OFF)
|
||||
if("configure")
|
||||
configuring = !configuring
|
||||
if(configuring)
|
||||
use_power = 0
|
||||
update_use_power(USE_POWER_OFF)
|
||||
|
||||
//only allows config changes when in configuring mode ~otherwise you'll get weird pressure stuff going on
|
||||
if(configuring && !use_power)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
name = "omni device"
|
||||
icon = 'icons/atmos/omni_devices_vr.dmi' //VOREStation Edit - New Icon
|
||||
icon_state = "base"
|
||||
use_power = 1
|
||||
use_power = USE_POWER_IDLE
|
||||
initialize_directions = 0
|
||||
construction_type = /obj/item/pipe/quaternary
|
||||
level = 1
|
||||
@@ -67,7 +67,7 @@
|
||||
last_flow_rate = 0
|
||||
|
||||
if(error_check())
|
||||
use_power = 0
|
||||
update_use_power(USE_POWER_OFF)
|
||||
|
||||
if((stat & (NOPOWER|BROKEN)) || !use_power)
|
||||
return 0
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
var/datum/pipe_network/network
|
||||
|
||||
var/on = 0
|
||||
use_power = 0
|
||||
use_power = USE_POWER_OFF
|
||||
level = 1
|
||||
|
||||
/obj/machinery/atmospherics/portables_connector/init_dir()
|
||||
|
||||
@@ -7,6 +7,7 @@ GLOBAL_LIST_EMPTY(shutoff_valves)
|
||||
|
||||
name = "automatic shutoff valve"
|
||||
desc = "An automatic valve with control circuitry and pipe integrity sensor, capable of automatically isolating damaged segments of the pipe network."
|
||||
description_info = "Clicking this will toggle the automatic control. Alt-clicking this when the automatic control is disabled will manually open or close the valve."
|
||||
var/close_on_leaks = TRUE // If false it will be always open
|
||||
level = 1
|
||||
|
||||
@@ -37,21 +38,97 @@ GLOBAL_LIST_EMPTY(shutoff_valves)
|
||||
to_chat(user, "You [close_on_leaks ? "enable" : "disable"] the automatic shutoff circuit.")
|
||||
return TRUE
|
||||
|
||||
// Alt+Click now toggles the open/close function, when the autoseal is disabled
|
||||
/obj/machinery/atmospherics/valve/shutoff/AltClick(var/mob/user)
|
||||
if(isliving(user))
|
||||
if(close_on_leaks)
|
||||
to_chat(user, "You try to manually [open ? "close" : "open"] the valve, but it [open ? "opens" : "closes"] automatically again.")
|
||||
return
|
||||
|
||||
open ? close() : open()
|
||||
to_chat(user, "You manually [open ? "open" : "close"] the valve.")
|
||||
|
||||
/obj/machinery/atmospherics/valve/shutoff/process()
|
||||
..()
|
||||
|
||||
if (!network_node1 || !network_node2)
|
||||
if(open)
|
||||
if(!network_node1 || !network_node2 || !node1 || !node2)
|
||||
if(open && close_on_leaks)
|
||||
close()
|
||||
return
|
||||
|
||||
if (!close_on_leaks)
|
||||
if (!open)
|
||||
if(close_on_leaks)
|
||||
if(open && (network_node1.leaks.len || network_node2.leaks.len))
|
||||
find_leaks() // If we can see the leak, then this will find it, close the valve, and cut off that network
|
||||
// If we cannot see the leak, then this will not close the valve, and any valves that can see the leak will cut it off from us
|
||||
else if(!open && !network_node1.leaks.len && !network_node2.leaks.len)
|
||||
open()
|
||||
return
|
||||
|
||||
// Breadth-first search for any leaking pipes that we can directly see
|
||||
/obj/machinery/atmospherics/valve/shutoff/proc/find_leaks()
|
||||
var/obj/machinery/atmospherics/list/search = list()
|
||||
|
||||
// We're the leak!
|
||||
if(!node1 || !node2)
|
||||
close()
|
||||
return
|
||||
|
||||
if (network_node1.leaks.len || network_node2.leaks.len)
|
||||
if (open)
|
||||
close()
|
||||
else if (!open)
|
||||
open()
|
||||
// Only searching pipes
|
||||
if(istype(node1, /obj/machinery/atmospherics))
|
||||
search |= node1
|
||||
if(istype(node2, /obj/machinery/atmospherics))
|
||||
search |= node2
|
||||
|
||||
// Breadth-first search
|
||||
for(var/i = 1, i <= search.len, i++) // wooo, proper for loop syntax!
|
||||
var/obj/machinery/atmospherics/A = search[i]
|
||||
if(!A)
|
||||
continue
|
||||
|
||||
if(istype(A, /obj/machinery/atmospherics/pipe))
|
||||
var/obj/machinery/atmospherics/pipe/L = A
|
||||
if(L.leaking)
|
||||
close() // Found the leak!
|
||||
return
|
||||
|
||||
|
||||
if(istype(A, /obj/machinery/atmospherics/valve/shutoff))
|
||||
var/obj/machinery/atmospherics/valve/shutoff/S = A
|
||||
if(S.close_on_leaks || !S.open)
|
||||
continue // Either it will close, or it is closed. We don't care what's on the other side
|
||||
search |= list(S.node1, S.node2) // |= skips existing nodes, so we don't search loops infinitely
|
||||
|
||||
else if(istype(A, /obj/machinery/atmospherics/valve)) // Putting the shutoff before this means this won't catch shutoffs
|
||||
var/obj/machinery/atmospherics/valve/V = A
|
||||
if(V.open)
|
||||
search |= list(V.node1, V.node2)
|
||||
else
|
||||
continue // Closed valve, dead end
|
||||
|
||||
else if(istype(A, /obj/machinery/atmospherics/tvalve))
|
||||
var/obj/machinery/atmospherics/tvalve/T = A
|
||||
if(T.state)
|
||||
search |= list(T.node1, T.node2)
|
||||
else
|
||||
search |= list(T.node1, T.node3)
|
||||
|
||||
else if(istype(A, /obj/machinery/atmospherics/pipe/zpipe))
|
||||
var/obj/machinery/atmospherics/pipe/zpipe/P = A
|
||||
search |= list(P.node1, P.node2)
|
||||
|
||||
else if(istype(A, /obj/machinery/atmospherics/pipe/simple))
|
||||
var/obj/machinery/atmospherics/pipe/P = A
|
||||
search |= list(P.node1, P.node2)
|
||||
|
||||
else if(istype(A, /obj/machinery/atmospherics/pipe/manifold))
|
||||
var/obj/machinery/atmospherics/pipe/manifold/M = A
|
||||
search |= list(M.node1, M.node2, M.node3)
|
||||
|
||||
else if(istype(A, /obj/machinery/atmospherics/pipe/manifold4w))
|
||||
var/obj/machinery/atmospherics/pipe/manifold4w/M = A
|
||||
search |= list(M.node1, M.node2, M.node3, M.node4)
|
||||
|
||||
// else continue, dead end
|
||||
// We broke out of the loop, so we see no leaks
|
||||
// The leaks therefore must be on the other side of another shutoff valve
|
||||
return
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
name = "Gas filter"
|
||||
desc = "Filters one type of gas from an input, and pushes it out the side."
|
||||
|
||||
use_power = 1
|
||||
use_power = USE_POWER_IDLE
|
||||
idle_power_usage = 150 //internal circuitry, friction losses and stuff
|
||||
power_rating = 7500 //This also doubles as a measure of how powerful the filter is, in Watts. 7500 W ~ 10 HP
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
icon_state += use_power ? "on" : "off"
|
||||
else
|
||||
icon_state += "off"
|
||||
use_power = 0
|
||||
update_use_power(USE_POWER_OFF)
|
||||
|
||||
/obj/machinery/atmospherics/trinary/atmos_filter/process()
|
||||
..()
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
name = "Gas mixer"
|
||||
|
||||
use_power = 1
|
||||
use_power = USE_POWER_IDLE
|
||||
idle_power_usage = 150 //internal circuitry, friction losses and stuff
|
||||
power_rating = 3700 //This also doubles as a measure of how powerful the mixer is, in Watts. 3700 W ~ 5 HP
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
icon_state += use_power ? "on" : "off"
|
||||
else
|
||||
icon_state += "off"
|
||||
use_power = 0
|
||||
update_use_power(USE_POWER_OFF)
|
||||
|
||||
/obj/machinery/atmospherics/trinary/mixer/New()
|
||||
..()
|
||||
@@ -114,7 +114,7 @@
|
||||
/obj/machinery/atmospherics/trinary/mixer/Topic(href,href_list)
|
||||
if(..()) return 1
|
||||
if(href_list["power"])
|
||||
use_power = !use_power
|
||||
update_use_power(!use_power)
|
||||
if(href_list["set_press"])
|
||||
var/max_flow_rate = min(air1.volume, air2.volume)
|
||||
var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",src.set_flow_rate) as num
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/obj/machinery/atmospherics/trinary
|
||||
dir = SOUTH
|
||||
initialize_directions = SOUTH|NORTH|WEST
|
||||
use_power = 0
|
||||
use_power = USE_POWER_OFF
|
||||
pipe_flags = PIPING_DEFAULT_LAYER_ONLY|PIPING_ONE_PER_TURF
|
||||
|
||||
var/mirrored = FALSE
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
icon_state = "freezer_0"
|
||||
density = 1
|
||||
anchored = 1
|
||||
use_power = 0
|
||||
use_power = USE_POWER_OFF
|
||||
idle_power_usage = 5 // 5 Watts for thermostat related circuitry
|
||||
circuit = /obj/item/weapon/circuitboard/unary_atmos/cooler
|
||||
|
||||
@@ -99,7 +99,7 @@
|
||||
if(..())
|
||||
return 1
|
||||
if(href_list["toggleStatus"])
|
||||
use_power = !use_power
|
||||
update_use_power(!use_power)
|
||||
update_icon()
|
||||
if(href_list["temp"])
|
||||
var/amount = text2num(href_list["temp"])
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
icon_state = "heater_0"
|
||||
density = 1
|
||||
anchored = 1
|
||||
use_power = 0
|
||||
use_power = USE_POWER_OFF
|
||||
idle_power_usage = 5 //5 Watts for thermostat related circuitry
|
||||
circuit = /obj/item/weapon/circuitboard/unary_atmos/heater
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
if(..())
|
||||
return 1
|
||||
if(href_list["toggleStatus"])
|
||||
use_power = !use_power
|
||||
update_use_power(!use_power)
|
||||
update_icon()
|
||||
if(href_list["temp"])
|
||||
var/amount = text2num(href_list["temp"])
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
name = "air injector"
|
||||
desc = "Passively injects air into its surroundings. Has a valve attached to it that can control flow rate."
|
||||
|
||||
use_power = 0
|
||||
use_power = USE_POWER_OFF
|
||||
idle_power_usage = 150 //internal circuitry, friction losses and stuff
|
||||
power_rating = 15000 //15000 W ~ 20 HP
|
||||
|
||||
@@ -132,10 +132,10 @@
|
||||
return 0
|
||||
|
||||
if(signal.data["power"])
|
||||
use_power = text2num(signal.data["power"])
|
||||
update_use_power(text2num(signal.data["power"]))
|
||||
|
||||
if(signal.data["power_toggle"])
|
||||
use_power = !use_power
|
||||
update_use_power(!use_power)
|
||||
|
||||
if(signal.data["inject"])
|
||||
spawn inject()
|
||||
@@ -160,7 +160,7 @@
|
||||
/obj/machinery/atmospherics/unary/outlet_injector/attack_hand(mob/user as mob)
|
||||
to_chat(user, "<span class='notice'>You toggle \the [src].</span>")
|
||||
injecting = !injecting
|
||||
use_power = injecting
|
||||
update_use_power(injecting ? USE_POWER_IDLE : USE_POWER_OFF)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/unary/outlet_injector/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
name = "Air Vent"
|
||||
desc = "Has a valve and pump attached to it"
|
||||
use_power = 0
|
||||
use_power = USE_POWER_OFF
|
||||
idle_power_usage = 150 //internal circuitry, friction losses and stuff
|
||||
power_rating = 30000 //7500 W ~ 10 HP //VOREStation Edit - 30000 W
|
||||
|
||||
@@ -50,18 +50,18 @@
|
||||
var/datum/looping_sound/air_pump/soundloop //Yawn Edit
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/on
|
||||
use_power = 1
|
||||
use_power = USE_POWER_IDLE
|
||||
icon_state = "map_vent_out"
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/siphon
|
||||
pump_direction = 0
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/siphon/on
|
||||
use_power = 1
|
||||
use_power = USE_POWER_IDLE
|
||||
icon_state = "map_vent_in"
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/siphon/on/atmos
|
||||
use_power = 1
|
||||
use_power = USE_POWER_IDLE
|
||||
icon_state = "map_vent_in"
|
||||
external_pressure_bound = 0
|
||||
external_pressure_bound_default = 0
|
||||
@@ -189,7 +189,7 @@
|
||||
return 1
|
||||
|
||||
if (!node)
|
||||
use_power = 0
|
||||
update_use_power(USE_POWER_OFF)
|
||||
if(!can_pump())
|
||||
return 0
|
||||
|
||||
@@ -311,10 +311,10 @@
|
||||
pump_direction = 1
|
||||
|
||||
if(signal.data["power"] != null)
|
||||
use_power = text2num(signal.data["power"])
|
||||
update_use_power(text2num(signal.data["power"]))
|
||||
|
||||
if(signal.data["power_toggle"] != null)
|
||||
use_power = !use_power
|
||||
update_use_power(!use_power)
|
||||
|
||||
if(signal.data["checks"] != null)
|
||||
if (signal.data["checks"] == "default")
|
||||
@@ -405,11 +405,11 @@
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/examine(mob/user)
|
||||
if(..(user, 1))
|
||||
user << "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W"
|
||||
to_chat(user, "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W")
|
||||
else
|
||||
user << "You are too far away to read the gauge."
|
||||
to_chat(user, "You are too far away to read the gauge.")
|
||||
if(welded)
|
||||
user << "It seems welded shut."
|
||||
to_chat(user, "It seems welded shut.")
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/power_change()
|
||||
var/old_stat = stat
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
name = "Air Scrubber"
|
||||
desc = "Has a valve and pump attached to it"
|
||||
use_power = 0
|
||||
use_power = USE_POWER_OFF
|
||||
idle_power_usage = 150 //internal circuitry, friction losses and stuff
|
||||
power_rating = 7500 //7500 W ~ 10 HP
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
var/radio_filter_in
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/on
|
||||
use_power = 1
|
||||
use_power = USE_POWER_IDLE
|
||||
icon_state = "map_scrubber_on"
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/New()
|
||||
@@ -135,7 +135,7 @@
|
||||
return 1
|
||||
|
||||
if (!node)
|
||||
use_power = 0
|
||||
update_use_power(USE_POWER_OFF)
|
||||
//broadcast_status()
|
||||
if(!use_power || (stat & (NOPOWER|BROKEN)))
|
||||
return 0
|
||||
@@ -180,21 +180,21 @@
|
||||
return 0
|
||||
|
||||
if(signal.data["power"] != null)
|
||||
use_power = text2num(signal.data["power"])
|
||||
update_use_power(text2num(signal.data["power"]))
|
||||
if(signal.data["power_toggle"] != null)
|
||||
use_power = !use_power
|
||||
update_use_power(!use_power)
|
||||
|
||||
if(signal.data["panic_siphon"]) //must be before if("scrubbing" thing
|
||||
panic = text2num(signal.data["panic_siphon"])
|
||||
if(panic)
|
||||
use_power = 1
|
||||
update_use_power(USE_POWER_IDLE)
|
||||
scrubbing = 0
|
||||
else
|
||||
scrubbing = 1
|
||||
if(signal.data["toggle_panic_siphon"] != null)
|
||||
panic = !panic
|
||||
if(panic)
|
||||
use_power = 1
|
||||
update_use_power(USE_POWER_IDLE)
|
||||
scrubbing = 0
|
||||
else
|
||||
scrubbing = 1
|
||||
@@ -288,6 +288,6 @@
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/examine(mob/user)
|
||||
if(..(user, 1))
|
||||
user << "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W"
|
||||
to_chat(user, "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W")
|
||||
else
|
||||
user << "You are too far away to read the gauge."
|
||||
to_chat(user, "You are too far away to read the gauge.")
|
||||
|
||||
@@ -308,4 +308,4 @@
|
||||
|
||||
/obj/machinery/atmospherics/valve/examine(mob/user)
|
||||
..()
|
||||
user << "It is [open ? "open" : "closed"]."
|
||||
to_chat(user, "It is [open ? "open" : "closed"].")
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
var/leaking = FALSE // Do not set directly, use set_leaking(TRUE/FALSE)
|
||||
|
||||
layer = PIPES_LAYER
|
||||
use_power = 0
|
||||
use_power = USE_POWER_OFF
|
||||
|
||||
pipe_flags = 0 // Does not have PIPING_DEFAULT_LAYER_ONLY flag.
|
||||
|
||||
|
||||
+15
-15
@@ -79,13 +79,13 @@ Class Procs:
|
||||
if(!direct())
|
||||
state |= CONNECTION_DIRECT
|
||||
edge.direct++
|
||||
//world << "Marked direct."
|
||||
//to_world("Marked direct.")
|
||||
|
||||
/connection/proc/mark_indirect()
|
||||
if(direct())
|
||||
state &= ~CONNECTION_DIRECT
|
||||
edge.direct--
|
||||
//world << "Marked indirect."
|
||||
//to_world("Marked indirect.")
|
||||
|
||||
/connection/proc/mark_space()
|
||||
state |= CONNECTION_SPACE
|
||||
@@ -99,18 +99,18 @@ Class Procs:
|
||||
/connection/proc/erase()
|
||||
edge.remove_connection(src)
|
||||
state |= CONNECTION_INVALID
|
||||
//world << "Connection Erased: [state]"
|
||||
//to_world("Connection Erased: [state]")
|
||||
|
||||
/connection/proc/update()
|
||||
//world << "Updated, \..."
|
||||
//to_world("Updated, \...")
|
||||
if(!istype(A,/turf/simulated))
|
||||
//world << "Invalid A."
|
||||
//to_world("Invalid A.")
|
||||
erase()
|
||||
return
|
||||
|
||||
var/block_status = air_master.air_blocked(A,B)
|
||||
if(block_status & AIR_BLOCKED)
|
||||
//world << "Blocked connection."
|
||||
//to_world("Blocked connection.")
|
||||
erase()
|
||||
return
|
||||
else if(block_status & ZONE_BLOCKED)
|
||||
@@ -122,14 +122,14 @@ Class Procs:
|
||||
|
||||
if(state & CONNECTION_SPACE)
|
||||
if(!b_is_space)
|
||||
//world << "Invalid B."
|
||||
//to_world("Invalid B.")
|
||||
erase()
|
||||
return
|
||||
if(A.zone != zoneA)
|
||||
//world << "Zone changed, \..."
|
||||
//to_world("Zone changed, \...")
|
||||
if(!A.zone)
|
||||
erase()
|
||||
//world << "erased."
|
||||
//to_world("erased.")
|
||||
return
|
||||
else
|
||||
edge.remove_connection(src)
|
||||
@@ -137,22 +137,22 @@ Class Procs:
|
||||
edge.add_connection(src)
|
||||
zoneA = A.zone
|
||||
|
||||
//world << "valid."
|
||||
//to_world("valid.")
|
||||
return
|
||||
|
||||
else if(b_is_space)
|
||||
//world << "Invalid B."
|
||||
//to_world("Invalid B.")
|
||||
erase()
|
||||
return
|
||||
|
||||
if(A.zone == B.zone)
|
||||
//world << "A == B"
|
||||
//to_world("A == B")
|
||||
erase()
|
||||
return
|
||||
|
||||
if(A.zone != zoneA || (zoneB && (B.zone != zoneB)))
|
||||
|
||||
//world << "Zones changed, \..."
|
||||
//to_world("Zones changed, \...")
|
||||
if(A.zone && B.zone)
|
||||
edge.remove_connection(src)
|
||||
edge = air_master.get_edge(A.zone, B.zone)
|
||||
@@ -160,9 +160,9 @@ Class Procs:
|
||||
zoneA = A.zone
|
||||
zoneB = B.zone
|
||||
else
|
||||
//world << "erased."
|
||||
//to_world("erased.")
|
||||
erase()
|
||||
return
|
||||
|
||||
|
||||
//world << "valid."
|
||||
//to_world("valid.")
|
||||
@@ -72,10 +72,10 @@ Class Procs:
|
||||
/connection_edge/proc/add_connection(connection/c)
|
||||
coefficient++
|
||||
if(c.direct()) direct++
|
||||
//world << "Connection added: [type] Coefficient: [coefficient]"
|
||||
//to_world("Connection added: [type] Coefficient: [coefficient]")
|
||||
|
||||
/connection_edge/proc/remove_connection(connection/c)
|
||||
//world << "Connection removed: [type] Coefficient: [coefficient-1]"
|
||||
//to_world("Connection removed: [type] Coefficient: [coefficient-1]")
|
||||
coefficient--
|
||||
if(coefficient <= 0)
|
||||
erase()
|
||||
@@ -85,7 +85,7 @@ Class Procs:
|
||||
|
||||
/connection_edge/proc/erase()
|
||||
air_master.remove_edge(src)
|
||||
//world << "[type] Erased."
|
||||
//to_world("[type] Erased.")
|
||||
|
||||
/connection_edge/proc/tick()
|
||||
|
||||
@@ -128,7 +128,7 @@ Class Procs:
|
||||
A.edges.Add(src)
|
||||
B.edges.Add(src)
|
||||
//id = edge_id(A,B)
|
||||
//world << "New edge between [A] and [B]"
|
||||
//to_world("New edge between [A] and [B]")
|
||||
|
||||
/connection_edge/zone/add_connection(connection/c)
|
||||
. = ..()
|
||||
@@ -198,7 +198,7 @@ Class Procs:
|
||||
A.edges.Add(src)
|
||||
air = B.return_air()
|
||||
//id = 52*A.id
|
||||
//world << "New edge from [A] to [B]."
|
||||
//to_world("New edge from [A] to [B].")
|
||||
|
||||
/connection_edge/unsimulated/add_connection(connection/c)
|
||||
. = ..()
|
||||
|
||||
+14
-14
@@ -22,11 +22,11 @@ client/proc/Zone_Info(turf/T as null|turf)
|
||||
if(istype(T,/turf/simulated) && T:zone)
|
||||
T:zone:dbg_data(src)
|
||||
else
|
||||
mob << "No zone here."
|
||||
to_chat(mob, "No zone here.")
|
||||
var/datum/gas_mixture/mix = T.return_air()
|
||||
mob << "[mix.return_pressure()] kPa [mix.temperature]C"
|
||||
to_chat(mob, "[mix.return_pressure()] kPa [mix.temperature]C")
|
||||
for(var/g in mix.gas)
|
||||
mob << "[g]: [mix.gas[g]]\n"
|
||||
to_chat(mob, "[g]: [mix.gas[g]]\n")
|
||||
else
|
||||
if(zone_debug_images)
|
||||
for(var/zone in zone_debug_images)
|
||||
@@ -56,9 +56,9 @@ client/proc/Test_ZAS_Connection(var/turf/simulated/T as turf)
|
||||
|
||||
if(direction == "N/A")
|
||||
if(!(T.c_airblock(T) & AIR_BLOCKED))
|
||||
mob << "The turf can pass air! :D"
|
||||
to_chat(mob, "The turf can pass air! :D")
|
||||
else
|
||||
mob << "No air passage :x"
|
||||
to_chat(mob, "No air passage :x")
|
||||
return
|
||||
|
||||
var/turf/simulated/other_turf = get_step(T, direction_list[direction])
|
||||
@@ -70,29 +70,29 @@ client/proc/Test_ZAS_Connection(var/turf/simulated/T as turf)
|
||||
|
||||
if(o_block & AIR_BLOCKED)
|
||||
if(t_block & AIR_BLOCKED)
|
||||
mob << "Neither turf can connect. :("
|
||||
to_chat(mob, "Neither turf can connect. :(")
|
||||
|
||||
else
|
||||
mob << "The initial turf only can connect. :\\"
|
||||
to_chat(mob, "The initial turf only can connect. :\\")
|
||||
else
|
||||
if(t_block & AIR_BLOCKED)
|
||||
mob << "The other turf can connect, but not the initial turf. :/"
|
||||
to_chat(mob, "The other turf can connect, but not the initial turf. :/")
|
||||
|
||||
else
|
||||
mob << "Both turfs can connect! :)"
|
||||
to_chat(mob, "Both turfs can connect! :)")
|
||||
|
||||
mob << "Additionally, \..."
|
||||
to_chat(mob, "Additionally, \...")
|
||||
|
||||
if(o_block & ZONE_BLOCKED)
|
||||
if(t_block & ZONE_BLOCKED)
|
||||
mob << "neither turf can merge."
|
||||
to_chat(mob, "neither turf can merge.")
|
||||
else
|
||||
mob << "the other turf cannot merge."
|
||||
to_chat(mob, "the other turf cannot merge.")
|
||||
else
|
||||
if(t_block & ZONE_BLOCKED)
|
||||
mob << "the initial turf cannot merge."
|
||||
to_chat(mob, "the initial turf cannot merge.")
|
||||
else
|
||||
mob << "both turfs can merge."
|
||||
to_chat(mob, "both turfs can merge.")
|
||||
|
||||
client/proc/ZASSettings()
|
||||
set category = "Debug"
|
||||
|
||||
+8
-8
@@ -99,7 +99,7 @@
|
||||
var/s_block = c_airblock(src)
|
||||
if(s_block & AIR_BLOCKED)
|
||||
#ifdef ZASDBG
|
||||
if(verbose) world << "Self-blocked."
|
||||
if(verbose) to_world("Self-blocked.")
|
||||
//dbg(blocked)
|
||||
#endif
|
||||
if(zone)
|
||||
@@ -131,7 +131,7 @@
|
||||
if(block & AIR_BLOCKED)
|
||||
|
||||
#ifdef ZASDBG
|
||||
if(verbose) world << "[d] is blocked."
|
||||
if(verbose) to_world("[d] is blocked.")
|
||||
//unsim.dbg(air_blocked, turn(180,d))
|
||||
#endif
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
if(r_block & AIR_BLOCKED)
|
||||
|
||||
#ifdef ZASDBG
|
||||
if(verbose) world << "[d] is blocked."
|
||||
if(verbose) to_world("[d] is blocked.")
|
||||
//dbg(air_blocked, d)
|
||||
#endif
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
// we are blocking them and not blocking ourselves - this prevents tiny zones from forming on doorways.
|
||||
if(((block & ZONE_BLOCKED) && !(r_block & ZONE_BLOCKED)) || ((r_block & ZONE_BLOCKED) && !(s_block & ZONE_BLOCKED)))
|
||||
#ifdef ZASDBG
|
||||
if(verbose) world << "[d] is zone blocked."
|
||||
if(verbose) to_world("[d] is zone blocked.")
|
||||
//dbg(zone_blocked, d)
|
||||
#endif
|
||||
|
||||
@@ -186,22 +186,22 @@
|
||||
|
||||
#ifdef ZASDBG
|
||||
dbg(assigned)
|
||||
if(verbose) world << "Added to [zone]"
|
||||
if(verbose) to_world("Added to [zone]")
|
||||
#endif
|
||||
|
||||
else if(sim.zone != zone)
|
||||
|
||||
#ifdef ZASDBG
|
||||
if(verbose) world << "Connecting to [sim.zone]"
|
||||
if(verbose) to_world("Connecting to [sim.zone]")
|
||||
#endif
|
||||
|
||||
air_master.connect(src, sim)
|
||||
|
||||
|
||||
#ifdef ZASDBG
|
||||
else if(verbose) world << "[d] has same zone."
|
||||
else if(verbose) to_world("[d] has same zone.")
|
||||
|
||||
else if(verbose) world << "[d] has invalid zone."
|
||||
else if(verbose) to_world("[d] has invalid zone.")
|
||||
#endif
|
||||
|
||||
else
|
||||
|
||||
@@ -169,7 +169,7 @@ var/global/vs_control/vsc = new
|
||||
vars[ch] = vw
|
||||
if(how == "Toggle")
|
||||
newvar = (newvar?"ON":"OFF")
|
||||
world << "<span class='notice'><b>[key_name(user)] changed the setting [display_description] to [newvar].</b></span>"
|
||||
to_world("<span class='notice'><b>[key_name(user)] changed the setting [display_description] to [newvar].</b></span>")
|
||||
if(ch in plc.settings)
|
||||
ChangeSettingsDialog(user,plc.settings)
|
||||
else
|
||||
@@ -322,7 +322,7 @@ var/global/vs_control/vsc = new
|
||||
plc.N2O_HALLUCINATION = initial(plc.N2O_HALLUCINATION)
|
||||
|
||||
|
||||
world << "<span class='notice'><b>[key_name(user)] changed the global phoron/ZAS settings to \"[def]\"</b></span>"
|
||||
to_world("<span class='notice'><b>[key_name(user)] changed the global phoron/ZAS settings to \"[def]\"</b></span>")
|
||||
|
||||
/pl_control/var/list/settings = list()
|
||||
|
||||
|
||||
+13
-12
@@ -168,15 +168,16 @@ Class Procs:
|
||||
E.recheck()
|
||||
|
||||
/zone/proc/dbg_data(mob/M)
|
||||
M << name
|
||||
to_chat(M,name)
|
||||
for(var/g in air.gas)
|
||||
M << "[gas_data.name[g]]: [air.gas[g]]"
|
||||
M << "P: [air.return_pressure()] kPa V: [air.volume]L T: [air.temperature]°K ([air.temperature - T0C]°C)"
|
||||
M << "O2 per N2: [(air.gas["nitrogen"] ? air.gas["oxygen"]/air.gas["nitrogen"] : "N/A")] Moles: [air.total_moles]"
|
||||
M << "Simulated: [contents.len] ([air.group_multiplier])"
|
||||
//M << "Unsimulated: [unsimulated_contents.len]"
|
||||
//M << "Edges: [edges.len]"
|
||||
if(invalid) M << "Invalid!"
|
||||
to_chat(M, "[gas_data.name[g]]: [air.gas[g]]")
|
||||
to_chat(M, "P: [air.return_pressure()] kPa V: [air.volume]L T: [air.temperature]°K ([air.temperature - T0C]°C)")
|
||||
to_chat(M, "O2 per N2: [(air.gas["nitrogen"] ? air.gas["oxygen"]/air.gas["nitrogen"] : "N/A")] Moles: [air.total_moles]")
|
||||
to_chat(M, "Simulated: [contents.len] ([air.group_multiplier])")
|
||||
//to_chat(M, "Unsimulated: [unsimulated_contents.len]")
|
||||
//to_chat(M, "Edges: [edges.len]")
|
||||
if(invalid)
|
||||
to_chat(M, "Invalid!")
|
||||
var/zone_edges = 0
|
||||
var/space_edges = 0
|
||||
var/space_coefficient = 0
|
||||
@@ -185,10 +186,10 @@ Class Procs:
|
||||
else
|
||||
space_edges++
|
||||
space_coefficient += E.coefficient
|
||||
M << "[E:air:return_pressure()]kPa"
|
||||
to_chat(M, "[E:air:return_pressure()]kPa")
|
||||
|
||||
M << "Zone Edges: [zone_edges]"
|
||||
M << "Space Edges: [space_edges] ([space_coefficient] connections)"
|
||||
to_chat(M, "Zone Edges: [zone_edges]")
|
||||
to_chat(M, "Space Edges: [space_edges] ([space_coefficient] connections)")
|
||||
|
||||
//for(var/turf/T in unsimulated_contents)
|
||||
// M << "[T] at ([T.x],[T.y])"
|
||||
// to_chat(M, "[T] at ([T.x],[T.y])")
|
||||
@@ -1,11 +1,15 @@
|
||||
//See controllers/globals.dm
|
||||
// See also controllers/globals.dm
|
||||
|
||||
// Creates a global initializer with a given InitValue expression, do not use outside this file
|
||||
#define GLOBAL_MANAGED(X, InitValue)\
|
||||
/datum/controller/global_vars/proc/InitGlobal##X(){\
|
||||
##X = ##InitValue;\
|
||||
gvars_datum_init_order += #X;\
|
||||
}
|
||||
#define GLOBAL_UNMANAGED(X, InitValue) /datum/controller/global_vars/proc/InitGlobal##X()
|
||||
// Creates an empty global initializer, do not use outside this file
|
||||
#define GLOBAL_UNMANAGED(X) /datum/controller/global_vars/proc/InitGlobal##X() { return; }
|
||||
|
||||
// Prevents a given global from being VV'd
|
||||
#ifndef TESTING
|
||||
#define GLOBAL_PROTECT(X)\
|
||||
/datum/controller/global_vars/InitGlobal##X(){\
|
||||
@@ -16,24 +20,42 @@
|
||||
#define GLOBAL_PROTECT(X)
|
||||
#endif
|
||||
|
||||
// Standard BYOND global, do not use outside this file
|
||||
#define GLOBAL_REAL_VAR(X) var/global/##X
|
||||
|
||||
// Standard typed BYOND global, do not use outside this file
|
||||
#define GLOBAL_REAL(X, Typepath) var/global##Typepath/##X
|
||||
|
||||
// Defines a global var on the controller, do not use outside this file.
|
||||
#define GLOBAL_RAW(X) /datum/controller/global_vars/var/global##X
|
||||
|
||||
// Create an untyped global with an initializer expression
|
||||
#define GLOBAL_VAR_INIT(X, InitValue) GLOBAL_RAW(/##X); GLOBAL_MANAGED(X, InitValue)
|
||||
|
||||
#define GLOBAL_VAR_CONST(X, InitValue) GLOBAL_RAW(/const/##X) = InitValue; GLOBAL_UNMANAGED(X, InitValue)
|
||||
// Create a global const var, do not use
|
||||
#define GLOBAL_VAR_CONST(X, InitValue) GLOBAL_RAW(/const/##X) = InitValue; GLOBAL_UNMANAGED(X)
|
||||
|
||||
// Create a list global with an initializer expression
|
||||
#define GLOBAL_LIST_INIT(X, InitValue) GLOBAL_RAW(/list/##X); GLOBAL_MANAGED(X, InitValue)
|
||||
|
||||
// Create a list global that is initialized as an empty list
|
||||
#define GLOBAL_LIST_EMPTY(X) GLOBAL_LIST_INIT(X, list())
|
||||
|
||||
// Create a typed list global with an initializer expression
|
||||
#define GLOBAL_LIST_INIT_TYPED(X, Typepath, InitValue) GLOBAL_RAW(/list##Typepath/X); GLOBAL_MANAGED(X, InitValue)
|
||||
|
||||
// Create a typed list global that is initialized as an empty list
|
||||
#define GLOBAL_LIST_EMPTY_TYPED(X, Typepath) GLOBAL_LIST_INIT_TYPED(X, Typepath, list())
|
||||
|
||||
// Create a typed global with an initializer expression
|
||||
#define GLOBAL_DATUM_INIT(X, Typepath, InitValue) GLOBAL_RAW(Typepath/##X); GLOBAL_MANAGED(X, InitValue)
|
||||
|
||||
#define GLOBAL_VAR(X) GLOBAL_RAW(/##X); GLOBAL_MANAGED(X, null)
|
||||
// Create an untyped null global
|
||||
#define GLOBAL_VAR(X) GLOBAL_RAW(/##X); GLOBAL_UNMANAGED(X)
|
||||
|
||||
#define GLOBAL_LIST(X) GLOBAL_RAW(/list/##X); GLOBAL_MANAGED(X, null)
|
||||
// Create a null global list
|
||||
#define GLOBAL_LIST(X) GLOBAL_RAW(/list/##X); GLOBAL_UNMANAGED(X)
|
||||
|
||||
#define GLOBAL_DATUM(X, Typepath) GLOBAL_RAW(Typepath/##X); GLOBAL_MANAGED(X, null)
|
||||
// Create a typed null global
|
||||
#define GLOBAL_DATUM(X, Typepath) GLOBAL_RAW(Typepath/##X); GLOBAL_UNMANAGED(X)
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
//#define ZASDBG // Uncomment to turn on super detailed ZAS debugging that probably won't even compile.
|
||||
#define MULTIZAS // Uncomment to turn on Multi-Z ZAS Support!
|
||||
|
||||
// Comment/Uncomment this to turn off/on shuttle code debugging logs
|
||||
#define DEBUG_SHUTTLES
|
||||
|
||||
// If we are doing the map test build, do not include the main maps, only the submaps.
|
||||
#if MAP_TEST
|
||||
#define USING_MAP_DATUM /datum/map
|
||||
|
||||
@@ -3,26 +3,41 @@
|
||||
|
||||
//Picks from the list, with some safeties, and returns the "default" arg if it fails
|
||||
#define DEFAULTPICK(L, default) ((istype(L, /list) && L:len) ? pick(L) : default)
|
||||
|
||||
// Ensures L is initailized after this point
|
||||
#define LAZYINITLIST(L) if (!L) L = list()
|
||||
|
||||
// Sets a L back to null iff it is empty
|
||||
#define UNSETEMPTY(L) if (L && !length(L)) L = null
|
||||
|
||||
// Removes I from list L, and sets I to null if it is now empty
|
||||
#define LAZYREMOVE(L, I) if(L) { L -= I; if(!length(L)) { L = null; } }
|
||||
// Adds I to L, initalizing I if necessary
|
||||
|
||||
// Adds I to L, initalizing L if necessary
|
||||
#define LAZYADD(L, I) if(!L) { L = list(); } L += I;
|
||||
|
||||
#define LAZYOR(L, I) if(!L) { L = list(); } L |= I;
|
||||
|
||||
// Adds I to L, initalizing L if necessary, if I is not already in L
|
||||
#define LAZYDISTINCTADD(L, I) if(!L) { L = list(); } L |= I;
|
||||
|
||||
#define LAZYFIND(L, V) L ? L.Find(V) : 0
|
||||
|
||||
// Reads I from L safely - Works with both associative and traditional lists.
|
||||
#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= length(L) ? L[I] : null) : L[I]) : null)
|
||||
|
||||
// Turns LAZYINITLIST(L) L[K] = V into ... for associated lists
|
||||
#define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V;
|
||||
|
||||
// Reads the length of L, returning 0 if null
|
||||
#define LAZYLEN(L) length(L)
|
||||
|
||||
// Null-safe L.Cut()
|
||||
#define LAZYCLEARLIST(L) if(L) L.Cut()
|
||||
|
||||
// Reads L or an empty list if L is not a list. Note: Does NOT assign, L may be an expression.
|
||||
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
|
||||
|
||||
#define reverseList(L) reverseRange(L.Copy())
|
||||
|
||||
// binary search sorted insert
|
||||
|
||||
@@ -22,7 +22,7 @@ What can I do with Planesmasters?
|
||||
Planesmasters can be used as a neater way to deal with client images or potentially to do some neat things
|
||||
|
||||
How do planes work?
|
||||
A plane can be any integer from -100 to 100. (If you want more, bug lummox.)
|
||||
A plane can be any integer from -10000 to 10000.
|
||||
All planes above 0, the 'base plane', are visible even when your character cannot 'see' them, for example, the HUD.
|
||||
All planes below 0, the 'base plane', are only visible when a character can see them.
|
||||
|
||||
@@ -40,8 +40,14 @@ What is the naming convention for planes or layers?
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#define SPACE_PLANE -82 // Reserved for use in space/parallax
|
||||
#define PARALLAX_PLANE -80 // Reserved for use in space/parallax
|
||||
#define PARALLAX_PLANE -81 // Reserved for use in space/parallax
|
||||
#define SKYBOX_PLANE -80 // Skybox parallax
|
||||
#define DUST_PLANE -79 // For dust overlay on space turfs. Should be above skybox for parallax effect.
|
||||
|
||||
#define PLANE_LOOKINGGLASS -78 // For the Looking Glass holodecks
|
||||
#define PLANE_LOOKINGGLASS_IMG -77 // For the Looking Glass holodecks
|
||||
|
||||
// OPENSPACE_PLANE reserves all planes between OPENSPACE_PLANE_START and OPENSPACE_PLANE_END inclusive
|
||||
#define OPENSPACE_PLANE -75 // /turf/simulated/open will use OPENSPACE_PLANE + z (Valid z's being 2 thru 17)
|
||||
@@ -50,7 +56,6 @@ What is the naming convention for planes or layers?
|
||||
#define OVER_OPENSPACE_PLANE -57
|
||||
|
||||
// Turf Planes
|
||||
#define SPACE_PLANE -43 // Space turfs themselves
|
||||
#define PLATING_PLANE -44 // Plating
|
||||
#define DISPOSAL_LAYER 2.1 // Under objects, even when planeswapped
|
||||
#define PIPES_LAYER 2.2 // Under objects, even when planeswapped
|
||||
@@ -86,6 +91,9 @@ What is the naming convention for planes or layers?
|
||||
#define BELOW_MOB_LAYER 3.9 // Should be converted to plane swaps
|
||||
#define ABOVE_MOB_LAYER 4.1 // Should be converted to plane swaps
|
||||
|
||||
// Invisible things plane
|
||||
#define CLOAKED_PLANE -15
|
||||
|
||||
// Top plane (in the sense that it's the highest in 'the world' and not a UI element)
|
||||
#define ABOVE_PLANE -10
|
||||
|
||||
@@ -130,6 +138,8 @@ What is the naming convention for planes or layers?
|
||||
|
||||
#define PLANE_ADMIN2 33 //Purely for shenanigans (above lighting)
|
||||
|
||||
#define PLANE_BUILDMODE 39 //Things that only show up when you have buildmode on
|
||||
|
||||
//Fullscreen overlays under inventory
|
||||
#define PLANE_FULLSCREEN 90 //Blindness, mesons, druggy, etc
|
||||
#define OBFUSCATION_LAYER 5 //Where images covering the view for eyes are put
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
///Protects a datum from being VV'd
|
||||
#define GENERAL_PROTECT_DATUM(Path)\
|
||||
##Path/can_vv_get(var_name){\
|
||||
return FALSE;\
|
||||
}\
|
||||
##Path/vv_edit_var(var_name, var_value){\
|
||||
return FALSE;\
|
||||
}\
|
||||
##Path/CanProcCall(procname){\
|
||||
return FALSE;\
|
||||
}
|
||||
@@ -29,6 +29,7 @@
|
||||
#define MINIMUM_AIR_TO_SUSPEND (MOLES_CELLSTANDARD * MINIMUM_AIR_RATIO_TO_SUSPEND) // Minimum amount of air that has to move before a group processing can be suspended
|
||||
#define MINIMUM_MOLES_DELTA_TO_MOVE (MOLES_CELLSTANDARD * MINIMUM_AIR_RATIO_TO_SUSPEND) // Either this must be active
|
||||
#define MINIMUM_TEMPERATURE_TO_MOVE (T20C + 100) // or this (or both, obviously)
|
||||
#define MINIMUM_PRESSURE_DIFFERENCE_TO_SUSPEND (MINIMUM_AIR_TO_SUSPEND*R_IDEAL_GAS_EQUATION*T20C)/CELL_VOLUME // Minimum pressure difference between zones to suspend
|
||||
|
||||
#define MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND 0.012 // Minimum temperature difference before group processing is suspended.
|
||||
#define MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND 4
|
||||
|
||||
@@ -14,4 +14,7 @@
|
||||
#define COLOR_ASSEMBLY_LBLUE "#5D99BE"
|
||||
#define COLOR_ASSEMBLY_BLUE "#38559E"
|
||||
#define COLOR_ASSEMBLY_PURPLE "#6F6192"
|
||||
#define COLOR_ASSEMBLY_HOT_PINK "#FF69B4"
|
||||
#define COLOR_ASSEMBLY_HOT_PINK "#FF69B4"
|
||||
|
||||
#define COLOR_ASTEROID_ROCK "#735555"
|
||||
#define COLOR_GOLD "#ffcc33"
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#define CONNECT_TYPE_SUPPLY 2
|
||||
#define CONNECT_TYPE_SCRUBBER 4
|
||||
#define CONNECT_TYPE_HE 8
|
||||
#define CONNECT_TYPE_FUEL 16 // TODO - Implement this! Its piping so better ask Leshana
|
||||
|
||||
// We are based on the three named layers of supply, regular, and scrubber.
|
||||
#define PIPING_LAYER_SUPPLY 1
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
//---------------
|
||||
#define isatom(D) istype(D, /atom)
|
||||
#define isclient(D) istype(D, /client)
|
||||
|
||||
//---------------
|
||||
//#define isobj(D) istype(D, /obj) //Built in
|
||||
|
||||
@@ -11,6 +11,11 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called
|
||||
#define DOOR_CRUSH_DAMAGE 20
|
||||
#define ALIEN_SELECT_AFK_BUFFER 1 // How many minutes that a person can be AFK before not being allowed to be an alien.
|
||||
|
||||
// Constants for machine's use_power
|
||||
#define USE_POWER_OFF 0 // No continuous power use
|
||||
#define USE_POWER_IDLE 1 // Machine is using power at its idle power level
|
||||
#define USE_POWER_ACTIVE 2 // Machine is using power at its active power level
|
||||
|
||||
// Channel numbers for power.
|
||||
#define EQUIP 1
|
||||
#define LIGHT 2
|
||||
@@ -24,6 +29,11 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called
|
||||
#define MAINT 0x8 // Under maintenance.
|
||||
#define EMPED 0x10 // Temporary broken by EMP pulse.
|
||||
|
||||
// Remote control states
|
||||
#define RCON_NO 1
|
||||
#define RCON_AUTO 2
|
||||
#define RCON_YES 3
|
||||
|
||||
// Used by firelocks
|
||||
#define FIREDOOR_OPEN 1
|
||||
#define FIREDOOR_CLOSED 2
|
||||
@@ -60,7 +70,7 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called
|
||||
#define NETWORK_ALARM_ATMOS "Atmosphere Alarms"
|
||||
#define NETWORK_ALARM_POWER "Power Alarms"
|
||||
#define NETWORK_ALARM_FIRE "Fire Alarms"
|
||||
#define NETWORK_EXPLORATION
|
||||
#define NETWORK_EXPLORATION "Exploration"
|
||||
|
||||
// Those networks can only be accessed by pre-existing terminals. AIs and new terminals can't use them.
|
||||
var/list/restricted_camera_networks = list(NETWORK_ERT,NETWORK_MERCENARY,"Secret", NETWORK_COMMUNICATORS, NETWORK_EXPLORATION)
|
||||
|
||||
+27
-14
@@ -2,7 +2,7 @@
|
||||
// Turf-only flags.
|
||||
#define NOJAUNT 1 // This is used in literally one place, turf.dm, to block ethereal jaunt.
|
||||
|
||||
#define TRANSITIONEDGE 7 // Distance from edge to move to another z-level.
|
||||
#define TRANSITIONEDGE 1 // Distance from edge to move to another z-level.
|
||||
|
||||
// Invisibility constants. These should only be used for TRUE invisibility, AKA nothing living players touch
|
||||
#define INVISIBILITY_LIGHTING 20
|
||||
@@ -78,8 +78,7 @@
|
||||
#define COLOR_RED_LIGHT "#FF3333"
|
||||
#define COLOR_DEEP_SKY_BLUE "#00e1ff"
|
||||
|
||||
|
||||
|
||||
#define CLIENT_FROM_VAR(I) (ismob(I) ? I:client : (isclient(I) ? I : null))
|
||||
|
||||
// Shuttles.
|
||||
|
||||
@@ -105,6 +104,7 @@
|
||||
#define FORCE_LAUNCH 2
|
||||
#define WAIT_ARRIVE 3
|
||||
#define WAIT_FINISH 4
|
||||
#define DO_AUTOPILOT 5
|
||||
|
||||
// Setting this much higher than 1024 could allow spammers to DOS the server easily.
|
||||
#define MAX_MESSAGE_LEN 2048 //VOREStation Edit - I'm not sure about "easily". It can be a little longer.
|
||||
@@ -113,6 +113,7 @@
|
||||
#define MAX_RECORD_LENGTH 24576
|
||||
#define MAX_LNAME_LEN 64
|
||||
#define MAX_NAME_LEN 52
|
||||
#define MAX_FEEDBACK_LENGTH 4096
|
||||
#define MAX_TEXTFILE_LENGTH 128000 // 512GQ file
|
||||
|
||||
// Event defines.
|
||||
@@ -128,6 +129,13 @@
|
||||
//Area flags, possibly more to come
|
||||
#define RAD_SHIELDED 1 //shielded from radiation, clearly
|
||||
|
||||
// OnTopic return values
|
||||
#define TOPIC_NOACTION 0
|
||||
#define TOPIC_HANDLED 1
|
||||
#define TOPIC_REFRESH 2
|
||||
#define TOPIC_UPDATE_PREVIEW 4
|
||||
#define TOPIC_REFRESH_UPDATE_PREVIEW (TOPIC_REFRESH|TOPIC_UPDATE_PREVIEW)
|
||||
|
||||
// Convoluted setup so defines can be supplied by Bay12 main server compile script.
|
||||
// Should still work fine for people jamming the icons into their repo.
|
||||
#ifndef CUSTOM_ITEM_OBJ
|
||||
@@ -176,6 +184,7 @@
|
||||
#define MAT_SUPERMATTER "supermatter"
|
||||
#define MAT_METALHYDROGEN "mhydrogen"
|
||||
#define MAT_OSMIUM "osmium"
|
||||
#define MAT_GRAPHITE "graphite"
|
||||
|
||||
#define SHARD_SHARD "shard"
|
||||
#define SHARD_SHRAPNEL "shrapnel"
|
||||
@@ -236,17 +245,20 @@
|
||||
#define ANTAG_SHARED "Shared"
|
||||
#define ANTAG_KNOWN "Known"
|
||||
|
||||
// Job groups
|
||||
#define ROLE_COMMAND "command"
|
||||
#define ROLE_SECURITY "security"
|
||||
#define ROLE_ENGINEERING "engineering"
|
||||
#define ROLE_MEDICAL "medical"
|
||||
#define ROLE_RESEARCH "research"
|
||||
#define ROLE_CARGO "cargo"
|
||||
#define ROLE_CIVILIAN "civilian"
|
||||
#define ROLE_SYNTHETIC "synthetic"
|
||||
#define ROLE_UNKNOWN "unknown"
|
||||
#define ROLE_EVERYONE "everyone"
|
||||
// Departments.
|
||||
#define DEPARTMENT_COMMAND "Command"
|
||||
#define DEPARTMENT_SECURITY "Security"
|
||||
#define DEPARTMENT_ENGINEERING "Engineering"
|
||||
#define DEPARTMENT_MEDICAL "Medical"
|
||||
#define DEPARTMENT_RESEARCH "Research"
|
||||
#define DEPARTMENT_CARGO "Cargo"
|
||||
#define DEPARTMENT_CIVILIAN "Civilian"
|
||||
#define DEPARTMENT_PLANET "Exploration" //VOREStation Edit // I hate having this be here and not in a SC file. Hopefully someday the manifest can be rewritten to be map-agnostic.
|
||||
#define DEPARTMENT_SYNTHETIC "Synthetic"
|
||||
|
||||
// These are mostly for the department guessing code and event system.
|
||||
#define DEPARTMENT_UNKNOWN "Unknown"
|
||||
#define DEPARTMENT_EVERYONE "Everyone"
|
||||
|
||||
// Canonical spellings of TSCs, so typos never have to happen again due to human error.
|
||||
#define TSC_NT "NanoTrasen"
|
||||
@@ -263,6 +275,7 @@
|
||||
|
||||
#define WORLD_ICON_SIZE 32 //Needed for the R-UST port
|
||||
#define PIXEL_MULTIPLIER WORLD_ICON_SIZE/32 //Needed for the R-UST port
|
||||
#define MAX_CLIENT_VIEW 34 // Maximum effective value of client.view (According to DM references)
|
||||
|
||||
// Maploader bounds indices
|
||||
#define MAP_MINX 1
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#define VANTAG_KIDNAP "vantag_kidnap"
|
||||
#define VANTAG_KILL "vantag_kill"
|
||||
|
||||
#define DEPARTMENT_OFFDUTY "Off-Duty"
|
||||
|
||||
#define ANNOUNCER_NAME "Facility PA"
|
||||
|
||||
//For custom species
|
||||
@@ -46,3 +48,11 @@
|
||||
#define SHELTER_DEPLOY_BAD_TURFS "bad turfs"
|
||||
#define SHELTER_DEPLOY_BAD_AREA "bad area"
|
||||
#define SHELTER_DEPLOY_ANCHORED_OBJECTS "anchored objects"
|
||||
|
||||
#define PTO_SECURITY "Security"
|
||||
#define PTO_MEDICAL "Medical"
|
||||
#define PTO_ENGINEERING "Engineering"
|
||||
#define PTO_SCIENCE "Science"
|
||||
#define PTO_EXPLORATION "Exploration"
|
||||
#define PTO_CARGO "Cargo"
|
||||
#define PTO_CIVILIAN "Civilian"
|
||||
@@ -115,10 +115,10 @@
|
||||
#define INV_BACK_DEF_ICON 'icons/mob/back.dmi'
|
||||
#define INV_L_HAND_DEF_ICON 'icons/mob/items/lefthand.dmi'
|
||||
#define INV_R_HAND_DEF_ICON 'icons/mob/items/righthand.dmi'
|
||||
#define INV_W_UNIFORM_DEF_ICON 'icons/mob/uniform.dmi'
|
||||
#define INV_W_UNIFORM_DEF_ICON "icons/mob/uniform"
|
||||
#define INV_ACCESSORIES_DEF_ICON 'icons/mob/ties.dmi'
|
||||
#define INV_TIE_DEF_ICON 'icons/mob/ties.dmi'
|
||||
#define INV_SUIT_DEF_ICON 'icons/mob/suit.dmi'
|
||||
#define INV_SUIT_DEF_ICON "icons/mob/suit"
|
||||
#define INV_SPACESUIT_DEF_ICON 'icons/mob/spacesuit.dmi'
|
||||
#define INV_WEAR_ID_DEF_ICON 'icons/mob/mob.dmi'
|
||||
#define INV_GLOVES_DEF_ICON 'icons/mob/hands.dmi'
|
||||
@@ -394,7 +394,11 @@
|
||||
#define VIS_OBJS 20
|
||||
#define VIS_MOBS 21
|
||||
|
||||
#define VIS_COUNT 21 //Must be highest number from above.
|
||||
#define VIS_BUILDMODE 22
|
||||
|
||||
#define VIS_CLOAKED 23
|
||||
|
||||
#define VIS_COUNT 23 //Must be highest number from above.
|
||||
|
||||
//Some mob icon layering defines
|
||||
#define BODY_LAYER -100
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#undef VIS_COUNT
|
||||
|
||||
#define VIS_CH_STATUS_R 22
|
||||
#define VIS_CH_HEALTH_VR 23
|
||||
#define VIS_CH_BACKUP 24
|
||||
#define VIS_CH_VANTAG 25
|
||||
#define VIS_CH_STATUS_R 24
|
||||
#define VIS_CH_HEALTH_VR 25
|
||||
#define VIS_CH_BACKUP 26
|
||||
#define VIS_CH_VANTAG 27
|
||||
|
||||
#define VIS_AUGMENTED 26
|
||||
#define VIS_AUGMENTED 28
|
||||
|
||||
#define VIS_COUNT 26
|
||||
#define VIS_COUNT 28
|
||||
|
||||
//Protean organs
|
||||
#define O_ORCH "orchestrator"
|
||||
@@ -29,9 +29,7 @@
|
||||
#define SPECIES_VASILISSAN "Vasilissan"
|
||||
#define SPECIES_VULPKANIN "Vulpkanin"
|
||||
#define SPECIES_XENOCHIMERA "Xenochimera"
|
||||
#define SPECIES_XENOHYBRID "Xenomorph Hybrid"
|
||||
#define SPECIES_ZORREN_FLAT "Flatland Zorren"
|
||||
#define SPECIES_ZORREN_HIGH "Highlander Zorren"
|
||||
#define SPECIES_ZORREN_HIGH "Zorren"
|
||||
#define SPECIES_CUSTOM "Custom Species"
|
||||
//monkey species
|
||||
#define SPECIES_MONKEY_AKULA "Sobaka"
|
||||
@@ -41,3 +39,6 @@
|
||||
//event species
|
||||
#define SPECIES_WEREBEAST "Werebeast"
|
||||
#define SPECIES_SHADEKIN "Shadekin"
|
||||
//custom species base sprites
|
||||
#define SPECIES_FENNEC "Fennec"
|
||||
#define SPECIES_XENOHYBRID "Xenohybrid"
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
//How far from the edge of overmap zlevel could randomly placed objects spawn
|
||||
#define OVERMAP_EDGE 2
|
||||
|
||||
#define SHIP_SIZE_TINY 1
|
||||
#define SHIP_SIZE_SMALL 2
|
||||
#define SHIP_SIZE_LARGE 3
|
||||
|
||||
//multipliers for max_speed to find 'slow' and 'fast' speeds for the ship
|
||||
#define SHIP_SPEED_SLOW 1/(40 SECONDS)
|
||||
#define SHIP_SPEED_FAST 3/(20 SECONDS)// 15 speed
|
||||
|
||||
#define OVERMAP_WEAKNESS_NONE 0
|
||||
#define OVERMAP_WEAKNESS_FIRE 1
|
||||
#define OVERMAP_WEAKNESS_EMP 2
|
||||
#define OVERMAP_WEAKNESS_MINING 4
|
||||
#define OVERMAP_WEAKNESS_EXPLOSIVE 8
|
||||
@@ -26,6 +26,7 @@
|
||||
#define QDEL_IN(item, time) addtimer(CALLBACK(GLOBAL_PROC, .proc/qdel, item), time, TIMER_STOPPABLE)
|
||||
#define QDEL_IN_CLIENT_TIME(item, time) addtimer(CALLBACK(GLOBAL_PROC, .proc/qdel, item), time, TIMER_STOPPABLE | TIMER_CLIENT_TIME)
|
||||
#define QDEL_NULL(item) qdel(item); item = null
|
||||
#define QDEL_NULL_LIST QDEL_LIST_NULL
|
||||
#define QDEL_LIST_NULL(x) if(x) { for(var/y in x) { qdel(y) } ; x = null }
|
||||
#define QDEL_LIST(L) if(L) { for(var/I in L) qdel(I); L.Cut(); }
|
||||
#define QDEL_LIST_IN(L, time) addtimer(CALLBACK(GLOBAL_PROC, .proc/______qdel_list_wrapper, L), time, TIMER_STOPPABLE)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// Shuttle flags
|
||||
#define SHUTTLE_FLAGS_NONE 0
|
||||
#define SHUTTLE_FLAGS_PROCESS 1 // Should be processed by shuttle subsystem
|
||||
#define SHUTTLE_FLAGS_SUPPLY 2 // This is the supply shuttle. Why is this a tag?
|
||||
#define SHUTTLE_FLAGS_ZERO_G 4 // Shuttle has no internal gravity generation
|
||||
#define SHUTTLE_FLAGS_ALL (~SHUTTLE_FLAGS_NONE)
|
||||
|
||||
// shuttle_landmark flags
|
||||
#define SLANDMARK_FLAG_AUTOSET 1 // If set, will set base area and turf type to same as where it was spawned at
|
||||
#define SLANDMARK_FLAG_ZERO_G 2 // Zero-G shuttles moved here will lose gravity unless the area has ambient gravity.
|
||||
|
||||
// Overmap landable shuttles (/obj/effect/overmap/visitable/ship/landable on a /datum/shuttle/autodock/overmap)
|
||||
#define SHIP_STATUS_LANDED 1 // Ship is at any other shuttle landmark.
|
||||
#define SHIP_STATUS_TRANSIT 2 // Ship is at it's shuttle datum's transition shuttle landmark.
|
||||
#define SHIP_STATUS_OVERMAP 3 // Ship is at its "overmap" shuttle landmark (allowed to move on overmap now)
|
||||
|
||||
// Ferry shuttle location constants
|
||||
#define FERRY_LOCATION_STATION 0
|
||||
#define FERRY_LOCATION_OFFSITE 1
|
||||
#define FERRY_GOING_TO_STATION 0
|
||||
#define FERRY_GOING_TO_OFFSITE 1
|
||||
|
||||
#ifndef DEBUG_SHUTTLES
|
||||
#define log_shuttle(M)
|
||||
#else
|
||||
#define log_shuttle(M) log_debug("[M]")
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
#define SQLITE_TABLE_FEEDBACK "feedback"
|
||||
|
||||
#define SQLITE_FEEDBACK_COLUMN_ID "id"
|
||||
#define SQLITE_FEEDBACK_COLUMN_AUTHOR "author"
|
||||
#define SQLITE_FEEDBACK_COLUMN_TOPIC "topic"
|
||||
#define SQLITE_FEEDBACK_COLUMN_CONTENT "content"
|
||||
#define SQLITE_FEEDBACK_COLUMN_DATETIME "datetime"
|
||||
@@ -52,9 +52,11 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
|
||||
// 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_CHEMISTRY 18
|
||||
#define INIT_ORDER_MAPPING 17
|
||||
#define INIT_ORDER_DECALS 16
|
||||
#define INIT_ORDER_SQLITE 40
|
||||
#define INIT_ORDER_CHEMISTRY 35
|
||||
#define INIT_ORDER_SKYBOX 30
|
||||
#define INIT_ORDER_MAPPING 25
|
||||
#define INIT_ORDER_DECALS 20
|
||||
#define INIT_ORDER_ATOMS 15
|
||||
#define INIT_ORDER_MACHINES 10
|
||||
#define INIT_ORDER_SHUTTLES 3
|
||||
@@ -62,22 +64,27 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
|
||||
#define INIT_ORDER_DEFAULT 0
|
||||
#define INIT_ORDER_LIGHTING 0
|
||||
#define INIT_ORDER_AIR -1
|
||||
#define INIT_ORDER_ASSETS -3
|
||||
#define INIT_ORDER_PLANETS -4
|
||||
#define INIT_ORDER_HOLOMAPS -5
|
||||
#define INIT_ORDER_OVERLAY -6
|
||||
#define INIT_ORDER_ALARM -7
|
||||
#define INIT_ORDER_XENOARCH -20
|
||||
#define INIT_ORDER_CIRCUIT -21
|
||||
#define INIT_ORDER_AI -22
|
||||
#define INIT_ORDER_JOB -23
|
||||
#define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init.
|
||||
|
||||
|
||||
// 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)
|
||||
#define FIRE_PRIORITY_SHUTTLES 5
|
||||
#define FIRE_PRIORITY_TIMERS 7 //VOREStation Emergency Edit
|
||||
#define FIRE_PRIORITY_SUPPLY 5
|
||||
#define FIRE_PRIORITY_ORBIT 8
|
||||
#define FIRE_PRIORITY_VOTE 9
|
||||
#define FIRE_PRIORITY_AI 10
|
||||
#define FIRE_PRIORITY_GARBAGE 15
|
||||
#define FIRE_PRIORITY_ALARM 20
|
||||
#define FIRE_PRIORITY_CHARSETUP 25
|
||||
#define FIRE_PRIORITY_AIRFLOW 30
|
||||
#define FIRE_PRIORITY_AIR 35
|
||||
@@ -87,6 +94,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
|
||||
#define FIRE_PRIORITY_PLANETS 75
|
||||
#define FIRE_PRIORITY_MACHINES 100
|
||||
#define FIRE_PRIORITY_PROJECTILES 150
|
||||
#define FIRE_PRIORITY_CHAT 400
|
||||
#define FIRE_PRIORITY_OVERLAYS 500
|
||||
|
||||
// Macro defining the actual code applying our overlays lists to the BYOND overlays list. (I guess a macro for speed)
|
||||
|
||||
@@ -37,7 +37,11 @@
|
||||
#define ARCHAEO_ALIEN_BOAT 37
|
||||
#define ARCHAEO_IMPERION_CIRCUIT 38
|
||||
#define ARCHAEO_TELECUBE 39
|
||||
#define MAX_ARCHAEO 39
|
||||
#define ARCHAEO_BATTERY 40
|
||||
#define ARCHAEO_SYRINGE 41
|
||||
#define ARCHAEO_RING 42
|
||||
#define ARCHAEO_CLUB 43
|
||||
#define MAX_ARCHAEO 43
|
||||
|
||||
#define DIGSITE_GARDEN 1
|
||||
#define DIGSITE_ANIMAL 2
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
GLOBAL_LIST_INIT(speech_toppings, list("|" = "i", "+" = "b", "_" = "u"))
|
||||
GLOBAL_LIST_EMPTY(meteor_list)
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
//Languages/species/whitelist.
|
||||
GLOBAL_LIST_INIT(all_species, list())
|
||||
GLOBAL_LIST_INIT(all_languages, list())
|
||||
GLOBAL_LIST_INIT(language_name_conflicts, list())
|
||||
GLOBAL_LIST_INIT(language_keys, list()) // Table of say codes for all languages
|
||||
GLOBAL_LIST_INIT(language_key_conflicts, list())
|
||||
GLOBAL_LIST_INIT(whitelisted_species, list(SPECIES_HUMAN)) // Species that require a whitelist check.
|
||||
// VOREStation edit - include custom species
|
||||
GLOBAL_LIST_INIT(playable_species, list(SPECIES_HUMAN, SPECIES_CUSTOM)) // A list of ALL playable species, whitelisted, latejoin or otherwise.
|
||||
|
||||
+103
-6
@@ -5,18 +5,79 @@
|
||||
* Sorting
|
||||
*/
|
||||
|
||||
// Determiner constants
|
||||
#define DET_NONE 0x00;
|
||||
#define DET_DEFINITE 0x01; // the
|
||||
#define DET_INDEFINITE 0x02; // a, an, some
|
||||
#define DET_AUTO 0x04;
|
||||
|
||||
/*
|
||||
* Misc
|
||||
*/
|
||||
|
||||
//Returns a list in plain english as a string
|
||||
/proc/english_list(var/list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" )
|
||||
/proc/english_list(var/list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "")
|
||||
// this proc cannot be merged with counting_english_list to maintain compatibility
|
||||
// with shoddy use of this proc for code logic and for cases that require original order
|
||||
switch(input.len)
|
||||
if(0) return nothing_text
|
||||
if(1) return "[input[1]]"
|
||||
if(2) return "[input[1]][and_text][input[2]]"
|
||||
else return "[jointext(input, comma_text, 1, -1)][final_comma_text][and_text][input[input.len]]"
|
||||
|
||||
//Returns a newline-separated list that counts equal-ish items, outputting count and item names, optionally with icons and specific determiners
|
||||
/proc/counting_english_list(var/list/input, output_icons = TRUE, determiners = DET_NONE, nothing_text = "nothing", line_prefix = "\t", first_item_prefix = "\n", last_item_suffix = "\n", and_text = "\n", comma_text = "\n", final_comma_text = "")
|
||||
var/list/counts = list() // counted input items
|
||||
var/list/items = list() // actual objects for later reference (for icons and formatting)
|
||||
|
||||
// count items
|
||||
for(var/item in input)
|
||||
var/name = "[item]" // index items by name; usually works fairly well for loose equality
|
||||
if(name in counts)
|
||||
counts[name]++
|
||||
else
|
||||
counts[name] = 1
|
||||
items.Add(item)
|
||||
|
||||
// assemble the output list
|
||||
var/list/out = list()
|
||||
var/i = 0
|
||||
for(var/item in items)
|
||||
var/name = "[item]"
|
||||
var/count = counts[name]
|
||||
var/item_str = line_prefix
|
||||
if(count > 1)
|
||||
item_str += "[count]x "
|
||||
|
||||
if(isatom(item))
|
||||
// atoms/items/objects can be pretty and whatnot
|
||||
var/atom/A = item
|
||||
if(output_icons && isicon(A.icon) && !ismob(A)) // mobs tend to have unusable icons
|
||||
item_str += "[bicon(A)] "
|
||||
switch(determiners)
|
||||
if(DET_NONE) item_str += A.name
|
||||
if(DET_DEFINITE) item_str += "\the [A]"
|
||||
if(DET_INDEFINITE) item_str += "\a [A]"
|
||||
else item_str += name
|
||||
else
|
||||
// non-atoms use plain string conversion
|
||||
item_str += name
|
||||
|
||||
if(i == 0)
|
||||
item_str = first_item_prefix + item_str
|
||||
if(i == items.len - 1)
|
||||
item_str = item_str + last_item_suffix
|
||||
|
||||
out.Add(item_str)
|
||||
i++
|
||||
|
||||
// finally return the list using regular english_list builder
|
||||
return english_list(out, nothing_text, and_text, comma_text, final_comma_text)
|
||||
|
||||
//A "preset" for counting_english_list that displays the list "inline" (comma separated)
|
||||
/proc/inline_counting_english_list(var/list/input, output_icons = TRUE, determiners = DET_NONE, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "", line_prefix = "", first_item_prefix = "", last_item_suffix = "")
|
||||
return counting_english_list(input, output_icons, determiners, nothing_text, and_text, comma_text, final_comma_text)
|
||||
|
||||
//Returns list element or null. Should prevent "index out of bounds" error.
|
||||
proc/listgetindex(var/list/list,index)
|
||||
if(istype(list) && list.len)
|
||||
@@ -145,6 +206,20 @@ proc/listclearnulls(list/list)
|
||||
result = first - second
|
||||
return result
|
||||
|
||||
/*
|
||||
Two lists may be different (A!=B) even if they have the same elements.
|
||||
This actually tests if they have the same entries and values.
|
||||
*/
|
||||
/proc/same_entries(var/list/first, var/list/second)
|
||||
if(!islist(first) || !islist(second))
|
||||
return 0
|
||||
if(length(first) != length(second))
|
||||
return 0
|
||||
for(var/entry in first)
|
||||
if(!(entry in second) || (first[entry] != second[entry]))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/*
|
||||
* Returns list containing entries that are in either list but not both.
|
||||
* If skipref = 1, repeated elements are treated as one.
|
||||
@@ -247,6 +322,13 @@ proc/listclearnulls(list/list)
|
||||
else
|
||||
L[key] = temp[key]
|
||||
|
||||
// Return a list of the values in an assoc list (including null)
|
||||
/proc/list_values(var/list/L)
|
||||
var/list/V = list()
|
||||
V.len = L.len // Preallocate!
|
||||
for(var/i in 1 to L.len)
|
||||
V[i] = L[L[i]] // We avoid += in case the value is itself a list
|
||||
return V
|
||||
|
||||
//Mergesort: divides up the list into halves to begin the sort
|
||||
/proc/sortKey(var/list/client/L, var/order = 1)
|
||||
@@ -457,7 +539,7 @@ proc/listclearnulls(list/list)
|
||||
|
||||
//Don't use this on lists larger than half a dozen or so
|
||||
/proc/insertion_sort_numeric_list_ascending(var/list/L)
|
||||
//world.log << "ascending len input: [L.len]"
|
||||
//to_world_log("ascending len input: [L.len]")
|
||||
var/list/out = list(pop(L))
|
||||
for(var/entry in L)
|
||||
if(isnum(entry))
|
||||
@@ -470,13 +552,13 @@ proc/listclearnulls(list/list)
|
||||
if(!success)
|
||||
out.Add(entry)
|
||||
|
||||
//world.log << " output: [out.len]"
|
||||
//to_world_log(" output: [out.len]")
|
||||
return out
|
||||
|
||||
/proc/insertion_sort_numeric_list_descending(var/list/L)
|
||||
//world.log << "descending len input: [L.len]"
|
||||
//to_world_log("descending len input: [L.len]")
|
||||
var/list/out = insertion_sort_numeric_list_ascending(L)
|
||||
//world.log << " output: [out.len]"
|
||||
//to_world_log(" output: [out.len]")
|
||||
return reverselist(out)
|
||||
|
||||
/proc/dd_sortedObjectList(var/list/L, var/cache=list())
|
||||
@@ -762,4 +844,19 @@ proc/dd_sortedTextList(list/incoming)
|
||||
/proc/popleft(list/L)
|
||||
if(L.len)
|
||||
. = L[1]
|
||||
L.Cut(1,2)
|
||||
L.Cut(1,2)
|
||||
|
||||
//generates a list used to randomize transit animations so they aren't in lockstep
|
||||
/proc/get_cross_shift_list(var/size)
|
||||
var/list/result = list()
|
||||
|
||||
result += rand(0, 14)
|
||||
for(var/i in 2 to size)
|
||||
var/shifts = list(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
|
||||
shifts -= result[i - 1] //consecutive shifts should not be equal
|
||||
if(i == size)
|
||||
shifts -= result[1] //because shift list is a ring buffer
|
||||
result += pick(shifts)
|
||||
|
||||
return result
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
A.add_fingerprint(user)
|
||||
var/list/result = A.atmosanalyze(user)
|
||||
if(result && result.len)
|
||||
user << "<span class='notice'>Results of the analysis[src == A ? "" : " of \the [A]"]</span>"
|
||||
to_chat(user, "<span class='notice'>Results of the analysis[src == A ? "" : " of \the [A]"]</span>")
|
||||
for(var/line in result)
|
||||
user << "<span class='notice'>[line]</span>"
|
||||
to_chat(user, "<span class='notice'>[line]</span>")
|
||||
return 1
|
||||
|
||||
user << "<span class='warning'>Your [src] flashes a red light as it fails to analyze \the [A].</span>"
|
||||
to_chat(user, "<span class='warning'>Your [src] flashes a red light as it fails to analyze \the [A].</span>")
|
||||
return 0
|
||||
|
||||
/proc/atmosanalyzer_scan(var/atom/target, var/datum/gas_mixture/mixture, var/mob/user)
|
||||
|
||||
@@ -19,8 +19,6 @@ var/global/list/side_effects = list() //list of all medical sideeffects types
|
||||
var/global/list/mechas_list = list() //list of all mechs. Used by hostile mobs target tracking.
|
||||
var/global/list/joblist = list() //list of all jobstypes, minus borg and AI
|
||||
|
||||
var/global/list/turfs = list() //list of all turfs
|
||||
|
||||
#define all_genders_define_list list(MALE,FEMALE,PLURAL,NEUTER,HERM) //VOREStaton Edit
|
||||
#define all_genders_text_list list("Male","Female","Plural","Neuter","Herm") //VOREStation Edit
|
||||
|
||||
@@ -30,9 +28,6 @@ var/list/mannequins_
|
||||
var/global/list/poster_designs = list()
|
||||
var/global/list/NT_poster_designs = list()
|
||||
|
||||
// Uplinks
|
||||
var/list/obj/item/device/uplink/world_uplinks = list()
|
||||
|
||||
//Preferences stuff
|
||||
//Hairstyles
|
||||
var/global/list/hair_styles_list = list() //stores /datum/sprite_accessory/hair indexed by name
|
||||
@@ -48,7 +43,7 @@ var/datum/category_collection/underwear/global_underwear = new()
|
||||
|
||||
//Backpacks
|
||||
var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt", "Messenger Bag")
|
||||
var/global/list/pdachoicelist = list("Default", "Slim", "Old", "Rugged")
|
||||
var/global/list/pdachoicelist = list("Default", "Slim", "Old", "Rugged", "Holographic")
|
||||
var/global/list/exclude_jobs = list(/datum/job/ai,/datum/job/cyborg)
|
||||
|
||||
// Visual nets
|
||||
@@ -153,17 +148,30 @@ var/global/list/string_slot_flags = list(
|
||||
var/datum/job/J = new T
|
||||
joblist[J.title] = J
|
||||
|
||||
//Languages and species.
|
||||
//Languages
|
||||
paths = typesof(/datum/language)-/datum/language
|
||||
for(var/T in paths)
|
||||
var/datum/language/L = new T
|
||||
GLOB.all_languages[L.name] = L
|
||||
if (isnull(GLOB.all_languages[L.name]))
|
||||
GLOB.all_languages[L.name] = L
|
||||
else
|
||||
log_debug("Language name conflict! [T] is named [L.name], but that is taken by [GLOB.all_languages[L.name].type]")
|
||||
if(isnull(GLOB.language_name_conflicts[L.name]))
|
||||
GLOB.language_name_conflicts[L.name] = list(GLOB.all_languages[L.name])
|
||||
GLOB.language_name_conflicts[L.name] += L
|
||||
|
||||
for (var/language_name in GLOB.all_languages)
|
||||
var/datum/language/L = GLOB.all_languages[language_name]
|
||||
if(!(L.flags & NONGLOBAL))
|
||||
GLOB.language_keys[lowertext(L.key)] = L
|
||||
if(isnull(GLOB.language_keys[L.key]))
|
||||
GLOB.language_keys[L.key] = L
|
||||
else
|
||||
log_debug("Language key conflict! [L] has key [L.key], but that is taken by [(GLOB.language_keys[L.key])]")
|
||||
if(isnull(GLOB.language_key_conflicts[L.key]))
|
||||
GLOB.language_key_conflicts[L.key] = list(GLOB.language_keys[L.key])
|
||||
GLOB.language_key_conflicts[L.key] += L
|
||||
|
||||
//Species
|
||||
var/rkey = 0
|
||||
paths = typesof(/datum/species)
|
||||
for(var/T in paths)
|
||||
@@ -206,7 +214,7 @@ var/global/list/string_slot_flags = list(
|
||||
var/list/L = chemical_reactions_list[reaction]
|
||||
for(var/t in L)
|
||||
. += " has: [t]\n"
|
||||
world << .
|
||||
to_world(.)
|
||||
*/
|
||||
//Hexidecimal numbers
|
||||
var/global/list/hexNums = list("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")
|
||||
|
||||
@@ -426,8 +426,7 @@ var/global/list/remainless_species = list(SPECIES_PROMETHEAN,
|
||||
SPECIES_XENO_QUEEN,
|
||||
SPECIES_SHADOW,
|
||||
SPECIES_GOLEM, //Some special species that may or may not be ever used in event too,
|
||||
SPECIES_SHADEKIN, //Shadefluffers just poof away
|
||||
SPECIES_SHADEKIN_YW) //YW edits
|
||||
SPECIES_SHADEKIN) //Shadefluffers just poof away
|
||||
|
||||
/var/global/list/existing_solargrubs = list()
|
||||
|
||||
@@ -471,6 +470,7 @@ var/global/list/remainless_species = list(SPECIES_PROMETHEAN,
|
||||
|
||||
// Custom species icon bases
|
||||
var/list/blacklisted_icons = list(SPECIES_CUSTOM,SPECIES_PROMETHEAN) //Just ones that won't work well.
|
||||
var/list/whitelisted_icons = list(SPECIES_FENNEC,SPECIES_XENOHYBRID) //Include these anyway
|
||||
for(var/species_name in GLOB.playable_species)
|
||||
if(species_name in blacklisted_icons)
|
||||
continue
|
||||
@@ -478,5 +478,7 @@ var/global/list/remainless_species = list(SPECIES_PROMETHEAN,
|
||||
if(S.spawn_flags & SPECIES_IS_WHITELISTED)
|
||||
continue
|
||||
custom_species_bases += species_name
|
||||
for(var/species_name in whitelisted_icons)
|
||||
custom_species_bases += species_name
|
||||
|
||||
return 1 // Hooks must return 1
|
||||
|
||||
@@ -167,7 +167,7 @@ mob
|
||||
|
||||
Output_Icon()
|
||||
set name = "2. Output Icon"
|
||||
src<<"Icon is: \icon[getFlatIcon(src)]"
|
||||
to_chat(src, "Icon is: [bicon(getFlatIcon(src))]")
|
||||
|
||||
Label_Icon()
|
||||
set name = "3. Label Icon"
|
||||
|
||||
+19
-11
@@ -22,16 +22,16 @@
|
||||
#endif
|
||||
|
||||
/proc/error(msg)
|
||||
world.log << "## ERROR: [msg]"
|
||||
to_world_log("## ERROR: [msg]")
|
||||
|
||||
#define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [src] usr: [usr].")
|
||||
//print a warning message to world.log
|
||||
/proc/warning(msg)
|
||||
world.log << "## WARNING: [msg]"
|
||||
to_world_log("## WARNING: [msg]")
|
||||
|
||||
//print a testing-mode debug message to world.log
|
||||
/proc/testing(msg)
|
||||
world.log << "## TESTING: [msg]"
|
||||
to_world_log("## TESTING: [msg]")
|
||||
|
||||
/proc/log_admin(text)
|
||||
admin_log.Add(text)
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
for(var/client/C in admins)
|
||||
if(C.is_preference_enabled(/datum/client_preference/debug/show_debug_logs))
|
||||
C << "DEBUG: [text]"
|
||||
to_chat(C, "DEBUG: [text]")
|
||||
|
||||
/proc/log_game(text)
|
||||
if (config.log_game)
|
||||
@@ -154,12 +154,12 @@
|
||||
|
||||
|
||||
/proc/log_to_dd(text)
|
||||
world.log << text //this comes before the config check because it can't possibly runtime
|
||||
to_world_log(text) //this comes before the config check because it can't possibly runtime
|
||||
if(config.log_world_output)
|
||||
WRITE_LOG(diary, "DD_OUTPUT: [text]")
|
||||
|
||||
/proc/log_error(text)
|
||||
world.log << text
|
||||
to_world_log(text)
|
||||
WRITE_LOG(error_log, "RUNTIME: [text]")
|
||||
|
||||
/proc/log_misc(text)
|
||||
@@ -174,7 +174,7 @@
|
||||
WRITE_LOG(href_logfile, "HREF: [text]")
|
||||
|
||||
/proc/log_unit_test(text)
|
||||
world.log << "## UNIT_TEST: [text]"
|
||||
to_world_log("## UNIT_TEST: [text]")
|
||||
|
||||
/proc/report_progress(var/progress_message)
|
||||
admin_notice("<span class='boldannounce'>[progress_message]</span>", R_DEBUG)
|
||||
@@ -259,20 +259,28 @@
|
||||
return key_name(whom, 1, include_name)
|
||||
|
||||
// Helper procs for building detailed log lines
|
||||
//
|
||||
// These procs must not fail under ANY CIRCUMSTANCES!
|
||||
//
|
||||
|
||||
/datum/proc/log_info_line()
|
||||
return "[src] ([type])"
|
||||
|
||||
/atom/log_info_line()
|
||||
. = ..()
|
||||
var/turf/t = get_turf(src)
|
||||
if(istype(t))
|
||||
return "([t]) ([t.x],[t.y],[t.z]) ([t.type])"
|
||||
return "[.] @ [t.log_info_line()]"
|
||||
else if(loc)
|
||||
return "([loc]) (0,0,0) ([loc.type])"
|
||||
return "[.] @ ([loc]) (0,0,0) ([loc.type])"
|
||||
else
|
||||
return "(NULL) (0,0,0) (NULL)"
|
||||
return "[.] @ (NULL) (0,0,0) (NULL)"
|
||||
|
||||
/turf/log_info_line()
|
||||
return "([src]) ([x],[y],[z]) ([type])"
|
||||
|
||||
/mob/log_info_line()
|
||||
return "[..()] ([ckey])"
|
||||
return "[..()] (ckey=[ckey])"
|
||||
|
||||
/proc/log_info_line(var/datum/d)
|
||||
if(!d)
|
||||
|
||||
@@ -1,38 +1,3 @@
|
||||
/atom/movable/proc/get_mob()
|
||||
return
|
||||
|
||||
/obj/mecha/get_mob()
|
||||
return occupant
|
||||
|
||||
/obj/vehicle/train/get_mob()
|
||||
return buckled_mobs
|
||||
|
||||
/mob/get_mob()
|
||||
return src
|
||||
|
||||
/mob/living/bot/mulebot/get_mob()
|
||||
if(load && istype(load, /mob/living))
|
||||
return list(src, load)
|
||||
return src
|
||||
|
||||
/proc/mobs_in_view(var/range, var/source)
|
||||
var/list/mobs = list()
|
||||
for(var/atom/movable/AM in view(range, source))
|
||||
var/M = AM.get_mob()
|
||||
if(M)
|
||||
mobs += M
|
||||
|
||||
return mobs
|
||||
|
||||
/proc/mobs_in_xray_view(var/range, var/source)
|
||||
var/list/mobs = list()
|
||||
for(var/atom/movable/AM in orange(range, source))
|
||||
var/M = AM.get_mob()
|
||||
if(M)
|
||||
mobs += M
|
||||
|
||||
return mobs
|
||||
|
||||
proc/random_hair_style(gender, species = SPECIES_HUMAN)
|
||||
var/h_style = "Bald"
|
||||
|
||||
|
||||
@@ -34,12 +34,23 @@
|
||||
|
||||
// Sorts jobs by department, and then by flag within department
|
||||
/proc/cmp_job_datums(var/datum/job/a, var/datum/job/b)
|
||||
. = sorttext(b.department, a.department)
|
||||
if (. == 0) //Same department, push up if they're a head
|
||||
. = b.head_position - a.head_position
|
||||
if (. == 0) //Already in head/nothead spot, sort by name
|
||||
. = 0
|
||||
if( LAZYLEN(a.departments) && LAZYLEN(b.departments) )
|
||||
var/list/common_departments = a.departments & b.departments // Makes a list that contains only departments that were in both.
|
||||
if(!common_departments.len)
|
||||
. = sorttext(b.departments[1], a.departments[1])
|
||||
|
||||
if(. == 0) //Same department, push up if they're a head
|
||||
. = b.sorting_order - a.sorting_order
|
||||
|
||||
if(. == 0) //Already in same sorting order, sort by name
|
||||
. = sorttext(b.title, a.title)
|
||||
|
||||
/proc/cmp_department_datums(var/datum/department/a, var/datum/department/b)
|
||||
. = b.sorting_order - a.sorting_order // First, sort by the sorting order vars.
|
||||
if(. == 0) // If they have the same var, then sort by name.
|
||||
. = sorttext(b.name, a.name)
|
||||
|
||||
// Sorts entries in a performance stats list.
|
||||
/proc/cmp_generic_stat_item_time(list/A, list/B)
|
||||
. = B[STAT_ENTRY_TIME] - A[STAT_ENTRY_TIME]
|
||||
|
||||
@@ -301,11 +301,15 @@ proc/TextPreview(var/string,var/len=40)
|
||||
//For generating neat chat tag-images
|
||||
//The icon var could be local in the proc, but it's a waste of resources
|
||||
// to always create it and then throw it out.
|
||||
/var/icon/text_tag_icons = new('./icons/chattags.dmi')
|
||||
/var/icon/text_tag_icons = 'icons/chattags.dmi'
|
||||
/var/list/text_tag_cache = list()
|
||||
/proc/create_text_tag(var/tagname, var/tagdesc = tagname, var/client/C = null)
|
||||
if(!(C && C.is_preference_enabled(/datum/client_preference/chat_tags)))
|
||||
return tagdesc
|
||||
return "<IMG src='\ref[text_tag_icons.icon]' class='text_tag' iconstate='[tagname]'" + (tagdesc ? " alt='[tagdesc]'" : "") + ">"
|
||||
if(!text_tag_cache[tagname])
|
||||
var/icon/tag = icon(text_tag_icons, tagname)
|
||||
text_tag_cache[tagname] = bicon(tag, TRUE, "text_tag")
|
||||
return text_tag_cache[tagname]
|
||||
|
||||
/proc/contains_az09(var/input)
|
||||
for(var/i=1, i<=length(input), i++)
|
||||
|
||||
+131
-1
@@ -33,9 +33,139 @@
|
||||
available_turfs = start_turfs
|
||||
return pick(available_turfs)
|
||||
|
||||
// Picks a turf that is clearance tiles away from the map edge given by dir, on z-level Z
|
||||
/proc/pick_random_edge_turf(var/dir, var/Z, var/clearance = TRANSITIONEDGE + 1)
|
||||
if(!dir)
|
||||
return
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
return locate(rand(clearance, world.maxx - clearance), world.maxy - clearance, Z)
|
||||
if(SOUTH)
|
||||
return locate(rand(clearance, world.maxx - clearance), clearance, Z)
|
||||
if(EAST)
|
||||
return locate(world.maxx - clearance, rand(clearance, world.maxy - clearance), Z)
|
||||
if(WEST)
|
||||
return locate(clearance, rand(clearance, world.maxy - clearance), Z)
|
||||
|
||||
/proc/is_below_sound_pressure(var/turf/T)
|
||||
var/datum/gas_mixture/environment = T ? T.return_air() : null
|
||||
var/pressure = environment ? environment.return_pressure() : 0
|
||||
if(pressure < SOUND_MINIMUM_PRESSURE)
|
||||
return TRUE
|
||||
return FALSE
|
||||
return FALSE
|
||||
|
||||
/*
|
||||
Turf manipulation
|
||||
*/
|
||||
|
||||
//Returns an assoc list that describes how turfs would be changed if the
|
||||
//turfs in turfs_src were translated by shifting the src_origin to the dst_origin
|
||||
/proc/get_turf_translation(turf/src_origin, turf/dst_origin, list/turfs_src)
|
||||
var/list/turf_map = list()
|
||||
for(var/turf/source in turfs_src)
|
||||
var/x_pos = (source.x - src_origin.x)
|
||||
var/y_pos = (source.y - src_origin.y)
|
||||
var/z_pos = (source.z - src_origin.z)
|
||||
|
||||
var/turf/target = locate(dst_origin.x + x_pos, dst_origin.y + y_pos, dst_origin.z + z_pos)
|
||||
if(!target)
|
||||
error("Null turf in translation @ ([dst_origin.x + x_pos], [dst_origin.y + y_pos], [dst_origin.z + z_pos])")
|
||||
turf_map[source] = target //if target is null, preserve that information in the turf map
|
||||
|
||||
return turf_map
|
||||
|
||||
/proc/translate_turfs(var/list/translation, var/area/base_area = null, var/turf/base_turf)
|
||||
for(var/turf/source in translation)
|
||||
|
||||
var/turf/target = translation[source]
|
||||
|
||||
if(target)
|
||||
if(base_area) ChangeArea(target, get_area(source))
|
||||
var/leave_turf = base_turf ? base_turf : get_base_turf_by_area(base_area ? base_area : source)
|
||||
translate_turf(source, target, leave_turf)
|
||||
if(base_area) ChangeArea(source, base_area)
|
||||
|
||||
//change the old turfs (Currently done by translate_turf for us)
|
||||
//for(var/turf/source in translation)
|
||||
// source.ChangeTurf(base_turf ? base_turf : get_base_turf_by_area(source), 1, 1)
|
||||
|
||||
// Parmaters for stupid historical reasons are:
|
||||
// T - Origin
|
||||
// B - Destination
|
||||
/proc/translate_turf(var/turf/T, var/turf/B, var/turftoleave = null)
|
||||
|
||||
//You can stay, though.
|
||||
if(istype(T,/turf/space))
|
||||
error("Tried to translate a space turf: src=[log_info_line(T)] dst=[log_info_line(B)]")
|
||||
return FALSE // TODO - Is this really okay to do nothing?
|
||||
|
||||
var/turf/X //New Destination Turf
|
||||
|
||||
//Are we doing shuttlework? Just to save another type check later.
|
||||
var/shuttlework = 0
|
||||
|
||||
//Shuttle turfs handle their own fancy moving.
|
||||
if(istype(T,/turf/simulated/shuttle))
|
||||
shuttlework = 1
|
||||
var/turf/simulated/shuttle/SS = T
|
||||
if(!SS.landed_holder) SS.landed_holder = new(turf = SS)
|
||||
X = SS.landed_holder.land_on(B)
|
||||
|
||||
//Generic non-shuttle turf move.
|
||||
else
|
||||
var/old_dir1 = T.dir
|
||||
var/old_icon_state1 = T.icon_state
|
||||
var/old_icon1 = T.icon
|
||||
var/old_underlays = T.underlays.Copy()
|
||||
var/old_decals = T.decals ? T.decals.Copy() : null
|
||||
|
||||
X = B.ChangeTurf(T.type)
|
||||
X.set_dir(old_dir1)
|
||||
X.icon_state = old_icon_state1
|
||||
X.icon = old_icon1
|
||||
X.copy_overlays(T, TRUE)
|
||||
X.underlays = old_underlays
|
||||
X.decals = old_decals
|
||||
|
||||
//Move the air from source to dest
|
||||
var/turf/simulated/ST = T
|
||||
if(istype(ST) && ST.zone)
|
||||
var/turf/simulated/SX = X
|
||||
if(!SX.air)
|
||||
SX.make_air()
|
||||
SX.air.copy_from(ST.zone.air)
|
||||
ST.zone.remove(ST)
|
||||
|
||||
var/z_level_change = FALSE
|
||||
if(T.z != X.z)
|
||||
z_level_change = TRUE
|
||||
|
||||
//Move the objects. Not forceMove because the object isn't "moving" really, it's supposed to be on the "same" turf.
|
||||
for(var/obj/O in T)
|
||||
if(O.simulated)
|
||||
O.loc = X
|
||||
O.update_light()
|
||||
if(z_level_change) // The objects still need to know if their z-level changed.
|
||||
O.onTransitZ(T.z, X.z)
|
||||
|
||||
//Move the mobs unless it's an AI eye or other eye type.
|
||||
for(var/mob/M in T)
|
||||
if(isEye(M)) continue // If we need to check for more mobs, I'll add a variable
|
||||
M.loc = X
|
||||
|
||||
if(z_level_change) // Same goes for mobs.
|
||||
M.onTransitZ(T.z, X.z)
|
||||
|
||||
if(istype(M, /mob/living))
|
||||
var/mob/living/LM = M
|
||||
LM.check_shadow() // Need to check their Z-shadow, which is normally done in forceMove().
|
||||
|
||||
if(shuttlework)
|
||||
var/turf/simulated/shuttle/SS = T
|
||||
SS.landed_holder.leave_turf(turftoleave)
|
||||
else if(turftoleave)
|
||||
T.ChangeTurf(turftoleave)
|
||||
else
|
||||
T.ChangeTurf(get_base_turf_by_area(T))
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
if (4.0) return EAST
|
||||
if (8.0) return WEST
|
||||
else
|
||||
world.log << "UNKNOWN DIRECTION: [direction]"
|
||||
to_world_log("UNKNOWN DIRECTION: [direction]")
|
||||
|
||||
// Turns a direction into text
|
||||
/proc/dir2text(direction)
|
||||
|
||||
@@ -370,7 +370,7 @@ Turf and target are seperate in case you want to teleport some distance from a t
|
||||
if(isAI(src))
|
||||
var/mob/living/silicon/ai/A = src
|
||||
oldname = null//don't bother with the records update crap
|
||||
//world << "<b>[newname] is the AI!</b>"
|
||||
//to_world("<b>[newname] is the AI!</b>")
|
||||
//world << sound('sound/AI/newAI.ogg')
|
||||
// Set eyeobj name
|
||||
A.SetName(newname)
|
||||
@@ -1420,6 +1420,8 @@ var/mob/dview/dview_mob = new
|
||||
#define VARSET_LIST_CALLBACK(target, var_name, var_value) CALLBACK(GLOBAL_PROC, /proc/___callbackvarset, ##target, ##var_name, ##var_value)
|
||||
//dupe code because dm can't handle 3 level deep macros
|
||||
#define VARSET_CALLBACK(datum, var, var_value) CALLBACK(GLOBAL_PROC, /proc/___callbackvarset, ##datum, NAMEOF(##datum, ##var), ##var_value)
|
||||
//we'll see about those 3-level deep macros
|
||||
#define VARSET_IN(datum, var, var_value, time) addtimer(VARSET_CALLBACK(datum, var, var_value), time)
|
||||
|
||||
/proc/___callbackvarset(list_or_datum, var_name, var_value)
|
||||
if(length(list_or_datum))
|
||||
@@ -1577,4 +1579,12 @@ var/mob/dview/dview_mob = new
|
||||
return "\ref[input]"
|
||||
|
||||
/proc/pass()
|
||||
return
|
||||
return
|
||||
|
||||
// Painlessly creates an <a href=...> element.
|
||||
// First argument is where to send the Topic call to when clicked. Should be a reference to an object. This is generally src, but not always.
|
||||
// Second one is for all the params that will be sent. Uses an assoc list (e.g. "value" = "5").
|
||||
// Note that object refs will be converted to text, as if \ref[thing] was done. To get the ref back on Topic() side, you will need to use locate().
|
||||
// Third one is the text that will be clickable.
|
||||
/proc/href(href_src, list/href_params, href_text)
|
||||
return "<a href='?src=\ref[href_src];[list2params(href_params)]'>[href_text]</a>"
|
||||
|
||||
+15
-3
@@ -2,27 +2,39 @@
|
||||
|
||||
#define get_turf(A) get_step(A,0)
|
||||
|
||||
#define get_x(A) (get_step(A, 0)?.x || 0)
|
||||
|
||||
#define get_y(A) (get_step(A, 0)?.y || 0)
|
||||
|
||||
#define get_z(A) (get_step(A, 0)?.z || 0)
|
||||
|
||||
#define RANDOM_BLOOD_TYPE pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+")
|
||||
|
||||
#define to_chat(target, message) target << message
|
||||
#define to_world(message) world << message
|
||||
// #define to_chat(target, message) target << message Not anymore!
|
||||
#define to_chat to_chat_filename=__FILE__;to_chat_line=__LINE__;to_chat_src=src;__to_chat
|
||||
#define to_world(message) to_chat(world, message)
|
||||
#define to_world_log(message) world.log << message
|
||||
// TODO - Baystation has this log to crazy places. For now lets just world.log, but maybe look into it later.
|
||||
#define log_world(message) world.log << message
|
||||
#define log_world(message) to_world_log(message)
|
||||
#define to_file(file_entry, source_var) file_entry << source_var
|
||||
#define from_file(file_entry, target_var) file_entry >> target_var
|
||||
#define show_browser(target, browser_content, browser_name) target << browse(browser_content, browser_name)
|
||||
#define send_rsc(target, rsc_content, rsc_name) target << browse_rsc(rsc_content, rsc_name)
|
||||
#define open_link(target, url) target << link(url)
|
||||
|
||||
// From TG, might be useful to have.
|
||||
// Didn't port SEND_TEXT() since to_chat() appears to serve the same purpose.
|
||||
#define DIRECT_OUTPUT(A, B) A << B
|
||||
#define SEND_IMAGE(target, image) DIRECT_OUTPUT(target, image)
|
||||
#define SEND_SOUND(target, sound) DIRECT_OUTPUT(target, sound)
|
||||
//#define WRITE_LOG is in logging.dm
|
||||
|
||||
#define CanInteract(user, state) (CanUseTopic(user, state) == STATUS_INTERACTIVE)
|
||||
|
||||
#define qdel_null(x) if(x) { qdel(x) ; x = null }
|
||||
|
||||
#define sequential_id(key) uniqueness_repository.Generate(/datum/uniqueness_generator/id_sequential, key)
|
||||
|
||||
#define random_id(key,min_id,max_id) uniqueness_repository.Generate(/datum/uniqueness_generator/id_random, key, min_id, max_id)
|
||||
|
||||
#define ARGS_DEBUG log_debug("[__FILE__] - [__LINE__]") ; for(var/arg in args) { log_debug("\t[log_info_line(arg)]") }
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
var/sdepth = A.storage_depth(src)
|
||||
if((!isturf(A) && A == loc) || (sdepth != -1 && sdepth <= 1))
|
||||
if(W)
|
||||
var/resolved = W.resolve_attackby(A, src)
|
||||
var/resolved = W.resolve_attackby(A, src, click_parameters = params)
|
||||
if(!resolved && A && W)
|
||||
W.afterattack(A, src, 1, params) // 1 indicates adjacency
|
||||
else
|
||||
@@ -134,16 +134,10 @@
|
||||
// A is a turf or is on a turf, or in something on a turf (pen in a box); but not something in something on a turf (pen in a box in a backpack)
|
||||
sdepth = A.storage_depth_turf()
|
||||
if(isturf(A) || isturf(A.loc) || (sdepth != -1 && sdepth <= 1))
|
||||
//VOREStation Edit begin: SHADEKIN
|
||||
var/mob/SK = src
|
||||
if(istype(SK))
|
||||
if(SK.shadekin_phasing_check())
|
||||
return
|
||||
//VOREStation Edit end: SHADEKIN
|
||||
if(A.Adjacent(src) || (W && W.attack_can_reach(src, A, W.reach)) ) // see adjacent.dm
|
||||
if(W)
|
||||
// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
|
||||
var/resolved = W.resolve_attackby(A,src)
|
||||
var/resolved = W.resolve_attackby(A,src, click_parameters = params)
|
||||
if(!resolved && A && W)
|
||||
W.afterattack(A, src, 1, params) // 1: clicking something Adjacent
|
||||
else
|
||||
@@ -188,6 +182,9 @@
|
||||
|
||||
/mob/living/UnarmedAttack(var/atom/A, var/proximity_flag)
|
||||
|
||||
if(is_incorporeal())
|
||||
return 0
|
||||
|
||||
if(!ticker)
|
||||
to_chat(src, "You cannot attack people before the game has started.")
|
||||
return 0
|
||||
|
||||
@@ -270,7 +270,7 @@
|
||||
|
||||
// Makes the ability be triggered. The subclasses of this are responsible for carrying it out in whatever way it needs to.
|
||||
/obj/screen/ability/proc/activate()
|
||||
world << "[src] had activate() called."
|
||||
to_world("[src] had activate() called.")
|
||||
return
|
||||
|
||||
// This checks if the ability can be used.
|
||||
@@ -305,7 +305,7 @@
|
||||
if(object_used && verb_to_call)
|
||||
call(object_used,verb_to_call)(arguments_to_use)
|
||||
// call(object_used,verb_to_call)(arguments_to_use)
|
||||
// world << "Attempted to call([object_used],[verb_to_call])([arguments_to_use])"
|
||||
// to_world("Attempted to call([object_used],[verb_to_call])([arguments_to_use])")
|
||||
// if(hascall(object_used, verb_to_call))
|
||||
// call(object_used,verb_to_call)(arguments_to_use)
|
||||
// else
|
||||
|
||||
@@ -40,8 +40,9 @@ var/list/global_huds = list(
|
||||
|
||||
/datum/global_hud/proc/setup_overlay(var/icon_state)
|
||||
var/obj/screen/screen = new /obj/screen()
|
||||
screen.screen_loc = "1,1"
|
||||
screen.icon = 'icons/obj/hud_full.dmi'
|
||||
screen.alpha = 40 // Adjut this if you want goggle overlays to be thinner or thicker.
|
||||
screen.screen_loc = "SOUTHWEST to NORTHEAST" // Will tile up to the whole screen, scaling beyond 15x15 if needed.
|
||||
screen.icon = 'icons/obj/hud_tiled.dmi'
|
||||
screen.icon_state = icon_state
|
||||
screen.layer = SCREEN_LAYER
|
||||
screen.plane = PLANE_FULLSCREEN
|
||||
@@ -332,11 +333,11 @@ datum/hud/New(mob/owner)
|
||||
set hidden = 1
|
||||
|
||||
if(!hud_used)
|
||||
usr << "<span class='warning'>This mob type does not use a HUD.</span>"
|
||||
to_chat(usr, "<span class='warning'>This mob type does not use a HUD.</span>")
|
||||
return
|
||||
|
||||
if(!ishuman(src))
|
||||
usr << "<span class='warning'>Inventory hiding is currently only supported for human mobs, sorry.</span>"
|
||||
to_chat(usr, "<span class='warning'>Inventory hiding is currently only supported for human mobs, sorry.</span>")
|
||||
return
|
||||
|
||||
if(!client) return
|
||||
|
||||
@@ -223,11 +223,11 @@ var/obj/screen/robot_inventory
|
||||
//r.client.screen += robot_inventory //"store" icon
|
||||
|
||||
if(!r.module)
|
||||
usr << "<span class='danger'>No module selected</span>"
|
||||
to_chat(usr, "<span class='danger'>No module selected</span>")
|
||||
return
|
||||
|
||||
if(!r.module.modules)
|
||||
usr << "<span class='danger'>Selected module has no modules to select</span>"
|
||||
to_chat(usr, "<span class='danger'>Selected module has no modules to select</span>")
|
||||
return
|
||||
|
||||
if(!r.robot_modules_background)
|
||||
|
||||
@@ -205,7 +205,7 @@
|
||||
if(iscarbon(usr))
|
||||
var/mob/living/carbon/C = usr
|
||||
if(C.legcuffed)
|
||||
C << "<span class='notice'>You are legcuffed! You cannot run until you get [C.legcuffed] removed!</span>"
|
||||
to_chat(C, "<span class='notice'>You are legcuffed! You cannot run until you get [C.legcuffed] removed!</span>")
|
||||
C.m_intent = "walk" //Just incase
|
||||
C.hud_used.move_intent.icon_state = "walking"
|
||||
return 1
|
||||
@@ -245,7 +245,7 @@
|
||||
if(!C.stat && !C.stunned && !C.paralysis && !C.restrained())
|
||||
if(C.internal)
|
||||
C.internal = null
|
||||
C << "<span class='notice'>No longer running on internals.</span>"
|
||||
to_chat(C, "<span class='notice'>No longer running on internals.</span>")
|
||||
if(C.internals)
|
||||
C.internals.icon_state = "internal0"
|
||||
else
|
||||
@@ -257,7 +257,7 @@
|
||||
no_mask = 1
|
||||
|
||||
if(no_mask)
|
||||
C << "<span class='notice'>You are not wearing a suitable mask or helmet.</span>"
|
||||
to_chat(C, "<span class='notice'>You are not wearing a suitable mask or helmet.</span>")
|
||||
return 1
|
||||
else
|
||||
var/list/nicename = null
|
||||
@@ -276,12 +276,12 @@
|
||||
tankcheck = list(C.r_hand, C.l_hand, C.back)
|
||||
|
||||
// Rigs are a fucking pain since they keep an air tank in nullspace.
|
||||
if(istype(C.back,/obj/item/weapon/rig))
|
||||
var/obj/item/weapon/rig/rig = C.back
|
||||
if(rig.air_supply && !rig.offline)
|
||||
var/obj/item/weapon/rig/Rig = C.get_rig()
|
||||
if(Rig)
|
||||
if(Rig.air_supply && !Rig.offline)
|
||||
from = "in"
|
||||
nicename |= "hardsuit"
|
||||
tankcheck |= rig.air_supply
|
||||
tankcheck |= Rig.air_supply
|
||||
|
||||
for(var/i=1, i<tankcheck.len+1, ++i)
|
||||
if(istype(tankcheck[i], /obj/item/weapon/tank))
|
||||
@@ -338,7 +338,7 @@
|
||||
//We've determined the best container now we set it as our internals
|
||||
|
||||
if(best)
|
||||
C << "<span class='notice'>You are now running on internals from [tankcheck[best]] [from] your [nicename[best]].</span>"
|
||||
to_chat(C, "<span class='notice'>You are now running on internals from [tankcheck[best]] [from] your [nicename[best]].</span>")
|
||||
C.internal = tankcheck[best]
|
||||
|
||||
|
||||
@@ -346,7 +346,7 @@
|
||||
if(C.internals)
|
||||
C.internals.icon_state = "internal1"
|
||||
else
|
||||
C << "<span class='notice'>You don't have a[breathes=="oxygen" ? "n oxygen" : addtext(" ",breathes)] tank.</span>"
|
||||
to_chat(C, "<span class='notice'>You don't have a[breathes=="oxygen" ? "n oxygen" : addtext(" ",breathes)] tank.</span>")
|
||||
if("act_intent")
|
||||
usr.a_intent_change("right")
|
||||
if(I_HELP)
|
||||
@@ -386,7 +386,7 @@
|
||||
R.hud_used.toggle_show_robot_modules()
|
||||
return 1
|
||||
else
|
||||
R << "You haven't selected a module yet."
|
||||
to_chat(R, "You haven't selected a module yet.")
|
||||
|
||||
if("radio")
|
||||
if(issilicon(usr))
|
||||
@@ -402,7 +402,7 @@
|
||||
R.uneq_active()
|
||||
R.hud_used.update_robot_modules_display()
|
||||
else
|
||||
R << "You haven't selected a module yet."
|
||||
to_chat(R, "You haven't selected a module yet.")
|
||||
|
||||
if("module1")
|
||||
if(istype(usr, /mob/living/silicon/robot))
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
#define SKYBOX_PADDING 4 // How much larger we want the skybox image to be than client's screen (in turfs)
|
||||
#define SKYBOX_PIXELS 736 // Size of skybox image in pixels
|
||||
#define SKYBOX_TURFS (SKYBOX_PIXELS/WORLD_ICON_SIZE)
|
||||
|
||||
// Skybox screen object.
|
||||
/obj/skybox
|
||||
name = "skybox"
|
||||
mouse_opacity = 0
|
||||
anchored = TRUE
|
||||
simulated = FALSE
|
||||
screen_loc = "CENTER,CENTER"
|
||||
plane = SKYBOX_PLANE
|
||||
blend_mode = BLEND_MULTIPLY // You actually need to do it this way or you see it in occlusion.
|
||||
|
||||
// Adjust transform property to scale for client's view var. We assume the skybox is 736x736 px
|
||||
/obj/skybox/proc/scale_to_view(var/view)
|
||||
var/matrix/M = matrix()
|
||||
// Translate to center the icon over us!
|
||||
M.Translate(-(SKYBOX_PIXELS - WORLD_ICON_SIZE) / 2)
|
||||
// Scale appropriately based on view size. (7 results in scale of 1)
|
||||
view = text2num(view) || 7 // Sanitize
|
||||
M.Scale(((min(MAX_CLIENT_VIEW, view) + SKYBOX_PADDING) * 2 + 1) / SKYBOX_TURFS)
|
||||
src.transform = M
|
||||
|
||||
/client
|
||||
var/obj/skybox/skybox
|
||||
|
||||
/client/proc/update_skybox(rebuild)
|
||||
if(!skybox)
|
||||
skybox = new()
|
||||
skybox.scale_to_view(src.view)
|
||||
screen += skybox
|
||||
rebuild = 1
|
||||
|
||||
var/turf/T = get_turf(eye)
|
||||
if(T)
|
||||
if(rebuild)
|
||||
skybox.cut_overlays()
|
||||
skybox.add_overlay(SSskybox.get_skybox(T.z))
|
||||
screen |= skybox
|
||||
skybox.screen_loc = "CENTER:[(world.maxx>>1) - T.x],CENTER:[(world.maxy>>1) - T.y]"
|
||||
|
||||
/mob/Login()
|
||||
. = ..()
|
||||
client.update_skybox(TRUE)
|
||||
|
||||
/mob/Move()
|
||||
var/old_z = get_z(src)
|
||||
. = ..()
|
||||
if(. && client)
|
||||
client.update_skybox(old_z != get_z(src))
|
||||
|
||||
/mob/forceMove()
|
||||
var/old_z = get_z(src)
|
||||
. = ..()
|
||||
if(. && client)
|
||||
client.update_skybox(old_z != get_z(src))
|
||||
|
||||
/mob/set_viewsize()
|
||||
. = ..()
|
||||
if (. && client)
|
||||
client.update_skybox()
|
||||
client.skybox?.scale_to_view(client.view)
|
||||
|
||||
#undef SKYBOX_BORDER
|
||||
#undef SKYBOX_PIXELS
|
||||
#undef SKYBOX_TURFS
|
||||
@@ -28,27 +28,24 @@ avoid code duplication. This includes items that may sometimes act as a standard
|
||||
return
|
||||
|
||||
//I would prefer to rename this to attack(), but that would involve touching hundreds of files.
|
||||
/obj/item/proc/resolve_attackby(atom/A, mob/user, var/attack_modifier = 1)
|
||||
/obj/item/proc/resolve_attackby(atom/A, mob/user, var/attack_modifier = 1, var/click_parameters)
|
||||
pre_attack(A, user)
|
||||
add_fingerprint(user)
|
||||
return A.attackby(src, user, attack_modifier)
|
||||
return A.attackby(src, user, attack_modifier, click_parameters)
|
||||
|
||||
// No comment
|
||||
/atom/proc/attackby(obj/item/W, mob/user, var/attack_modifier)
|
||||
/atom/proc/attackby(obj/item/W, mob/user, var/attack_modifier, var/click_parameters)
|
||||
return
|
||||
|
||||
/atom/movable/attackby(obj/item/W, mob/user, var/attack_modifier)
|
||||
/atom/movable/attackby(obj/item/W, mob/user, var/attack_modifier, var/click_parameters)
|
||||
if(!(W.flags & NOBLUDGEON))
|
||||
visible_message("<span class='danger'>[src] has been hit by [user] with [W].</span>")
|
||||
|
||||
/mob/living/attackby(obj/item/I, mob/user, var/attack_modifier)
|
||||
/mob/living/attackby(obj/item/I, mob/user, var/attack_modifier, var/click_parameters)
|
||||
if(!ismob(user))
|
||||
return 0
|
||||
if(can_operate(src) && I.do_surgery(src,user))
|
||||
if(I.can_do_surgery(src,user))
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
return 1
|
||||
if(attempt_vr(src,"vore_attackby",args)) return //VOREStation Add - The vore, of course.
|
||||
return I.attack(src, user, user.zone_sel.selecting, attack_modifier)
|
||||
|
||||
@@ -113,4 +110,4 @@ avoid code duplication. This includes items that may sometimes act as a standard
|
||||
|
||||
power *= attack_modifier
|
||||
|
||||
return target.hit_with_weapon(src, user, power, hit_zone)
|
||||
return target.hit_with_weapon(src, user, power, hit_zone)
|
||||
|
||||
@@ -61,13 +61,13 @@
|
||||
if(awaygate)
|
||||
user.loc = awaygate.loc
|
||||
else
|
||||
user << "[src] has no destination."
|
||||
to_chat(user, "[src] has no destination.")
|
||||
|
||||
/obj/machinery/gateway/centeraway/attack_ghost(mob/user as mob)
|
||||
if(stationgate)
|
||||
user.loc = stationgate.loc
|
||||
else
|
||||
user << "[src] has no destination."
|
||||
to_chat(user, "[src] has no destination.")
|
||||
|
||||
// -------------------------------------------
|
||||
// This was supposed to be used by adminghosts
|
||||
|
||||
@@ -110,7 +110,7 @@ var/const/tk_maxrange = 15
|
||||
if(focus)
|
||||
d = max(d, get_dist(user, focus)) // whichever is further
|
||||
if(d > tk_maxrange)
|
||||
user << "<span class='notice'>Your mind won't reach that far.</span>"
|
||||
to_chat(user, "<span class='notice'>Your mind won't reach that far.</span>")
|
||||
return
|
||||
|
||||
if(!focus)
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
|
||||
// We manually initialize the alarm handlers instead of looping over all existing types
|
||||
// to make it possible to write: camera.triggerAlarm() rather than alarm_manager.managers[datum/alarm_handler/camera].triggerAlarm() or a variant thereof.
|
||||
/var/global/datum/alarm_handler/atmosphere/atmosphere_alarm = new()
|
||||
/var/global/datum/alarm_handler/camera/camera_alarm = new()
|
||||
/var/global/datum/alarm_handler/fire/fire_alarm = new()
|
||||
/var/global/datum/alarm_handler/motion/motion_alarm = new()
|
||||
/var/global/datum/alarm_handler/power/power_alarm = new()
|
||||
|
||||
// Alarm Manager, the manager for alarms.
|
||||
var/datum/controller/process/alarm/alarm_manager
|
||||
|
||||
/datum/controller/process/alarm
|
||||
var/list/datum/alarm/all_handlers = list()
|
||||
|
||||
/datum/controller/process/alarm/setup()
|
||||
name = "alarm"
|
||||
schedule_interval = 20 // every 2 seconds
|
||||
all_handlers = list(atmosphere_alarm, camera_alarm, fire_alarm, motion_alarm, power_alarm)
|
||||
alarm_manager = src
|
||||
|
||||
/datum/controller/process/alarm/doWork()
|
||||
for(last_object in all_handlers)
|
||||
var/datum/alarm_handler/AH = last_object
|
||||
AH.process()
|
||||
SCHECK
|
||||
|
||||
/datum/controller/process/alarm/proc/active_alarms()
|
||||
var/list/all_alarms = new
|
||||
for(var/datum/alarm_handler/AH in all_handlers)
|
||||
var/list/alarms = AH.alarms
|
||||
all_alarms += alarms
|
||||
|
||||
return all_alarms
|
||||
|
||||
/datum/controller/process/alarm/proc/number_of_active_alarms()
|
||||
var/list/alarms = active_alarms()
|
||||
return alarms.len
|
||||
|
||||
/datum/controller/process/alarm/statProcess()
|
||||
..()
|
||||
stat(null, "[number_of_active_alarms()] alarm\s")
|
||||
@@ -9,10 +9,10 @@ datum/controller/transfer_controller/New()
|
||||
timerbuffer = config.vote_autotransfer_initial
|
||||
shift_hard_end = config.vote_autotransfer_initial + (config.vote_autotransfer_interval * 3) //CHOMPStation Edit //Change this "1" to how many extend votes you want there to be.
|
||||
shift_last_vote = shift_hard_end - config.vote_autotransfer_interval //VOREStation Edit
|
||||
START_PROCESSING(SSobj, src)
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
|
||||
datum/controller/transfer_controller/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
|
||||
datum/controller/transfer_controller/process()
|
||||
currenttick = currenttick + 1
|
||||
|
||||
@@ -21,7 +21,8 @@ var/list/gamemode_cache = list()
|
||||
var/log_pda = 0 // log pda messages
|
||||
var/log_hrefs = 0 // logs all links clicked in-game. Could be used for debugging and tracking down exploits
|
||||
var/log_runtime = 0 // logs world.log to a file
|
||||
var/log_world_output = 0 // log world.log << messages
|
||||
var/log_world_output = 0 // log to_world_log(messages)
|
||||
var/log_graffiti = 0 // logs graffiti
|
||||
var/sql_enabled = 0 // for sql switching
|
||||
var/allow_admin_ooccolor = 0 // Allows admins with relevant permissions to have their own ooc colour
|
||||
var/allow_vote_restart = 0 // allow votes to restart
|
||||
@@ -30,6 +31,7 @@ var/list/gamemode_cache = list()
|
||||
var/allow_admin_jump = 1 // allows admin jumping
|
||||
var/allow_admin_spawning = 1 // allows admin item spawning
|
||||
var/allow_admin_rev = 1 // allows admin revives
|
||||
var/pregame_time = 180 // pregame time in seconds
|
||||
var/vote_delay = 6000 // minimum time between voting sessions (deciseconds, 10 minute default)
|
||||
var/vote_period = 600 // length of voting period (deciseconds, default 1 minute)
|
||||
var/vote_autotransfer_initial = 108000 // Length of time before the first autotransfer vote is called
|
||||
@@ -252,6 +254,21 @@ var/list/gamemode_cache = list()
|
||||
var/random_submap_orientation = FALSE // If true, submaps loaded automatically can be rotated.
|
||||
var/autostart_solars = FALSE // If true, specifically mapped in solar control computers will set themselves up when the round starts.
|
||||
|
||||
// New shiny SQLite stuff.
|
||||
// The basics.
|
||||
var/sqlite_enabled = FALSE // If it should even be active. SQLite can be ran alongside other databases but you should not have them do the same functions.
|
||||
|
||||
// In-Game Feedback.
|
||||
var/sqlite_feedback = FALSE // Feedback cannot be submitted if this is false.
|
||||
var/list/sqlite_feedback_topics = list("General") // A list of 'topics' that feedback can be catagorized under by the submitter.
|
||||
var/sqlite_feedback_privacy = FALSE // If true, feedback submitted can have its author name be obfuscated. This is not 100% foolproof (it's md5 ffs) but can stop casual snooping.
|
||||
var/sqlite_feedback_cooldown = 0 // How long one must wait, in days, to submit another feedback form. Used to help prevent spam, especially with privacy active. 0 = No limit.
|
||||
var/sqlite_feedback_min_age = 0 // Used to block new people from giving feedback. This metric is very bad but it can help slow down spammers.
|
||||
|
||||
// disables the annoying "You have already logged in this round, disconnect or be banned" popup for multikeying, because it annoys the shit out of me when testing.
|
||||
var/disable_cid_warn_popup = FALSE
|
||||
|
||||
|
||||
/datum/configuration/New()
|
||||
var/list/L = typesof(/datum/game_mode) - /datum/game_mode
|
||||
for (var/T in L)
|
||||
@@ -376,6 +393,9 @@ var/list/gamemode_cache = list()
|
||||
if ("log_runtime")
|
||||
config.log_runtime = 1
|
||||
|
||||
if ("log_graffiti")
|
||||
config.log_graffiti = 1
|
||||
|
||||
if ("generate_map")
|
||||
config.generate_map = 1
|
||||
|
||||
@@ -406,6 +426,9 @@ var/list/gamemode_cache = list()
|
||||
if ("default_no_vote")
|
||||
config.vote_no_default = 1
|
||||
|
||||
if ("pregame_time")
|
||||
config.pregame_time = text2num(value)
|
||||
|
||||
if ("vote_delay")
|
||||
config.vote_delay = text2num(value)
|
||||
|
||||
@@ -841,7 +864,25 @@ var/list/gamemode_cache = list()
|
||||
if("autostart_solars")
|
||||
config.autostart_solars = TRUE
|
||||
|
||||
if("sqlite_enabled")
|
||||
config.sqlite_enabled = TRUE
|
||||
|
||||
if("sqlite_feedback")
|
||||
config.sqlite_feedback = TRUE
|
||||
|
||||
if("sqlite_feedback_topics")
|
||||
config.sqlite_feedback_topics = splittext(value, ";")
|
||||
if(!config.sqlite_feedback_topics.len)
|
||||
config.sqlite_feedback_topics += "General"
|
||||
|
||||
if("sqlite_feedback_privacy")
|
||||
config.sqlite_feedback_privacy = TRUE
|
||||
|
||||
if("sqlite_feedback_cooldown")
|
||||
config.sqlite_feedback_cooldown = text2num(value)
|
||||
|
||||
if("disable_cid_warn_popup")
|
||||
config.disable_cid_warn_popup = TRUE
|
||||
|
||||
else
|
||||
log_misc("Unknown setting in configuration: '[name]'")
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
var/limit_visitors = -1 //Unlimited by default
|
||||
var/pto_cap = 100 //Hours
|
||||
var/require_flavor = FALSE
|
||||
var/ipqualityscore_apikey //API key for ipqualityscore.com
|
||||
|
||||
/hook/startup/proc/read_vs_config()
|
||||
var/list/Lines = file2list("config/config.txt")
|
||||
@@ -58,4 +59,6 @@
|
||||
config.pto_job_change = TRUE
|
||||
if ("require_flavor")
|
||||
config.require_flavor = TRUE
|
||||
if ("ipqualityscore_apikey")
|
||||
config.ipqualityscore_apikey = value
|
||||
return 1
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
var/global/datum/emergency_shuttle_controller/emergency_shuttle
|
||||
|
||||
/datum/emergency_shuttle_controller
|
||||
var/datum/shuttle/ferry/emergency/shuttle
|
||||
var/datum/shuttle/autodock/ferry/emergency/shuttle // Set in shuttle_emergency.dm TODO - is it really?
|
||||
var/list/escape_pods
|
||||
|
||||
var/launch_time //the time at which the shuttle will be launched
|
||||
@@ -36,8 +36,8 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
|
||||
if (!shuttle.location) //leaving from the station
|
||||
//launch the pods!
|
||||
for (var/EP in escape_pods)
|
||||
var/datum/shuttle/ferry/escape_pod/pod
|
||||
if(istype(escape_pods[EP], /datum/shuttle/ferry/escape_pod))
|
||||
var/datum/shuttle/autodock/ferry/escape_pod/pod
|
||||
if(istype(escape_pods[EP], /datum/shuttle/autodock/ferry/escape_pod))
|
||||
pod = escape_pods[EP]
|
||||
else
|
||||
continue
|
||||
@@ -63,8 +63,8 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
|
||||
//arm the escape pods
|
||||
if (evac)
|
||||
for (var/EP in escape_pods)
|
||||
var/datum/shuttle/ferry/escape_pod/pod
|
||||
if(istype(escape_pods[EP], /datum/shuttle/ferry/escape_pod))
|
||||
var/datum/shuttle/autodock/ferry/escape_pod/pod
|
||||
if(istype(escape_pods[EP], /datum/shuttle/autodock/ferry/escape_pod))
|
||||
pod = escape_pods[EP]
|
||||
else
|
||||
continue
|
||||
@@ -215,11 +215,11 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
|
||||
|
||||
//returns 1 if the shuttle is currently in transit (or just leaving) to the station
|
||||
/datum/emergency_shuttle_controller/proc/going_to_station()
|
||||
return (!shuttle.direction && shuttle.moving_status != SHUTTLE_IDLE)
|
||||
return shuttle && (!shuttle.direction && shuttle.moving_status != SHUTTLE_IDLE)
|
||||
|
||||
//returns 1 if the shuttle is currently in transit (or just leaving) to centcom
|
||||
/datum/emergency_shuttle_controller/proc/going_to_centcom()
|
||||
return (shuttle.direction && shuttle.moving_status != SHUTTLE_IDLE)
|
||||
return shuttle && (shuttle.direction && shuttle.moving_status != SHUTTLE_IDLE)
|
||||
|
||||
|
||||
/datum/emergency_shuttle_controller/proc/get_status_panel_eta()
|
||||
|
||||
@@ -52,6 +52,7 @@ var/datum/controller/failsafe/Failsafe
|
||||
if(Master.processing && Master.iteration)
|
||||
// Check if processing is done yet.
|
||||
if(Master.iteration == master_iteration)
|
||||
log_debug("DEFCON [defcon]: Master.iteration=[Master.iteration] Master.last_run=[Master.last_run] world.time=[world.time]")
|
||||
switch(defcon)
|
||||
if(4,5)
|
||||
--defcon
|
||||
@@ -71,7 +72,7 @@ var/datum/controller/failsafe/Failsafe
|
||||
master_iteration = 0
|
||||
to_chat(admins, "<span class='adminnotice'>MC restarted successfully</span>")
|
||||
else if(rtn < 0)
|
||||
log_game("FailSafe: Could not restart MC, runtime encountered. Entering defcon 0")
|
||||
log_world("FailSafe: Could not restart MC, runtime encountered. Entering defcon 0")
|
||||
to_chat(admins, "<span class='boldannounce'>ERROR: DEFCON [defcon_pretty()]. Could not restart MC, runtime encountered. I will silently keep retrying.</span>")
|
||||
//if the return number was 0, it just means the mc was restarted too recently, and it just needs some time before we try again
|
||||
//no need to handle that specially when defcon 0 can handle it
|
||||
|
||||
@@ -50,6 +50,8 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
|
||||
var/current_runlevel //for scheduling different subsystems for different stages of the round
|
||||
|
||||
var/dbg_is_running_subsystem = FALSE // TEMPORARY DEBUGGING - true only while we are actually waiting on a subsystem
|
||||
|
||||
var/static/restart_clear = 0
|
||||
var/static/restart_timeout = 0
|
||||
var/static/restart_count = 0
|
||||
@@ -198,7 +200,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
#else
|
||||
world.sleep_offline = 1
|
||||
#endif
|
||||
world.fps = config.fps
|
||||
world.change_fps(config.fps)
|
||||
var/initialized_tod = REALTIMEOFDAY
|
||||
sleep(1)
|
||||
initializations_finished_with_no_players_logged_in = initialized_tod < REALTIMEOFDAY - 10
|
||||
@@ -223,10 +225,12 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
//loop ended, restart the mc
|
||||
log_game("MC crashed or runtimed, restarting")
|
||||
message_admins("MC crashed or runtimed, restarting")
|
||||
log_world("MC crashed or runtimed, restarting")
|
||||
var/rtn2 = Recreate_MC()
|
||||
if (rtn2 <= 0)
|
||||
log_game("Failed to recreate MC (Error code: [rtn2]), it's up to the failsafe now")
|
||||
message_admins("Failed to recreate MC (Error code: [rtn2]), it's up to the failsafe now")
|
||||
log_world("Failed to recreate MC (Error code: [rtn2]), it's up to the failsafe now")
|
||||
Failsafe.defcon = 2
|
||||
|
||||
// Main loop.
|
||||
@@ -338,6 +342,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
subsystems_to_check = tickersubsystems
|
||||
|
||||
if (CheckQueue(subsystems_to_check) <= 0)
|
||||
log_world("MC: CheckQueue(subsystems_to_check) exited uncleanly, SoftReset (error_level=[error_level]")
|
||||
if (!SoftReset(tickersubsystems, runlevel_sorted_subsystems))
|
||||
log_world("MC: SoftReset() failed, crashing")
|
||||
return
|
||||
@@ -350,6 +355,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
|
||||
if (queue_head)
|
||||
if (RunQueue() <= 0)
|
||||
log_world("MC: RunQueue() exited uncleanly, running SoftReset (error_level=[error_level]")
|
||||
if (!SoftReset(tickersubsystems, runlevel_sorted_subsystems))
|
||||
log_world("MC: SoftReset() failed, crashing")
|
||||
return
|
||||
@@ -472,9 +478,11 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
|
||||
queue_node.state = SS_RUNNING
|
||||
|
||||
dbg_is_running_subsystem = TRUE // TEMPORARY DEBUGGING
|
||||
tick_usage = TICK_USAGE
|
||||
var/state = queue_node.ignite(queue_node_paused)
|
||||
tick_usage = TICK_USAGE - tick_usage
|
||||
dbg_is_running_subsystem = FALSE // TEMPORARY DEBUGGING
|
||||
|
||||
if (state == SS_RUNNING)
|
||||
state = SS_IDLE
|
||||
|
||||
@@ -25,7 +25,7 @@ SUBSYSTEM_DEF(ai)
|
||||
// var/mob/living/L = currentrun[currentrun.len]
|
||||
var/datum/ai_holder/A = currentrun[currentrun.len]
|
||||
--currentrun.len
|
||||
if(!A || QDELETED(A)) // Doesn't exist or won't exist soon.
|
||||
if(!A || QDELETED(A) || A.busy) // Doesn't exist or won't exist soon or not doing it this tick
|
||||
continue
|
||||
if(times_fired % 4 == 0 && A.holder.stat != DEAD)
|
||||
A.handle_strategicals()
|
||||
|
||||
@@ -38,7 +38,7 @@ SUBSYSTEM_DEF(air)
|
||||
|
||||
current_cycle = 0
|
||||
var/simulated_turf_count = 0
|
||||
for(var/turf/simulated/S in turfs)
|
||||
for(var/turf/simulated/S in world)
|
||||
simulated_turf_count++
|
||||
S.update_air_properties()
|
||||
CHECK_TICK
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
// We manually initialize the alarm handlers instead of looping over all existing types
|
||||
// to make it possible to write: camera_alarm.triggerAlarm() rather than SSalarm.managers[datum/alarm_handler/camera].triggerAlarm() or a variant thereof.
|
||||
/var/global/datum/alarm_handler/atmosphere/atmosphere_alarm = new()
|
||||
/var/global/datum/alarm_handler/camera/camera_alarm = new()
|
||||
/var/global/datum/alarm_handler/fire/fire_alarm = new()
|
||||
/var/global/datum/alarm_handler/motion/motion_alarm = new()
|
||||
/var/global/datum/alarm_handler/power/power_alarm = new()
|
||||
|
||||
SUBSYSTEM_DEF(alarm)
|
||||
name = "Alarm"
|
||||
wait = 2 SECONDS
|
||||
priority = FIRE_PRIORITY_ALARM
|
||||
init_order = INIT_ORDER_ALARM
|
||||
var/list/datum/alarm/all_handlers
|
||||
var/tmp/list/currentrun = null
|
||||
var/static/list/active_alarm_cache = list()
|
||||
|
||||
/datum/controller/subsystem/alarm/Initialize()
|
||||
all_handlers = list(atmosphere_alarm, camera_alarm, fire_alarm, motion_alarm, power_alarm)
|
||||
. = ..()
|
||||
|
||||
/datum/controller/subsystem/alarm/fire(resumed = FALSE)
|
||||
if(!resumed)
|
||||
src.currentrun = all_handlers.Copy()
|
||||
active_alarm_cache.Cut()
|
||||
|
||||
var/list/currentrun = src.currentrun // Cache for sanic speed
|
||||
while (currentrun.len)
|
||||
var/datum/alarm_handler/AH = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
AH.process()
|
||||
active_alarm_cache += AH.alarms
|
||||
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
/datum/controller/subsystem/alarm/proc/active_alarms()
|
||||
return active_alarm_cache.Copy()
|
||||
|
||||
/datum/controller/subsystem/alarm/proc/number_of_active_alarms()
|
||||
return active_alarm_cache.len
|
||||
|
||||
/datum/controller/subsystem/alarm/stat_entry()
|
||||
..("[number_of_active_alarms()] alarm\s")
|
||||
@@ -0,0 +1,17 @@
|
||||
SUBSYSTEM_DEF(assets)
|
||||
name = "Assets"
|
||||
init_order = INIT_ORDER_ASSETS
|
||||
flags = SS_NO_FIRE
|
||||
var/list/cache = list()
|
||||
var/list/preload = list()
|
||||
|
||||
/datum/controller/subsystem/assets/Initialize(timeofday)
|
||||
for(var/type in typesof(/datum/asset) - list(/datum/asset, /datum/asset/simple))
|
||||
var/datum/asset/A = new type()
|
||||
A.register()
|
||||
|
||||
preload = cache.Copy() //don't preload assets generated during the round
|
||||
|
||||
for(var/client/C in GLOB.clients)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/getFilesSlow, C, preload, FALSE), 10)
|
||||
return ..()
|
||||
@@ -8,9 +8,9 @@ SUBSYSTEM_DEF(atoms)
|
||||
init_order = INIT_ORDER_ATOMS
|
||||
flags = SS_NO_FIRE
|
||||
|
||||
var/initialized = INITIALIZATION_INSSATOMS
|
||||
var/static/initialized = INITIALIZATION_INSSATOMS
|
||||
// var/list/created_atoms // This is never used, so don't bother. ~Leshana
|
||||
var/old_initialized
|
||||
var/static/old_initialized
|
||||
|
||||
var/list/late_loaders
|
||||
var/list/created_atoms
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
SUBSYSTEM_DEF(chat)
|
||||
name = "Chat"
|
||||
flags = SS_TICKER
|
||||
wait = 1 // SS_TICKER means this runs every tick
|
||||
priority = FIRE_PRIORITY_CHAT
|
||||
init_order = INIT_ORDER_CHAT
|
||||
|
||||
var/list/msg_queue = list()
|
||||
|
||||
/datum/controller/subsystem/chat/Initialize(timeofday)
|
||||
init_vchat()
|
||||
..()
|
||||
|
||||
/datum/controller/subsystem/chat/fire()
|
||||
var/list/msg_queue = src.msg_queue // Local variable for sanic speed.
|
||||
for(var/i in msg_queue)
|
||||
var/client/C = i
|
||||
var/list/messages = msg_queue[C]
|
||||
msg_queue -= C
|
||||
if (C)
|
||||
C << output(jsEncode(messages), "htmloutput:putmessage")
|
||||
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
/datum/controller/subsystem/chat/stat_entry()
|
||||
..("C:[msg_queue.len]")
|
||||
|
||||
/datum/controller/subsystem/chat/proc/queue(target, time, message, handle_whitespace = TRUE)
|
||||
if(!target || !message)
|
||||
return
|
||||
|
||||
if(!istext(message))
|
||||
stack_trace("to_chat called with invalid input type")
|
||||
return
|
||||
|
||||
// Currently to_chat(world, ...) gets sent individually to each client. Consider.
|
||||
if(target == world)
|
||||
target = GLOB.clients
|
||||
|
||||
//Some macros remain in the string even after parsing and fuck up the eventual output
|
||||
var/original_message = message
|
||||
message = replacetext(message, "\n", "<br>")
|
||||
message = replacetext(message, "\improper", "")
|
||||
message = replacetext(message, "\proper", "")
|
||||
|
||||
if(isnull(time))
|
||||
time = world.time
|
||||
|
||||
var/list/messageStruct = list("time" = time, "message" = message);
|
||||
|
||||
if(islist(target))
|
||||
for(var/I in target)
|
||||
var/client/C = CLIENT_FROM_VAR(I) //Grab us a client if possible
|
||||
|
||||
if(!C)
|
||||
return
|
||||
|
||||
if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file.
|
||||
//Send it to the old style output window.
|
||||
DIRECT_OUTPUT(C, original_message)
|
||||
continue
|
||||
|
||||
// // Client still loading, put their messages in a queue - Actually don't, logged already in database.
|
||||
// if(!C.chatOutput.loaded && C.chatOutput.message_queue && islist(C.chatOutput.message_queue))
|
||||
// C.chatOutput.message_queue[++C.chatOutput.message_queue.len] = messageStruct
|
||||
// continue
|
||||
|
||||
LAZYINITLIST(msg_queue[C])
|
||||
msg_queue[C][++msg_queue[C].len] = messageStruct
|
||||
else
|
||||
var/client/C = CLIENT_FROM_VAR(target) //Grab us a client if possible
|
||||
|
||||
if(!C)
|
||||
return
|
||||
|
||||
if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file.
|
||||
DIRECT_OUTPUT(C, original_message)
|
||||
return
|
||||
|
||||
// // Client still loading, put their messages in a queue - Actually don't, logged already in database.
|
||||
// if(!C.chatOutput.loaded && C.chatOutput.message_queue && islist(C.chatOutput.message_queue))
|
||||
// C.chatOutput.message_queue[++C.chatOutput.message_queue.len] = messageStruct
|
||||
// return
|
||||
|
||||
LAZYINITLIST(msg_queue[C])
|
||||
msg_queue[C][++msg_queue[C].len] = messageStruct
|
||||
@@ -1,6 +1,8 @@
|
||||
SUBSYSTEM_DEF(events)
|
||||
name = "Events"
|
||||
wait = 20
|
||||
wait = 2 SECONDS
|
||||
|
||||
var/tmp/list/currentrun = null
|
||||
|
||||
var/list/datum/event/active_events = list()
|
||||
var/list/datum/event/finished_events = list()
|
||||
@@ -11,23 +13,37 @@ SUBSYSTEM_DEF(events)
|
||||
var/datum/event_meta/new_event = new
|
||||
|
||||
/datum/controller/subsystem/events/Initialize()
|
||||
allEvents = typesof(/datum/event) - /datum/event
|
||||
event_containers = list(
|
||||
EVENT_LEVEL_MUNDANE = new/datum/event_container/mundane,
|
||||
EVENT_LEVEL_MODERATE = new/datum/event_container/moderate,
|
||||
EVENT_LEVEL_MAJOR = new/datum/event_container/major
|
||||
)
|
||||
allEvents = typesof(/datum/event) - /datum/event
|
||||
if(global.using_map.use_overmap)
|
||||
GLOB.overmap_event_handler.create_events(global.using_map.overmap_z, global.using_map.overmap_size, global.using_map.overmap_event_areas)
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/events/fire(resumed)
|
||||
for(var/datum/event/E in active_events)
|
||||
if (!resumed)
|
||||
src.currentrun = active_events.Copy()
|
||||
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
while (currentrun.len)
|
||||
var/datum/event/E = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if(E.processing_active)
|
||||
E.process()
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
for(var/i = EVENT_LEVEL_MUNDANE to EVENT_LEVEL_MAJOR)
|
||||
var/list/datum/event_container/EC = event_containers[i]
|
||||
EC.process()
|
||||
|
||||
/datum/controller/subsystem/events/stat_entry()
|
||||
..("E:[active_events.len]")
|
||||
|
||||
/datum/controller/subsystem/events/Recover()
|
||||
if(SSevents.active_events)
|
||||
active_events |= SSevents.active_events
|
||||
@@ -35,6 +51,8 @@ SUBSYSTEM_DEF(events)
|
||||
finished_events |= SSevents.finished_events
|
||||
|
||||
/datum/controller/subsystem/events/proc/event_complete(var/datum/event/E)
|
||||
active_events -= E
|
||||
|
||||
if(!E.event_meta || !E.severity) // datum/event is used here and there for random reasons, maintaining "backwards compatibility"
|
||||
log_debug("Event of '[E.type]' with missing meta-data has completed.")
|
||||
return
|
||||
@@ -50,7 +68,7 @@ SUBSYSTEM_DEF(events)
|
||||
log_debug("Event '[EM.name]' has completed at [stationtime2text()].")
|
||||
|
||||
/datum/controller/subsystem/events/proc/delay_events(var/severity, var/delay)
|
||||
var/list/datum/event_container/EC = event_containers[severity]
|
||||
var/datum/event_container/EC = event_containers[severity]
|
||||
EC.next_event_time += delay
|
||||
|
||||
/datum/controller/subsystem/events/proc/RoundEnd()
|
||||
|
||||
@@ -1,42 +1,64 @@
|
||||
SUBSYSTEM_DEF(inactivity)
|
||||
name = "AFK Kick"
|
||||
wait = 600
|
||||
flags = SS_BACKGROUND | SS_NO_TICK_CHECK
|
||||
name = "Inactivity"
|
||||
wait = 1 MINUTE
|
||||
flags = SS_NO_INIT | SS_BACKGROUND
|
||||
var/tmp/list/client_list
|
||||
var/number_kicked = 0
|
||||
|
||||
/datum/controller/subsystem/inactivity/fire()
|
||||
if(config.kick_inactive)
|
||||
for(var/i in GLOB.clients)
|
||||
var/client/C = i
|
||||
if(C.is_afk(config.kick_inactive MINUTES) && !C.holder) // VOREStation Edit - Allow admins to idle
|
||||
to_chat(C,"<span class='warning'>You have been inactive for more than [config.kick_inactive] minute\s and have been disconnected.</span>")
|
||||
var/information
|
||||
/datum/controller/subsystem/inactivity/fire(resumed = FALSE)
|
||||
if (!config.kick_inactive)
|
||||
can_fire = FALSE
|
||||
return
|
||||
if (!resumed)
|
||||
client_list = GLOB.clients.Copy()
|
||||
|
||||
if(C.mob)
|
||||
if(ishuman(C.mob))
|
||||
var/job
|
||||
var/mob/living/carbon/human/H = C.mob
|
||||
var/datum/data/record/R = find_general_record("name", H.real_name)
|
||||
if(R)
|
||||
job = R.fields["real_rank"]
|
||||
if(!job && H.mind)
|
||||
job = H.mind.assigned_role
|
||||
if(!job && H.job)
|
||||
job = H.job
|
||||
if(job)
|
||||
information = " while [job]."
|
||||
while(client_list.len)
|
||||
var/client/C = client_list[client_list.len]
|
||||
client_list.len--
|
||||
if(C.is_afk(config.kick_inactive MINUTES) && can_kick(C))
|
||||
to_chat(C, "<span class='warning'>You have been inactive for more than [config.kick_inactive] minute\s and have been disconnected.</span>")
|
||||
|
||||
else if(issilicon(C.mob))
|
||||
information = " while a silicon."
|
||||
if(isAI(C.mob))
|
||||
var/mob/living/silicon/ai/A = C.mob
|
||||
empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(A.loc)
|
||||
global_announcer.autosay("[A] has been moved to intelligence storage.", "Artificial Intelligence Oversight")
|
||||
A.clear_client()
|
||||
information = " while an AI."
|
||||
var/information
|
||||
if(C.mob)
|
||||
if(ishuman(C.mob))
|
||||
var/job
|
||||
var/mob/living/carbon/human/H = C.mob
|
||||
var/datum/data/record/R = find_general_record("name", H.real_name)
|
||||
if(R)
|
||||
job = R.fields["real_rank"]
|
||||
if(!job && H.mind)
|
||||
job = H.mind.assigned_role
|
||||
if(!job && H.job)
|
||||
job = H.job
|
||||
if(job)
|
||||
information = " while [job]."
|
||||
|
||||
var/adminlinks
|
||||
adminlinks = " (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[C.mob.x];Y=[C.mob.y];Z=[C.mob.z]'>JMP</a>|<A HREF='?_src_=holder;cryoplayer=\ref[C.mob]'>CRYO</a>)"
|
||||
else if(isobserver(C.mob))
|
||||
information = " while a ghost."
|
||||
|
||||
log_and_message_admins("being kicked for AFK[information][adminlinks]", C.mob)
|
||||
else if(issilicon(C.mob))
|
||||
information = " while a silicon."
|
||||
if(isAI(C.mob))
|
||||
var/mob/living/silicon/ai/A = C.mob
|
||||
empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(A.loc)
|
||||
global_announcer.autosay("[A] has been moved to intelligence storage.", "Artificial Intelligence Oversight")
|
||||
A.clear_client()
|
||||
information = " while an AI."
|
||||
|
||||
qdel(C)
|
||||
var/adminlinks
|
||||
adminlinks = " (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[C.mob.x];Y=[C.mob.y];Z=[C.mob.z]'>JMP</a>|<A HREF='?_src_=holder;cryoplayer=\ref[C.mob]'>CRYO</a>)"
|
||||
|
||||
log_and_message_admins("being kicked for AFK[information][adminlinks]", C.mob)
|
||||
|
||||
qdel(C)
|
||||
number_kicked++
|
||||
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
/datum/controller/subsystem/inactivity/stat_entry()
|
||||
..("Kicked: [number_kicked]")
|
||||
|
||||
/datum/controller/subsystem/inactivity/proc/can_kick(var/client/C)
|
||||
if(C.holder) return FALSE //VOREStation Add - Don't kick admins.
|
||||
return TRUE
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
SUBSYSTEM_DEF(job)
|
||||
name = "Job"
|
||||
init_order = INIT_ORDER_JOB
|
||||
flags = SS_NO_FIRE
|
||||
|
||||
var/list/occupations = list() //List of all jobs
|
||||
var/list/datum/job/name_occupations = list() //Dict of all jobs, keys are titles
|
||||
var/list/type_occupations = list() //Dict of all jobs, keys are types
|
||||
|
||||
var/list/department_datums = list()
|
||||
var/debug_messages = FALSE
|
||||
|
||||
|
||||
/datum/controller/subsystem/job/Initialize(timeofday)
|
||||
if(!department_datums.len)
|
||||
setup_departments()
|
||||
if(!occupations.len)
|
||||
setup_occupations()
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/job/proc/setup_occupations(faction = "Station")
|
||||
occupations = list()
|
||||
var/list/all_jobs = subtypesof(/datum/job)
|
||||
if(!all_jobs.len)
|
||||
to_chat(world, span("warning", "Error setting up jobs, no job datums found"))
|
||||
return FALSE
|
||||
|
||||
for(var/J in all_jobs)
|
||||
var/datum/job/job = new J()
|
||||
if(!job)
|
||||
continue
|
||||
if(job.faction != faction)
|
||||
continue
|
||||
occupations += job
|
||||
name_occupations[job.title] = job
|
||||
type_occupations[J] = job
|
||||
if(LAZYLEN(job.departments))
|
||||
add_to_departments(job)
|
||||
|
||||
sortTim(occupations, /proc/cmp_job_datums)
|
||||
for(var/D in department_datums)
|
||||
var/datum/department/dept = department_datums[D]
|
||||
sortTim(dept.jobs, /proc/cmp_job_datums, TRUE)
|
||||
sortTim(dept.primary_jobs, /proc/cmp_job_datums, TRUE)
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/controller/subsystem/job/proc/add_to_departments(datum/job/J)
|
||||
// Adds to the regular job lists in the departments, which allow multiple departments for a job.
|
||||
for(var/D in J.departments)
|
||||
var/datum/department/dept = LAZYACCESS(department_datums, D)
|
||||
if(!istype(dept))
|
||||
job_debug_message("Job '[J.title]' is defined as being inside department '[D]', but it does not exist.")
|
||||
continue
|
||||
dept.jobs[J.title] = J
|
||||
|
||||
// Now for the 'primary' department for a job, which is defined as being the first department in the list for a job.
|
||||
// This results in no duplicates, which can be useful in some situations.
|
||||
if(LAZYLEN(J.departments))
|
||||
var/primary_department = J.departments[1]
|
||||
var/datum/department/dept = LAZYACCESS(department_datums, primary_department)
|
||||
if(!istype(dept))
|
||||
job_debug_message("Job '[J.title]' has their primary department be '[primary_department]', but it does not exist.")
|
||||
else
|
||||
dept.primary_jobs[J.title] = J
|
||||
|
||||
/datum/controller/subsystem/job/proc/setup_departments()
|
||||
for(var/t in subtypesof(/datum/department))
|
||||
var/datum/department/D = new t()
|
||||
department_datums[D.name] = D
|
||||
|
||||
sortTim(department_datums, /proc/cmp_department_datums, TRUE)
|
||||
|
||||
/datum/controller/subsystem/job/proc/get_all_department_datums()
|
||||
var/list/dept_datums = list()
|
||||
for(var/D in department_datums)
|
||||
dept_datums += department_datums[D]
|
||||
return dept_datums
|
||||
|
||||
/datum/controller/subsystem/job/proc/get_job(rank)
|
||||
if(!occupations.len)
|
||||
setup_occupations()
|
||||
return name_occupations[rank]
|
||||
|
||||
/datum/controller/subsystem/job/proc/get_job_type(jobtype)
|
||||
if(!occupations.len)
|
||||
setup_occupations()
|
||||
return type_occupations[jobtype]
|
||||
|
||||
// Determines if a job title is inside of a specific department.
|
||||
// Useful to replace the old `if(job_title in command_positions)` code.
|
||||
/datum/controller/subsystem/job/proc/is_job_in_department(rank, target_department_name)
|
||||
var/datum/department/D = LAZYACCESS(department_datums, target_department_name)
|
||||
if(istype(D))
|
||||
return LAZYFIND(D.jobs, rank) ? TRUE : FALSE
|
||||
return FALSE
|
||||
|
||||
// Returns a list of all job names in a specific department.
|
||||
/datum/controller/subsystem/job/proc/get_job_titles_in_department(target_department_name)
|
||||
var/datum/department/D = LAZYACCESS(department_datums, target_department_name)
|
||||
if(istype(D))
|
||||
var/list/job_titles = list()
|
||||
for(var/J in D.jobs)
|
||||
job_titles += J
|
||||
return job_titles
|
||||
|
||||
job_debug_message("Was asked to get job titles for a non-existant department '[target_department_name]'.")
|
||||
return list()
|
||||
|
||||
// Returns a reference to the primary department datum that a job is in.
|
||||
// Can receive job datum refs, typepaths, or job title strings.
|
||||
/datum/controller/subsystem/job/proc/get_primary_department_of_job(datum/job/J)
|
||||
if(!istype(J, /datum/job))
|
||||
if(ispath(J))
|
||||
J = get_job_type(J)
|
||||
else if(istext(J))
|
||||
J = get_job(J)
|
||||
|
||||
if(!istype(J))
|
||||
job_debug_message("Was asked to get department for job '[J]', but input could not be resolved into a job datum.")
|
||||
return
|
||||
|
||||
if(!LAZYLEN(J.departments))
|
||||
return
|
||||
|
||||
var/primary_department = J.departments[1]
|
||||
var/datum/department/dept = LAZYACCESS(department_datums, primary_department)
|
||||
if(!istype(dept))
|
||||
job_debug_message("Job '[J.title]' has their primary department be '[primary_department]', but it does not exist.")
|
||||
return
|
||||
|
||||
return department_datums[primary_department]
|
||||
|
||||
// Someday it might be good to port code/game/jobs/job_controller.dm to here and clean it up.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/datum/controller/subsystem/job/proc/job_debug_message(message)
|
||||
if(debug_messages)
|
||||
log_debug("JOB DEBUG: [message]")
|
||||
@@ -1,30 +1,29 @@
|
||||
// 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
|
||||
flags = SS_NO_FIRE
|
||||
|
||||
var/list/map_templates = list()
|
||||
var/dmm_suite/maploader = null
|
||||
|
||||
/datum/controller/subsystem/mapping/Initialize(timeofday)
|
||||
if(subsystem_initialized)
|
||||
return
|
||||
world.max_z_changed() // This is to set up the player z-level list, maxz hasn't actually changed (probably)
|
||||
maploader = new()
|
||||
load_map_templates()
|
||||
|
||||
if(config.generate_map)
|
||||
// Map-gen is still very specific to the map, however putting it here should ensure it loads in the correct order.
|
||||
if(using_map.perform_map_generation())
|
||||
using_map.refresh_mining_turfs()
|
||||
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/load_map_templates()
|
||||
for(var/T in subtypesof(/datum/map_template))
|
||||
var/datum/map_template/template = T
|
||||
if(!(initial(template.mappath))) // If it's missing the actual path its probably a base type or being used for inheritence.
|
||||
continue
|
||||
template = new T()
|
||||
map_templates[template.name] = template
|
||||
return TRUE
|
||||
// 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
|
||||
flags = SS_NO_FIRE
|
||||
|
||||
var/list/map_templates = list()
|
||||
var/dmm_suite/maploader = null
|
||||
|
||||
/datum/controller/subsystem/mapping/Initialize(timeofday)
|
||||
if(subsystem_initialized)
|
||||
return
|
||||
world.max_z_changed() // This is to set up the player z-level list, maxz hasn't actually changed (probably)
|
||||
maploader = new()
|
||||
load_map_templates()
|
||||
|
||||
if(config.generate_map)
|
||||
// Map-gen is still very specific to the map, however putting it here should ensure it loads in the correct order.
|
||||
using_map.perform_map_generation()
|
||||
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/load_map_templates()
|
||||
for(var/T in subtypesof(/datum/map_template))
|
||||
var/datum/map_template/template = T
|
||||
if(!(initial(template.mappath))) // If it's missing the actual path its probably a base type or being used for inheritence.
|
||||
continue
|
||||
template = new T()
|
||||
map_templates[template.name] = template
|
||||
return TRUE
|
||||
|
||||
@@ -27,8 +27,7 @@ SUBSYSTEM_DEF(mapping)
|
||||
|
||||
if(config.generate_map)
|
||||
// Map-gen is still very specific to the map, however putting it here should ensure it loads in the correct order.
|
||||
if(using_map.perform_map_generation())
|
||||
using_map.refresh_mining_turfs()
|
||||
using_map.perform_map_generation()
|
||||
|
||||
loadEngine()
|
||||
preloadShelterTemplates()
|
||||
|
||||
@@ -1,41 +1,17 @@
|
||||
SUBSYSTEM_DEF(nanoui)
|
||||
name = "NanoUI"
|
||||
wait = 5
|
||||
flags = SS_NO_INIT
|
||||
// a list of current open /nanoui UIs, grouped by src_object and ui_key
|
||||
var/list/open_uis = list()
|
||||
// a list of current open /nanoui UIs, not grouped, for use in processing
|
||||
var/list/processing_uis = list()
|
||||
// a list of asset filenames which are to be sent to the client on user logon
|
||||
var/list/asset_files = list()
|
||||
|
||||
/datum/controller/subsystem/nanoui/Initialize()
|
||||
var/list/nano_asset_dirs = list(\
|
||||
"nano/css/",\
|
||||
"nano/images/",\
|
||||
"nano/images/status_icons/",\
|
||||
"nano/images/modular_computers/",\
|
||||
"nano/js/",\
|
||||
"nano/templates/"\
|
||||
)
|
||||
|
||||
var/list/filenames = null
|
||||
for (var/path in nano_asset_dirs)
|
||||
filenames = flist(path)
|
||||
for(var/filename in filenames)
|
||||
if(copytext(filename, length(filename)) != "/") // filenames which end in "/" are actually directories, which we want to ignore
|
||||
if(fexists(path + filename))
|
||||
asset_files.Add(fcopy_rsc(path + filename)) // add this file to asset_files for sending to clients when they connect
|
||||
.=..()
|
||||
for(var/i in GLOB.clients)
|
||||
send_resources(i)
|
||||
|
||||
/datum/controller/subsystem/nanoui/Recover()
|
||||
if(SSnanoui.open_uis)
|
||||
open_uis |= SSnanoui.open_uis
|
||||
if(SSnanoui.processing_uis)
|
||||
processing_uis |= SSnanoui.processing_uis
|
||||
if(SSnanoui.asset_files)
|
||||
asset_files |= SSnanoui.asset_files
|
||||
|
||||
/datum/controller/subsystem/nanoui/stat_entry()
|
||||
return ..("[processing_uis.len] UIs")
|
||||
@@ -44,10 +20,3 @@ SUBSYSTEM_DEF(nanoui)
|
||||
for(var/thing in processing_uis)
|
||||
var/datum/nanoui/UI = thing
|
||||
UI.process()
|
||||
|
||||
//Sends asset files to a client, called on client/New()
|
||||
/datum/controller/subsystem/nanoui/proc/send_resources(client)
|
||||
if(!subsystem_initialized)
|
||||
return
|
||||
for(var/file in asset_files)
|
||||
client << browse_rsc(file) // send the file to the client
|
||||
|
||||
@@ -36,15 +36,13 @@ SUBSYSTEM_DEF(persist)
|
||||
|
||||
// Try and detect job and department of mob
|
||||
var/datum/job/J = detect_job(M)
|
||||
if(!istype(J) || !J.department || !J.timeoff_factor)
|
||||
if(!istype(J) || !J.pto_type || !J.timeoff_factor)
|
||||
if (MC_TICK_CHECK)
|
||||
return
|
||||
continue
|
||||
|
||||
// Do not collect useless PTO
|
||||
var/department_earning = J.department
|
||||
if(J.department == "Command")
|
||||
department_earning = "Civilian"
|
||||
var/department_earning = J.pto_type
|
||||
clear_unused_pto(M)
|
||||
|
||||
// Update client whatever
|
||||
@@ -90,6 +88,6 @@ SUBSYSTEM_DEF(persist)
|
||||
/datum/controller/subsystem/persist/proc/clear_unused_pto(var/mob/M)
|
||||
var/client/C = M.client
|
||||
LAZYINITLIST(C.department_hours)
|
||||
if(C.department_hours["Command"])
|
||||
C.department_hours["Command"] = null
|
||||
C.department_hours.Remove("Command")
|
||||
if(C.department_hours[DEPARTMENT_COMMAND])
|
||||
C.department_hours[DEPARTMENT_COMMAND] = null
|
||||
C.department_hours.Remove(DEPARTMENT_COMMAND)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user