diff --git a/.gitignore b/.gitignore index b0cdc822cb3..0574bbe5ccc 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,4 @@ data/ /maps/backup/* /maps/cyberiad.dmm.backup -/nano/debug.html \ No newline at end of file +/nano/debug.html diff --git a/LICENSE-AGPL3.txt b/LICENSE-AGPL3.txt new file mode 100644 index 00000000000..2def0e8831c --- /dev/null +++ b/LICENSE-AGPL3.txt @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. \ No newline at end of file diff --git a/LICENSE-GPL3.txt b/LICENSE-GPL3.txt index 20d40b6bcec..e4ca08d4b0d 100644 --- a/LICENSE-GPL3.txt +++ b/LICENSE-GPL3.txt @@ -1,3 +1,7 @@ +Note: New submissions as of 5th January 2015 now fall under AGPL v3, prior code is +still licensed GPL v3, see README.md for details. + + GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -671,4 +675,4 @@ into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read -. \ No newline at end of file +. diff --git a/README.md b/README.md index 2c1859126cf..d5c90980bad 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ -# baystation12 +# Paradise -[Website](http://baystation12.net/) - [Code](http://github.com/Baystation12/Baystation12/) - [IRC](http://baystation12.net/forums/viewtopic.php?f=12&t=5088) +[Website](http://www.nanotrasen.se/) - [Code](https://github.com/ParadiseSS13/Paradise) - [IRC](http://www.nanotrasen.se/phpBB3/viewtopic.php?f=10&t=1113) --- ### GETTING THE CODE The simplest way to obtain the code is using the github .zip feature. -Click [here](https://github.com/Baystation12/Baystation12/archive/master.zip) to get the latest code as a .zip file, then unzip it to wherever you want. +Click [here](https://github.com/ParadiseSS13/Paradise/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/Baystation12/Baystation12.git + git clone https://github.com/ParadiseSS13/Paradise.git (hint: hold down ctrl and press insert to paste into git bash) @@ -21,23 +21,23 @@ This will take a while to download, but it provides an easier method for updatin First-time installation should be fairly straightforward. First, you'll need BYOND installed. You can get it from [here](http://www.byond.com/). -This is a sourcecode-only release, so the next step is to compile the server files. Open baystation12.dme by double-clicking it, open the Build menu, and click compile. This'll take a little while, and if everything's done right you'll get a message like this: +This is a sourcecode-only release, so the next step is to compile the server files. Open paradise.dme by double-clicking it, open the Build menu, and click compile. This'll take a little while, and if everything's done right you'll get a message like this: - saving baystation12.dmb (DEBUG mode) + saving paradise.dmb (DEBUG mode) - baystation12.dmb - 0 errors, 0 warnings + paradise.dmb - 0 errors, 0 warnings If you see any errors or warnings, something has gone wrong - possibly a corrupt download or the files extracted wrong, or a code issue on the main repo. Ask on IRC. Once that's done, open up the config folder. You'll want to edit config.txt to set the probabilities for different gamemodes in Secret and to set your server location so that all your players don't get disconnected at the end of each round. It's recommended you don't turn on the gamemodes with probability 0, as they have various issues and aren't currently being tested, so they may have unknown and bizarre bugs. -You'll also want to edit admins.txt to remove the default admins and add your own. "Game Master" is the highest level of access, and the other recommended admin levels for now are "Game Admin" and "Moderator". The format is: +You'll also want to edit admins.txt to remove the default admins and add your own. "Host" is the highest level of access, and the other recommended admin levels for now are "Game Admin" and "Moderator". The format is: byondkey - Rank where the BYOND key must be in lowercase and the admin rank must be properly capitalised. There are a bunch more admin ranks, but these two should be enough for most servers, assuming you have trustworthy admins. -Finally, to start the server, run Dream Daemon and enter the path to your compiled baystation12.dmb file. Make sure to set the port to the one you specified in the config.txt, and set the Security box to 'Trusted'. Then press GO and the server should start up and be ready to join. +Finally, to start the server, run Dream Daemon and enter the path to your compiled paradise.dmb file. Make sure to set the port to the one you specified in the config.txt, and set the Security box to 'Trusted'. Then press GO and the server should start up and be ready to join. --- @@ -73,3 +73,9 @@ The SQL backend for the library and stats tracking requires a MySQL server. You ### IRC Bot Setup Included in the repo is an IRC bot capable of relaying adminhelps to a specified IRC channel/server (thanks to Skibiliano). Instructions for bot setup are included in the /bot/ folder along with the bot/relay script itself. + +### LICENSE + +Paradise is licensed under the GNU Affero General Public License version 3 as of 5th January 2015 any new contributions are licensed under the AGPL as well, if you wish to submit code under the GPL v3 then commits and files must be marked as so in comments. If you wish to use our code in a closed source manner you may use anything before commit 445615b8439bf606ff204a42c8e7b6b69d983255 which is licensed under GPL v3. The major change here is that if you host a server using any code licensed under AGPL you are required to provide full source code for your servers users as well including addons and modifications you have made. + +See [this](https://www.gnu.org/licenses/why-affero-gpl.html) for more information. \ No newline at end of file diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql index 8bee94b9436..a38d292bcd4 100644 --- a/SQL/paradise_schema.sql +++ b/SQL/paradise_schema.sql @@ -76,6 +76,7 @@ CREATE TABLE `characters` ( `player_alt_titles` mediumtext NOT NULL, `organ_data` mediumtext NOT NULL, `nanotrasen_relation` varchar(45) NOT NULL, + `speciesprefs` int(1) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; diff --git a/code/WorkInProgress/Cael_Aislinn/Jungle/jungle_temple.dm b/code/WorkInProgress/Cael_Aislinn/Jungle/jungle_temple.dm index dcc7985c878..d4214f76fee 100644 --- a/code/WorkInProgress/Cael_Aislinn/Jungle/jungle_temple.dm +++ b/code/WorkInProgress/Cael_Aislinn/Jungle/jungle_temple.dm @@ -140,7 +140,7 @@ new /obj/item/clothing/under/psyche(C) else new /obj/item/clothing/under/syndicate/combat(C) - new /obj/item/clothing/shoes/swat(C) + new /obj/item/clothing/shoes/combat(C) new /obj/item/clothing/gloves/swat(C) new /obj/item/clothing/mask/balaclava(C) if("glasses") diff --git a/code/WorkInProgress/Mini/atmos_control.dm b/code/WorkInProgress/Mini/atmos_control.dm index c8a18d2dd6c..e0bb07369b6 100644 --- a/code/WorkInProgress/Mini/atmos_control.dm +++ b/code/WorkInProgress/Mini/atmos_control.dm @@ -68,6 +68,8 @@ continue if(alarm.hidden) continue + if(alarm.z != z) + continue var/turf/pos = get_turf(alarm) var/list/alarm_data=list() alarm_data["ID"]="\ref[alarm]" diff --git a/code/WorkInProgress/ZomgPonies/mobs/pony.dm b/code/WorkInProgress/ZomgPonies/mobs/pony.dm index c1ca84543d5..7680e8ee42a 100644 --- a/code/WorkInProgress/ZomgPonies/mobs/pony.dm +++ b/code/WorkInProgress/ZomgPonies/mobs/pony.dm @@ -43,7 +43,7 @@ else if(O.force) var/damage = O.force - if (O.damtype == HALLOSS) + if (O.damtype == STAMINA) damage = 0 health -= damage for(var/mob/M in viewers(src, null)) diff --git a/code/WorkInProgress/ZomgPonies/powerarmor/powerarmorcomponents.dm b/code/WorkInProgress/ZomgPonies/powerarmor/powerarmorcomponents.dm index 4ba3c9ddb65..42cc7b4c444 100644 --- a/code/WorkInProgress/ZomgPonies/powerarmor/powerarmorcomponents.dm +++ b/code/WorkInProgress/ZomgPonies/powerarmor/powerarmorcomponents.dm @@ -74,18 +74,18 @@ if(!crit_fail) if(prob(src.reliability)) return 1 //No failure if(prob(src.reliability)) - for (var/mob/M in range(0,src.parent)) //Only a minor failure, enjoy your radiation. + for (var/mob/living/M in range(0,src.parent)) //Only a minor failure, enjoy your radiation. if(src.parent in M.contents) M << "Your armor feels pleasantly warm for a moment." else M << "You feel a warm sensation." - M.radiation += rand(1,40) + M.apply_effect(-rand(1,40),IRRADIATE,0) else - for (var/mob/M in range(rand(1,4),src.parent)) //Big failure, TIME FOR RADIATION BITCHES + for (var/mob/living/M in range(rand(1,4),src.parent)) //Big failure, TIME FOR RADIATION BITCHES if (src.parent in M.contents) M << "Your armor's reactor overloads!" M << "You feel a wave of heat wash over you." - M.radiation += 100 + M.apply_effect(100,IRRADIATE,0) crit_fail = 1 //broken~ parent.powerdown(1) spawn(50) diff --git a/code/WorkInProgress/computer3/computers/camera.dm b/code/WorkInProgress/computer3/computers/camera.dm index 0a953e40a62..e0d485e1da1 100644 --- a/code/WorkInProgress/computer3/computers/camera.dm +++ b/code/WorkInProgress/computer3/computers/camera.dm @@ -32,7 +32,7 @@ /obj/machinery/computer3/security/mining name = "Outpost Cameras" desc = "Used to access the various cameras on the outpost." - spawn_files = list(/datum/file/camnet_key/mining) + spawn_files = list(/datum/file/camnet_key/miningoutpost) /* Camera monitoring computers, wall-mounted @@ -43,7 +43,7 @@ spawn_files = list(/datum/file/camnet_key) /obj/machinery/computer3/wall_comp/telescreen/entertainment - desc = "Damn, they better have /tg/thechannel on these things." + desc = "Damn, they better have Paradise Channel on these things." spawn_files = list(/datum/file/camnet_key/entertainment) @@ -76,53 +76,96 @@ return computer.Crash(MISSING_PROGRAM) -/datum/file/camnet_key/mining - name = "Mining Camera Network Key" - title = "mining station" - desc = "Connects to mining security cameras." - networks = list("MINE") +/datum/file/camnet_key/telecomms + name = "Telecomms Network Key" + title = "telecommunications satellite" + desc = "Connects to telecommunications satellite security cameras." + networks = list("Telecomms") + +/datum/file/camnet_key/researchoutpost + name = "Research Outpost Network Key" + title = "research outpost" + desc = "Connects to research outpost security cameras." + networks = list("Research Outpost") + +/datum/file/camnet_key/miningoutpost + name = "Mining Outpost Network Key" + title = "mining outpost" + desc = "Connects to mining outpost security cameras." + networks = list("Mining Outpost") screen = "miningcameras" /datum/file/camnet_key/research - name = "Research Camera Network Key" + name = "Research Network Key" title = "research" - networks = list("RD") - -/datum/file/camnet_key/bombrange - name = "R&D Bomb Range Camera Network Key" - title = "bomb range" - desc = "Monitors the bomb range." - networks = list("Toxins") - -/datum/file/camnet_key/xeno - name = "R&D Misc. Research Camera Network Key" - title = "special research" - networks = list("Misc") - -/datum/file/camnet_key/singulo - name = "Singularity Camera Network Key" - title = "singularity" - networks = list("Singularity") - -/datum/file/camnet_key/entertainment - name = "Entertainment Channel Encryption Key" - title = "entertainment" - desc = "Damn, I hope they have /tg/thechannel on here." - networks = list("thunder") - screen = "entertainment" - -/datum/file/camnet_key/creed - name = "Special Ops Camera Encryption Key" - title = "special ops" - desc = "Connects to special ops secure camera feeds." - networks = list("CREED") - + desc = "Connects to research security cameras." + networks = list("Research") + /datum/file/camnet_key/prison - name = "Prison Camera Network Key" + name = "Prison Network Key" title = "prison" - desc = "Monitors the prison." + desc = "Connects to prison security cameras." networks = list("Prison") - + +/datum/file/camnet_key/interrogation + name = "Interrogation Network Key" + title = "interrogation" + desc = "Connects to interrogation security cameras." + networks = list("Interrogation") + +/datum/file/camnet_key/supermatter + name = "Supermatter Network Key" + title = "supermatter" + desc = "Connects to supermatter security cameras." + networks = list("Supermatter") + +/datum/file/camnet_key/singularity + name = "Singularity Network Key" + title = "singularity" + desc = "Connects to singularity security cameras." + networks = list("Singularity") + +/datum/file/camnet_key/anomalyisolation + name = "Anomaly Isolation Network Key" + title = "anomalyisolation" + desc = "Connects to interrogation security cameras." + networks = list("Anomaly Isolation") + +/datum/file/camnet_key/toxins + name = "Toxins Network Key" + title = "toxins" + desc = "Connects to toxins security cameras." + networks = list("Toxins") + +/datum/file/camnet_key/telepad + name = "Telepad Network Key" + title = "telepad" + desc = "Connects to telepad security cameras." + networks = list("Telepad") + +/datum/file/camnet_key/ert + name = "Emergency Response Team Network Key" + title = "emergency response team" + desc = "Connects to emergency response team security cameras." + networks = list("ERT") + +/datum/file/camnet_key/centcom + name = "Central Command Network Key" + title = "central command" + desc = "Connects to central command security cameras." + networks = list("CentCom") + +/datum/file/camnet_key/thunderdome + name = "Thunderdome Network Key" + title = "thunderdome" + desc = "Connects to thunderdome security cameras." + networks = list("Thunderdome") + +/datum/file/camnet_key/entertainment + name = "Entertainment Network Key" + title = "entertainment" + desc = "Connects to entertainment security cameras." + networks = list("news") /* @@ -147,7 +190,7 @@ if(temp.len) L.Add(C) - //camera_sort(L) + camera_sort(L) return L verify_machine(var/obj/machinery/camera/C,var/datum/file/camnet_key/key = null) diff --git a/code/WorkInProgress/computer3/computers/card.dm b/code/WorkInProgress/computer3/computers/card.dm index 90e91a912e1..7c928d2ebec 100644 --- a/code/WorkInProgress/computer3/computers/card.dm +++ b/code/WorkInProgress/computer3/computers/card.dm @@ -4,7 +4,7 @@ /obj/machinery/computer3/card/hop default_prog = /datum/file/program/card_comp spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/cardslot/dual) - spawn_files = list(/datum/file/program/arcade, /datum/file/program/security, /datum/file/camnet_key/mining, /datum/file/camnet_key/entertainment,/datum/file/camnet_key/prison) + spawn_files = list(/datum/file/program/arcade, /datum/file/program/security, /datum/file/camnet_key/miningoutpost, /datum/file/camnet_key/entertainment,/datum/file/camnet_key/prison) /obj/machinery/computer3/card/centcom diff --git a/code/WorkInProgress/computer3/computers/communications.dm b/code/WorkInProgress/computer3/computers/communications.dm index 68a1020a750..58c7f904f06 100644 --- a/code/WorkInProgress/computer3/computers/communications.dm +++ b/code/WorkInProgress/computer3/computers/communications.dm @@ -6,7 +6,7 @@ default_prog = /datum/file/program/communications spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/radio/subspace,/obj/item/part/computer/cardslot/dual) spawn_files = list(/datum/file/program/card_comp, /datum/file/program/security, /datum/file/program/crew, /datum/file/program/arcade, - /datum/file/camnet_key, /datum/file/camnet_key/entertainment, /datum/file/camnet_key/singulo) + /datum/file/camnet_key, /datum/file/camnet_key/entertainment, /datum/file/camnet_key/singularity) /datum/file/program/communications @@ -130,6 +130,9 @@ if("cancelshuttle" in href_list) state = STATE_DEFAULT if(authenticated) + cancel_call_proc(usr) + if(emergency_shuttle.online()) + post_status("shuttle") state = STATE_CANCELSHUTTLE if("messagelist" in href_list) currmsg = 0 @@ -286,11 +289,11 @@ dat += "
\[ Restore Backup Routing Data \]" dat += "
\[ Change alert level \]" - if(emergency_shuttle.location()) + /*if(emergency_shuttle.location()) if (emergency_shuttle.online()) dat += "
\[ Cancel Shuttle Call \]" else - dat += "
\[ Call Emergency Shuttle \]" + dat += "
\[ Call Emergency Shuttle \]"*/ dat += "
\[ Set Status Display \]" else diff --git a/code/WorkInProgress/computer3/computers/security.dm b/code/WorkInProgress/computer3/computers/security.dm index 9f398446ad2..f193b071396 100644 --- a/code/WorkInProgress/computer3/computers/security.dm +++ b/code/WorkInProgress/computer3/computers/security.dm @@ -301,7 +301,6 @@ What a mess.*/ //RECORD FUNCTIONS if("Search Records") var/t1 = input("Search String: (Partial Name or ID or Fingerprints or Rank)", "Secure. records", null, null) as text - world << "input [t1]" if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || !interactable())) return Perp = new/list() diff --git a/code/WorkInProgress/computer3/lapvend.dm b/code/WorkInProgress/computer3/lapvend.dm index 5c4f56ad727..2bae9f2e2d6 100644 --- a/code/WorkInProgress/computer3/lapvend.dm +++ b/code/WorkInProgress/computer3/lapvend.dm @@ -296,6 +296,9 @@ if(access_security in C.access) newlap.spawn_files += (/datum/file/program/secure_data) newlap.spawn_files += (/datum/file/camnet_key) + newlap.spawn_files += (/datum/file/camnet_key/researchoutpost) + newlap.spawn_files += (/datum/file/camnet_key/miningoutpost) + newlap.spawn_files += (/datum/file/camnet_key/telecomms) newlap.spawn_files += (/datum/file/program/security) if(access_armory in C.access) newlap.spawn_files += (/datum/file/program/prisoner) @@ -312,13 +315,17 @@ if(access_engine in C.access) newlap.spawn_files += (/datum/file/program/powermon) if(access_research in C.access) + newlap.spawn_files += (/datum/file/camnet_key/researchoutpost) newlap.spawn_files += (/datum/file/camnet_key/research) - newlap.spawn_files += (/datum/file/camnet_key/bombrange) - newlap.spawn_files += (/datum/file/camnet_key/xeno) + newlap.spawn_files += (/datum/file/camnet_key/anomalyisolation) + newlap.spawn_files += (/datum/file/camnet_key/toxins) + newlap.spawn_files += (/datum/file/camnet_key/telepad) if(access_rd in C.access) newlap.spawn_files += (/datum/file/program/borg_control) if(access_cent_specops in C.access) - newlap.spawn_files += (/datum/file/camnet_key/creed) + newlap.spawn_files += (/datum/file/camnet_key/ert) + newlap.spawn_files += (/datum/file/camnet_key/centcom) + newlap.spawn_files += (/datum/file/camnet_key/thunderdome) newlap.spawn_files += (/datum/file/program/arcade) newlap.spawn_files += (/datum/file/camnet_key/entertainment) //Atlantis: Each laptop gets "invisible" program/security - REQUIRED for camnetkeys to work. diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 1f52c4cdfeb..fb8cf64f84a 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -338,6 +338,32 @@ proc/isInSight(var/atom/A, var/atom/B) candidates += G.key i++ return candidates + +/proc/get_blob_candidates() + + var/list/candidates = list() //List of candidate KEYS to assume control of the new blob core ~Carn + var/i = 0 + while(candidates.len <= 0 && i < 5) + for(var/mob/G in respawnable_list) + if( G.client && G.client.prefs.be_special & BE_BLOB) + if(((G.client.inactivity/10)/60) <= ALIEN_SELECT_AFK_BUFFER + i) // the most active players are more likely to become an alien + if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) + candidates += G.key + i++ + return candidates + +/proc/get_vox_candidates() + + var/list/candidates = list() //List of candidate KEYS to assume control of the new blob core ~Carn + var/i = 0 + while(candidates.len <= 0 && i < 5) + for(var/mob/G in respawnable_list) + if( G.client && G.client.prefs.be_special & BE_VOX) + if(((G.client.inactivity/10)/60) <= ALIEN_SELECT_AFK_BUFFER + i) // the most active players are more likely to become an alien + if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) + candidates += G.key + i++ + return candidates /proc/get_slime_candidates() @@ -355,9 +381,10 @@ proc/isInSight(var/atom/A, var/atom/B) proc/get_candidates(be_special_flag=0) . = list() for(var/mob/G in respawnable_list) - if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) - if(!G.client.is_afk() && (G.client.prefs.be_special & be_special_flag)) - . += G.client + if(G) + if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) + if(!G.client.is_afk() && (G.client.prefs.be_special & be_special_flag)) + . += G.client /proc/ScreenText(obj/O, maptext="", screen_loc="CENTER-7,CENTER-7", maptext_height=480, maptext_width=480) if(!isobj(O)) O = new /obj/screen/text() diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 4e6422e2779..cea62844c77 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -22,6 +22,7 @@ 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/flag_list = list() //list of flags during Nations gamemode +var/global/list/airlocks = list() //list of all airlocks //Languages/species/whitelist. var/global/list/all_species[0] @@ -45,7 +46,7 @@ var/global/list/skin_styles_female_list = list() //unused var/global/list/underwear_m = list("White", "Grey", "Green", "Blue", "Black", "Mankini", "None") //Curse whoever made male/female underwear diffrent colours var/global/list/underwear_f = list("Red", "White", "Yellow", "Blue", "Black", "Thong", "None") //undershirt -var/global/list/undershirt_t = list("Black Tank top", "White Tank top", "Black shirt", "White shirt", "None") +var/global/list/undershirt_t = list("White Shirt", "White Tank top", "Black shirt", "Black Tank top", "Grey Shirt", "Grey tank top", "Lover Shirt", "Blue Ian Shirt", "UK Shirt","I Love NT Shirt", "Peace Shirt", "Band Shirt", "PogoMan Shirt", "Matroska Shirt", "White Short-sleeved shirt", "Purple Short-sleeved shirt", "Blue Short-sleeved shirt", "Green Short-sleeved shirt", "Black Short-Sleeved shirt", "Blue T-Shirt", "Red T-Shirt", "Yellow T-Shirt", "Green T-Shirt", "Blue Polo Shirt", "Red Polo Shirt", "White Polo Shirt", "Gray-Yellow Polo Shirt", "Green Sports Shirt", "Red Sports Shirt", "Blue Sports Shirt", "SS13 Shirt", "Fire Tank Top", "Question Shirt", "Skull Shirt", "Commie Shirt", "Nanotrasen Shirt", "Striped Shirt", "Blue Shirt", "Red Shirt", "Green Shirt", "Meat Shirt", "Tie-Dye Shirt", "Red Jersey", "Blue Jersey", "None") //Backpacks var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt") diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 15d93b5563f..98fc00c97b1 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -16,7 +16,7 @@ // Run all strings to be used in an SQL query through this proc first to properly escape out injection attempts. /proc/sanitizeSQL(var/t as text) var/sqltext = dbcon.Quote(t); - return copytext(sqltext, 2, lentext(sqltext)-1);//Quote() adds quotes around input, we already do that + return copytext(sqltext, 2, lentext(sqltext));//Quote() adds quotes around input, we already do that /* * Text sanitization diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 76598fc6ec9..bddc9ec90f5 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -82,47 +82,51 @@ hex = text("0[]", hex) return hex - // Concatenates a list of strings into a single string. A seperator may optionally be provided. /proc/list2text(list/ls, sep) - if(ls.len <= 1) return ls.len ? ls[1] : "" - . = "" - var/l = ls.len - var/i = 0 + if(ls.len <= 1) // Early-out code for empty or singleton lists. + return ls.len ? ls[1] : "" - if(sep) - #define S1 ls[++i] - #define S4 S1, sep, S1, sep, S1, sep, S1 - #define S16 S4, sep, S4, sep, S4, sep, S4 - #define S64 S16, sep, S16, sep, S16, sep, S16 + var/l = ls.len // Made local for sanic speed. + var/i = 0 // Incremented every time a list index is accessed. - while(l-i >= 128) - . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ - [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ - [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ - [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ - [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ - [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ - [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ - [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, sep, S64) - if(l-i >= 64) - . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + if(sep != null) + // Macros expand to long argument lists like so: sep, ls[++i], sep, ls[++i], sep, ls[++i], etc... + #define S1 sep, ls[++i] + #define S4 S1, S1, S1, S1 + #define S16 S4, S4, S4, S4 + #define S64 S16, S16, S16, S16 + + . = "[ls[++i]]" // Make sure the initial element is converted to text. + + // Having the small concatenations come before the large ones boosted speed by an average of at least 5%. + if(l-1 & 0x01) // 'i' will always be 1 here. + . = text("[][][]", ., S1) // Append 1 element if the remaining elements are not a multiple of 2. + if(l-i & 0x02) + . = text("[][][][][]", ., S1, S1) // Append 2 elements if the remaining elements are not a multiple of 4. + if(l-i & 0x04) + . = text("[][][][][][][][][]", ., S4) // And so on.... + if(l-i & 0x08) + . = text("[][][][][][][][][][][][][][][][][]", ., S4, S4) + if(l-i & 0x10) + . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16) + if(l-i & 0x20) + . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16, S16) + if(l-i & 0x40) + . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64) - if(l-i >= 32) - . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ - [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16, sep, S16) - if(l-i >= 16) - . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16) - if(l-i >= 8) - . = text("[][][][][][][][][][][][][][][][]", ., S4, sep, S4) - if(l-i >= 4) - . = text("[][][][][][][][]", ., S4) - if(l-i >= 2) - . = text("[][][][]", ., S1, sep, S1) - if(l > i) - . = text("[][][]", ., sep, S1) + while(l > i) // Chomp through the rest of the list, 128 elements at a time. + . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64) #undef S64 #undef S16 @@ -130,38 +134,40 @@ #undef S1 else + // Macros expand to long argument lists like so: ls[++i], ls[++i], ls[++i], etc... #define S1 ls[++i] #define S4 S1, S1, S1, S1 #define S16 S4, S4, S4, S4 #define S64 S16, S16, S16, S16 - while(l-i >= 128) + . = "[ls[++i]]" // Make sure the initial element is converted to text. + + if(l-1 & 0x01) // 'i' will always be 1 here. + . += S1 // Append 1 element if the remaining elements are not a multiple of 2. + if(l-i & 0x02) + . = text("[][][]", ., S1, S1) // Append 2 elements if the remaining elements are not a multiple of 4. + if(l-i & 0x04) + . = text("[][][][][]", ., S4) // And so on... + if(l-i & 0x08) + . = text("[][][][][][][][][]", ., S4, S4) + if(l-i & 0x10) + . = text("[][][][][][][][][][][][][][][][][]", ., S16) + if(l-i & 0x20) + . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16, S16) + if(l-i & 0x40) + . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ + [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64) + while(l > i) // Chomp through the rest of the list, 128 elements at a time. . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64) - if(l-i >= 64) - . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\ - [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64) - if(l-i >= 32) - . = text("[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S16, S16) - if(l-i >= 16) - . = text("[][][][][][][][][][][][][][][][][]", ., S16) - if(l-i >= 8) - . = text("[][][][][][][][][]", ., S4, S4) - if(l-i >= 4) - . = text("[][][][][]", ., S4) - if(l-i >= 2) - . = text("[][][]", ., S1, S1) - if(l > i) - . += S1 #undef S64 #undef S16 #undef S4 #undef S1 - //slower then list2text, but correctly processes associative lists. proc/tg_list2text(list/list, glue=",", assocglue=";") if(!istype(list) || !list.len) @@ -352,4 +358,4 @@ proc/tg_text2list(text, glue=",", assocglue=";") for(var/pos = end - 3, pos > 1, pos -= 3) finalNum = copytext(finalNum, 1, pos) + sep + copytext(finalNum, pos) - return finalNum + return finalNum diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 3122f089bd6..43d19a66a36 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -42,6 +42,9 @@ if(modifiers["shift"] && modifiers["ctrl"]) CtrlShiftClickOn(A) return + if(modifiers["shift"] && modifiers["alt"]) + AltShiftClickOn(A) + return if(modifiers["middle"]) MiddleClickOn(A) return @@ -99,6 +102,8 @@ /mob/living/silicon/ai/CtrlShiftClickOn(var/atom/A) A.AICtrlShiftClick(src) +/mob/living/silicon/ai/AltShiftClickOn(var/atom/A) + A.AIAltShiftClick(src) /mob/living/silicon/ai/ShiftClickOn(var/atom/A) A.AIShiftClick(src) /mob/living/silicon/ai/CtrlClickOn(var/atom/A) @@ -118,6 +123,18 @@ examine() return +/atom/proc/AIAltShiftClick() + return + +/obj/machinery/door/airlock/AIAltShiftClick() // Sets/Unsets Emergency Access Override + if(emagged) + return + if(!emergency) + Topic("aiEnable=11", list("aiEnable"="11"), 1) // 1 meaning no window (consistency!) + else + Topic("aiDisable=11", list("aiDisable"="11"), 1) + return + /atom/proc/AIShiftClick() return @@ -128,7 +145,10 @@ Topic("aiDisable=7", list("aiDisable"="7"), 1) return -/atom/proc/AICtrlClick() +/atom/proc/AICtrlClick(var/mob/living/silicon/ai/user) + if(user.holo) + var/obj/machinery/hologram/holopad/H = user.holo + H.face_atom(src) return /obj/machinery/door/airlock/AICtrlClick() // Bolts doors diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 533a6d26c84..bb288fc7d48 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -46,6 +46,9 @@ if(modifiers["shift"] && modifiers["ctrl"]) CtrlShiftClickOn(A) return + if(modifiers["shift"] && modifiers["alt"]) + AltShiftClickOn(A) + return if(modifiers["middle"]) MiddleClickOn(A) return @@ -262,7 +265,7 @@ return T.Adjacent(src) /* - Control+Shift click + Control+Shift/Alt+Shift click Unused except for AI */ /mob/proc/CtrlShiftClickOn(var/atom/A) @@ -271,6 +274,14 @@ /atom/proc/CtrlShiftClick(var/mob/user) return + +/mob/proc/AltShiftClickOn(var/atom/A) + A.AltShiftClick(src) + return + +/atom/proc/AltShiftClick(var/mob/user) + return + /* Misc helpers diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm index fc32220b6d4..4e20ef9ec32 100644 --- a/code/_onclick/cyborg.dm +++ b/code/_onclick/cyborg.dm @@ -19,6 +19,9 @@ if(modifiers["shift"] && modifiers["ctrl"]) CtrlShiftClickOn(A) return + if(modifiers["shift"] && modifiers["alt"]) + AltShiftClickOn(A) + return if(modifiers["middle"]) MiddleClickOn(A) return @@ -117,6 +120,8 @@ // for non-doors/apcs /mob/living/silicon/robot/CtrlShiftClickOn(var/atom/A) A.BorgCtrlShiftClick(src) +/mob/living/silicon/robot/AltShiftClickOn(var/atom/A) + A.BorgAltShiftClick(src) /mob/living/silicon/robot/ShiftClickOn(var/atom/A) A.BorgShiftClick(src) /mob/living/silicon/robot/CtrlClickOn(var/atom/A) @@ -129,9 +134,15 @@ examine() user.face_atom(src) return + +/atom/proc/BorgAltShiftClick() + return + +/obj/machinery/door/airlock/BorgAltShiftClick() // Enables emergency override on doors! Forwards to AI code. + AIAltShiftClick() /atom/proc/BorgShiftClick() - return + return /obj/machinery/door/airlock/BorgShiftClick() // Opens and closes doors! Forwards to AI code. AIShiftClick() diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 464593bbd47..98b99d0a1d3 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -71,6 +71,9 @@ #define ui_monkey_mask "5:14,1:5" //monkey #define ui_monkey_back "6:14,1:5" //monkey +#define ui_alien_storage_l "CENTER-2:14,SOUTH:5"//alien +#define ui_alien_storage_r "CENTER+1:18,SOUTH:5"//alien + //Lower right, persistant menu //#define ui_dropbutton "11:22,1:5" #define ui_drop_throw "16:28,2:7" @@ -99,12 +102,14 @@ #define ui_alien_toxin "16:28,13:25" #define ui_alien_fire "16:28,12:25" #define ui_alien_oxygen "16:28,11:25" +#define ui_alien_nightvision "16:28,10:25" //Middle right (status indicators) #define ui_nutrition "16:28,5:11" #define ui_temp "16:28,6:13" -#define ui_health "16:28,7:15" -#define ui_internal "16:28,8:17" +#define ui_healthdoll "16:28,7:15" +#define ui_health "16:28,8:17" +#define ui_internal "16:28,9:19" //borgs #define ui_borg_health "16:28,6:13" //borgs have the health display where humans have the pressure damage indicator. #define ui_alien_health "16:28,6:13" //aliens have the health display where humans have the pressure damage indicator. diff --git a/code/_onclick/hud/alien.dm b/code/_onclick/hud/alien.dm index 8017f7acbe0..f53267a862e 100644 --- a/code/_onclick/hud/alien.dm +++ b/code/_onclick/hud/alien.dm @@ -2,71 +2,21 @@ return /datum/hud/proc/alien_hud() - - src.adding = list( ) - src.other = list( ) + src.adding = list() + src.other = list() var/obj/screen/using var/obj/screen/inventory/inv_box - + using = new /obj/screen() using.name = "act_intent" using.dir = SOUTHWEST using.icon = 'icons/mob/screen1_alien.dmi' - using.icon_state = (mymob.a_intent == "harm" ? "harm" : mymob.a_intent) + using.icon_state = (mymob.a_intent == "hurt" ? "harm" : mymob.a_intent) using.screen_loc = ui_acti using.layer = 20 src.adding += using - action_intent = using - -//intent small hud objects - var/icon/ico - - ico = new('icons/mob/screen1_alien.dmi', "black") - ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) - ico.DrawBox(rgb(255,255,255,1),1,ico.Height()/2,ico.Width()/2,ico.Height()) - using = new /obj/screen( src ) - using.name = "help" - using.icon = ico - using.screen_loc = ui_acti - using.layer = 21 - src.adding += using - help_intent = using - - ico = new('icons/mob/screen1_alien.dmi', "black") - ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) - ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,ico.Height()/2,ico.Width(),ico.Height()) - using = new /obj/screen( src ) - using.name = "disarm" - using.icon = ico - using.screen_loc = ui_acti - using.layer = 21 - src.adding += using - disarm_intent = using - - ico = new('icons/mob/screen1_alien.dmi', "black") - ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) - ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,1,ico.Width(),ico.Height()/2) - using = new /obj/screen( src ) - using.name = "grab" - using.icon = ico - using.screen_loc = ui_acti - using.layer = 21 - src.adding += using - grab_intent = using - - ico = new('icons/mob/screen1_alien.dmi', "black") - ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1) - ico.DrawBox(rgb(255,255,255,1),1,1,ico.Width()/2,ico.Height()/2) - using = new /obj/screen( src ) - using.name = "harm" - using.icon = ico - using.screen_loc = ui_acti - using.layer = 21 - src.adding += using - hurt_intent = using - -//end intent small hud objects + action_intent = using using = new /obj/screen() using.name = "mov_intent" @@ -76,35 +26,24 @@ using.screen_loc = ui_movi using.layer = 20 src.adding += using - move_intent = using - - using = new /obj/screen() - using.name = "drop" - using.icon = 'icons/mob/screen1_alien.dmi' - using.icon_state = "act_drop" - using.screen_loc = ui_drop_throw - using.layer = 19 - src.adding += using - + move_intent = using + + if(istype(mymob, /mob/living/carbon/alien/humanoid/hunter)) + mymob.leap_icon = new /obj/screen() + mymob.leap_icon.icon = 'icons/mob/screen1_alien.dmi' + mymob.leap_icon.name = "toggle leap" + mymob.leap_icon.icon_state = "leap_off" + mymob.leap_icon.screen_loc = ui_alien_storage_r + src.adding += mymob.leap_icon + //equippable shit - //suit - inv_box = new /obj/screen/inventory() - inv_box.name = "o_clothing" - inv_box.dir = SOUTH - inv_box.icon = 'icons/mob/screen1_alien.dmi' - inv_box.icon_state = "equip" - inv_box.screen_loc = ui_alien_oclothing - inv_box.slot_id = slot_wear_suit - inv_box.layer = 19 - src.adding += inv_box - inv_box = new /obj/screen/inventory() inv_box.name = "r_hand" inv_box.dir = WEST inv_box.icon = 'icons/mob/screen1_alien.dmi' inv_box.icon_state = "hand_inactive" if(mymob && !mymob.hand) //This being 0 or null means the right hand is in use - using.icon_state = "hand_active" + inv_box.icon_state = "hand_active" inv_box.screen_loc = ui_rhand inv_box.layer = 19 src.r_hand_hud_object = inv_box @@ -142,46 +81,23 @@ using.layer = 19 src.adding += using - //pocket 1 - inv_box = new /obj/screen/inventory() - inv_box.name = "storage1" - inv_box.icon = 'icons/mob/screen1_alien.dmi' - inv_box.icon_state = "pocket" - inv_box.screen_loc = ui_storage1 - inv_box.slot_id = slot_l_store - inv_box.layer = 19 - src.adding += inv_box - - //pocket 2 - inv_box = new /obj/screen/inventory() - inv_box.name = "storage2" - inv_box.icon = 'icons/mob/screen1_alien.dmi' - inv_box.icon_state = "pocket" - inv_box.screen_loc = ui_storage2 - inv_box.slot_id = slot_r_store - inv_box.layer = 19 - src.adding += inv_box - - //head - inv_box = new /obj/screen/inventory() - inv_box.name = "head" - inv_box.icon = 'icons/mob/screen1_alien.dmi' - inv_box.icon_state = "hair" - inv_box.screen_loc = ui_alien_head - inv_box.slot_id = slot_head - inv_box.layer = 19 - src.adding += inv_box //end of equippable shit -/* using = new /obj/screen() using.name = "resist" using.icon = 'icons/mob/screen1_alien.dmi' using.icon_state = "act_resist" - using.screen_loc = ui_resist + using.screen_loc = ui_pull_resist + using.layer = 19 + src.adding += using + + using = new /obj/screen() + using.name = "drop" + using.icon = 'icons/mob/screen1_alien.dmi' + using.icon_state = "act_drop" + using.screen_loc = ui_drop_throw using.layer = 19 src.adding += using -*/ mymob.throw_icon = new /obj/screen() mymob.throw_icon.icon = 'icons/mob/screen1_alien.dmi' @@ -213,6 +129,12 @@ mymob.healths.name = "health" mymob.healths.screen_loc = ui_alien_health + nightvisionicon = new /obj/screen() + nightvisionicon.icon = 'icons/mob/screen1_alien.dmi' + nightvisionicon.icon_state = "nightvision1" + nightvisionicon.name = "night vision" + nightvisionicon.screen_loc = ui_alien_nightvision + mymob.pullin = new /obj/screen() mymob.pullin.icon = 'icons/mob/screen1_alien.dmi' mymob.pullin.icon_state = "pull0" @@ -246,5 +168,5 @@ mymob.client.screen = null - mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.toxin, mymob.fire, mymob.healths, mymob.pullin, alien_plasma_display, mymob.blind, mymob.flash) //, mymob.hands, mymob.rest, mymob.sleep, mymob.mach ) + mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.toxin, mymob.fire, mymob.healths, nightvisionicon, mymob.pullin, alien_plasma_display, mymob.pullin, mymob.blind, mymob.flash) //, mymob.hands, mymob.rest, mymob.sleep, mymob.mach ) mymob.client.screen += src.adding + src.other \ No newline at end of file diff --git a/code/_onclick/hud/alien_larva.dm b/code/_onclick/hud/alien_larva.dm index 59461e3c6b7..51d3275d3af 100644 --- a/code/_onclick/hud/alien_larva.dm +++ b/code/_onclick/hud/alien_larva.dm @@ -1,5 +1,4 @@ /datum/hud/proc/larva_hud() - src.adding = list() src.other = list() @@ -50,6 +49,12 @@ mymob.healths.icon_state = "health0" mymob.healths.name = "health" mymob.healths.screen_loc = ui_alien_health + + nightvisionicon = new /obj/screen() + nightvisionicon.icon = 'icons/mob/screen1_alien.dmi' + nightvisionicon.icon_state = "nightvision1" + nightvisionicon.name = "night vision" + nightvisionicon.screen_loc = ui_alien_nightvision mymob.pullin = new /obj/screen() mymob.pullin.icon = 'icons/mob/screen1_alien.dmi' @@ -72,10 +77,11 @@ mymob.flash.layer = 17 mymob.zone_sel = new /obj/screen/zone_sel() + mymob.zone_sel.icon = 'icons/mob/screen1_alien.dmi' mymob.zone_sel.overlays.Cut() mymob.zone_sel.overlays += image("icon" = 'icons/mob/zone_sel.dmi', "icon_state" = text("[]", mymob.zone_sel.selecting)) mymob.client.screen = null - mymob.client.screen += list( mymob.zone_sel, mymob.oxygen, mymob.toxin, mymob.fire, mymob.healths, mymob.pullin, mymob.blind, mymob.flash) //, mymob.rest, mymob.sleep, mymob.mach ) + mymob.client.screen += list( mymob.zone_sel, mymob.oxygen, mymob.toxin, mymob.fire, mymob.healths, nightvisionicon, mymob.pullin, mymob.blind, mymob.flash) //, mymob.rest, mymob.sleep, mymob.mach ) mymob.client.screen += src.adding + src.other diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 9f31ba970d9..20e50d9472c 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -98,6 +98,7 @@ var/datum/global_hud/global_hud = new() var/obj/screen/blobhealthdisplay var/obj/screen/vampire_blood_display var/obj/screen/alien_plasma_display + var/obj/screen/nightvisionicon var/obj/screen/r_hand_hud_object var/obj/screen/l_hand_hud_object var/obj/screen/action_intent @@ -228,6 +229,7 @@ datum/hud/New(mob/owner) else src.client.screen -= src.healths src.client.screen -= src.internals + src.client.screen -= src.healthdoll src.client.screen -= src.gun_setting_icon //These ones are not a part of 'adding', 'other' or 'hotkeybuttons' but we want them gone. @@ -243,6 +245,8 @@ datum/hud/New(mob/owner) src.client.screen += src.hud_used.hotkeybuttons if(src.healths) src.client.screen |= src.healths + if(src.healthdoll) + src.client.screen |= src.healthdoll if(src.internals) src.client.screen |= src.internals if(src.gun_setting_icon) diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 3a80570dbb7..ca8b9bc8795 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -410,6 +410,12 @@ mymob.healths.name = "health" mymob.healths.screen_loc = ui_health + mymob.healthdoll = new /obj/screen() + mymob.healthdoll.icon = ui_style + mymob.healthdoll.icon_state = "healthdoll_DEAD" + mymob.healthdoll.name = "health doll" + mymob.healthdoll.screen_loc = ui_healthdoll + mymob.nutrition_icon = new /obj/screen() mymob.nutrition_icon.icon = ui_style mymob.nutrition_icon.icon_state = "nutrition0" @@ -479,7 +485,7 @@ mymob.client.screen = null - mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.pressure, mymob.toxin, mymob.bodytemp, mymob.internals, mymob.fire, mymob.healths, mymob.nutrition_icon, mymob.pullin, mymob.blind, mymob.flash, mymob.damageoverlay, mymob.gun_setting_icon) //, mymob.hands, mymob.rest, mymob.sleep) //, mymob.mach ) + mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.pressure, mymob.toxin, mymob.bodytemp, mymob.internals, mymob.fire, mymob.healths, mymob.healthdoll, mymob.nutrition_icon, mymob.pullin, mymob.blind, mymob.flash, mymob.damageoverlay, mymob.gun_setting_icon) //, mymob.hands, mymob.rest, mymob.sleep) //, mymob.mach ) mymob.client.screen += src.adding + src.hotkeybuttons inventory_shown = 0; @@ -517,13 +523,11 @@ I = U.hastie if(I.icon_action_button) var/obj/screen/item_action/A = new(hud_used) - + //A.icon = 'icons/mob/screen1_action.dmi' //A.icon_state = I.icon_action_button - A.icon = ui_style2icon(client.prefs.UI_style) A.icon_state = "template" - var/image/img = image(I.icon, A, I.icon_state) img.pixel_x = 0 img.pixel_y = 0 @@ -534,9 +538,7 @@ else A.name = "Use [I.name]" A.owner = I - hud_used.item_action_list += A - switch(num) if(1) A.screen_loc = ui_action_slot1 @@ -548,16 +550,6 @@ A.screen_loc = ui_action_slot4 if(5) A.screen_loc = ui_action_slot5 - if(6) - A.screen_loc = ui_action_slot6 - if(7) - A.screen_loc = ui_action_slot7 - if(8) - A.screen_loc = ui_action_slot8 - if(9) - A.screen_loc = ui_action_slot9 - if(10) - A.screen_loc = ui_action_slot10 break //5 slots available, so no more can be added. num++ - src.client.screen += src.hud_used.item_action_list + src.client.screen += src.hud_used.item_action_list \ No newline at end of file diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index b31ef842b4f..efa433476d6 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -558,7 +558,17 @@ if(isAI(usr)) var/mob/living/silicon/ai/AI = usr AI.control_hud() - + + // Alien + if("night vision") + var/mob/living/carbon/alien/humanoid/A = usr + A.nightvisiontoggle() + + if("toggle leap") + if(istype(usr, /mob/living/carbon/alien/humanoid)) + var/mob/living/carbon/alien/humanoid/hunter/AH = usr + AH.toggle_leap() + else return 0 return 1 diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index ae857e59d46..427b286800b 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -99,76 +99,6 @@ /mob/living/carbon/alien/RestrainedClickOn(var/atom/A) return -/mob/living/carbon/alien/humanoid/RangedAttack(var/atom/A) - if(!large && a_intent == "harm") - Neurotox(A) - return - else if(large && a_intent == "harm") - NeuroAOE(A) - return - - -/mob/living/carbon/alien/humanoid/proc/Neurotox(atom/A) - if(world.time < next_attack) - return - - var/turf/T = get_turf(src) - var/turf/U = get_turf(A) // Get the tile infront of the move, based on their direction - - if(!isturf(U) || !isturf(T)) - return - - var/obj/item/projectile/bullet/neurotoxin/NT = new /obj/item/projectile/bullet/neurotoxin(loc) - NT.firer = src -// NT.def_zone = get_organ_target() - NT.original = A - NT.current = T - NT.yo = U.y - T.y - NT.xo = U.x - T.x - spawn( 1) - NT.process() - next_attack = world.time + 100 - -/mob/living/carbon/alien/humanoid/proc/NeuroAOE(atom/A) - if(world.time < next_attack) - return - - var/direction = get_dir(src,A) - var/turf/T = get_turf(A) - var/turf/T1 = get_step(T,turn(direction, 90)) - var/turf/T2 = get_step(T,turn(direction, -90)) - - var/list/the_targets = list(T,T1,T2) - - for(var/a=0, a<5, a++) - spawn(0) - var/obj/effect/effect/water/D = new /obj/effect/effect/water( get_turf(src) ) - D.color = "#00FF21" - var/turf/my_target = pick(the_targets) - for(var/b=0, b<5, b++) - if(!step_towards(D,my_target)) return - if(!D) return -// D.reagents.reaction(get_turf(D)) - for(var/atom/atm in get_turf(D)) - if(!D) return - if(istype(atm, /mob/living/carbon/alien)) - return - if(istype(atm, /mob/living/carbon)) - var/mob/living/carbon/C = atm - if(ishuman(C)) - var/mob/living/carbon/human/H = C - if(istype(H.wear_suit, /obj/item/clothing/suit/space) && istype(H.head, /obj/item/clothing/head/helmet/space)) - return - else - C.Weaken(5) - C.adjustToxLoss(20) - C << "You were drenched with neurotoxin!" -// D.reagents.reaction(atm, TOUCH) // Touch, since we sprayed it. - if(D.loc == my_target) break - sleep(2) - next_attack = world.time + 100 - - // Babby aliens /mob/living/carbon/alien/larva/UnarmedAttack(var/atom/A) A.attack_larva(src) diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 7400a695d27..74e09dc1211 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -96,6 +96,7 @@ //game_options.txt configs + var/health_threshold_softcrit = 0 var/health_threshold_crit = 0 var/health_threshold_dead = -100 diff --git a/code/controllers/shuttle_controller.dm b/code/controllers/shuttle_controller.dm index 68644df37eb..5eeedcb89e3 100644 --- a/code/controllers/shuttle_controller.dm +++ b/code/controllers/shuttle_controller.dm @@ -217,8 +217,8 @@ var/global/datum/shuttle_controller/shuttle_controller ) VS.announcer = "NSV Icarus" - VS.arrival_message = "Attention, Exodus, we just tracked a small target bypassing our defensive perimeter. Can't fire on it without hitting the station - you've got incoming visitors, like it or not." - VS.departure_message = "Your guests are pulling away, Exodus - moving too fast for us to draw a bead on them. Looks like they're heading out of the system at a rapid clip." + VS.arrival_message = "Attention, Cyberiad, we just tracked a small target bypassing our defensive perimeter. Can't fire on it without hitting the station - you've got incoming visitors, like it or not." + VS.departure_message = "Your guests are pulling away, Cyberiad - moving too fast for us to draw a bead on them. Looks like they're heading out of the system at a rapid clip." VS.interim = locate(/area/vox_station/transit) VS.warmup_time = 0 @@ -240,8 +240,8 @@ var/global/datum/shuttle_controller/shuttle_controller ) MS.announcer = "NSV Icarus" - MS.arrival_message = "Attention, Exodus, you have a large signature approaching the station - looks unarmed to surface scans. We're too far out to intercept - brace for visitors." - MS.departure_message = "Your visitors are on their way out of the system, Exodus, burning delta-v like it's nothing. Good riddance." + MS.arrival_message = "Attention, Cyberiad, you have a large signature approaching the station - looks unarmed to surface scans. We're too far out to intercept - brace for visitors." + MS.departure_message = "Your visitors are on their way out of the system, Cyberiad, burning delta-v like it's nothing. Good riddance." MS.interim = locate(/area/syndicate_station/transit) MS.warmup_time = 0 diff --git a/code/datums/crafting/recipes.dm b/code/datums/crafting/recipes.dm index 32d5a4d3b5e..6dda4d79622 100644 --- a/code/datums/crafting/recipes.dm +++ b/code/datums/crafting/recipes.dm @@ -89,7 +89,7 @@ /obj/item/robot_parts/r_leg = 1, /obj/item/stack/sheet/metal = 5, /obj/item/stack/cable_coil = 5, - /obj/item/weapon/gun/energy/taser = 1, + /obj/item/weapon/gun/energy/advtaser = 1, /obj/item/weapon/cell = 1, /obj/item/device/assembly/prox_sensor = 1, /obj/item/robot_parts/r_arm = 1) diff --git a/code/datums/spells/horsemask.dm b/code/datums/spells/horsemask.dm index 2d4796309e4..9766d356232 100644 --- a/code/datums/spells/horsemask.dm +++ b/code/datums/spells/horsemask.dm @@ -22,6 +22,9 @@ return var/mob/living/carbon/target = targets[1] + + if(!target) + return if(!(target.type in compatible_mobs)) user << "It'd be stupid to curse [target] with a horse's head!" diff --git a/code/datums/spells/mind_transfer.dm b/code/datums/spells/mind_transfer.dm index c19cb43be7b..c905bf88a97 100644 --- a/code/datums/spells/mind_transfer.dm +++ b/code/datums/spells/mind_transfer.dm @@ -10,14 +10,12 @@ range = 1 cooldown_min = 200 //100 deciseconds reduction per rank var/list/protected_roles = list("Wizard","Changeling","Cultist") //which roles are immune to the spell - var/list/compatible_mobs = list(/mob/living/carbon/human,/mob/living/carbon/monkey) //which types of mobs are affected by the spell. NOTE: change at your own risk var/base_spell_loss_chance = 20 //base probability of the wizard losing a spell in the process var/spell_loss_chance_modifier = 7 //amount of probability of losing a spell added per spell (mind_transfer included) var/spell_loss_amount = 1 //the maximum amount of spells possible to lose during a single transfer var/msg_wait = 500 //how long in deciseconds it waits before telling that body doesn't feel right or mind swap robbed of a spell var/paralysis_amount_caster = 20 //how much the caster is paralysed for after the spell var/paralysis_amount_victim = 20 //how much the victim is paralysed for after the spell - icon_power_button = "spell_mind" /* @@ -40,12 +38,8 @@ Also, you never added distance checking after target is selected. I've went ahea user << "They are too far away!" return - if(!(target.type in compatible_mobs)) - user << "Their mind isn't compatible with yours." - return - if(target.stat == DEAD) - user << "You didn't study necromancy back at the Space Wizard Federation academy." + user << "You don't particularly want to be dead." return if(!target.key || !target.mind) diff --git a/code/datums/spells/wizard.dm b/code/datums/spells/wizard.dm index 70fa7449189..bcd5bbd56bb 100644 --- a/code/datums/spells/wizard.dm +++ b/code/datums/spells/wizard.dm @@ -27,7 +27,7 @@ icon_power_button = "spell_missile" /obj/effect/proc_holder/spell/wizard/targeted/inflict_handler/magic_missile - amt_weakened = 5 + amt_weakened = 3 amt_dam_fire = 10 /obj/effect/proc_holder/spell/wizard/noclothes @@ -119,7 +119,7 @@ smoke_spread = 1 - smoke_amt = 10 + smoke_amt = 1 inner_tele_radius = 0 outer_tele_radius = 6 @@ -268,7 +268,7 @@ icon_power_button = "spell_fireball" /obj/effect/proc_holder/spell/wizard/turf/fireball/cast(var/turf/T) - explosion(T, -1, 0, 2, 0) + explosion(T, -1, 0, 2, 3, 0) /obj/effect/proc_holder/spell/wizard/targeted/inflict_handler/fireball @@ -277,5 +277,5 @@ /obj/effect/proc_holder/spell/wizard/targeted/explosion/fireball ex_severe = -1 - ex_heavy = 0 - ex_light = 2 + ex_heavy = -1 + ex_light = 2 \ No newline at end of file diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index ab27aeb73df..c20cc25382b 100755 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -239,7 +239,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /obj/item/weapon/bikehorn, /obj/item/clothing/under/mime, /obj/item/clothing/shoes/black, - /obj/item/clothing/gloves/white, + /obj/item/clothing/gloves/color/white, /obj/item/clothing/mask/gas/mime, /obj/item/clothing/head/beret, /obj/item/clothing/suit/suspenders, @@ -341,6 +341,13 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee containername = "cat crate" group = "Organic" +/datum/supply_packs/organic/fox + name = "Fox Crate" + cost = 55 //Foxes are cool. + containertype = /obj/structure/closet/critter/fox + containername = "fox crate" + group = "Organic" + /datum/supply_packs/seeds name = "Seeds Crate" contains = list(/obj/item/seeds/chiliseed, @@ -657,8 +664,8 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /obj/item/weapon/melee/baton/loaded, /obj/item/weapon/gun/energy/laser, /obj/item/weapon/gun/energy/laser, - /obj/item/weapon/gun/energy/taser, - /obj/item/weapon/gun/energy/taser, + /obj/item/weapon/gun/energy/advtaser, + /obj/item/weapon/gun/energy/advtaser, /obj/item/weapon/storage/box/flashbangs, /obj/item/weapon/storage/box/flashbangs) cost = 30 @@ -1067,6 +1074,26 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee access = access_hydroponics group = "Hydroponics" +/datum/supply_packs/misc/lasertag + name = "Laser Tag Crate" + contains = list(/obj/item/weapon/gun/energy/laser/redtag, + /obj/item/weapon/gun/energy/laser/redtag, + /obj/item/weapon/gun/energy/laser/redtag, + /obj/item/weapon/gun/energy/laser/bluetag, + /obj/item/weapon/gun/energy/laser/bluetag, + /obj/item/weapon/gun/energy/laser/bluetag, + /obj/item/clothing/suit/redtag, + /obj/item/clothing/suit/redtag, + /obj/item/clothing/suit/redtag, + /obj/item/clothing/suit/bluetag, + /obj/item/clothing/suit/bluetag, + /obj/item/clothing/suit/bluetag, + /obj/item/clothing/head/helmet/redtaghelm, + /obj/item/clothing/head/helmet/bluetaghelm) + cost = 15 + containertype = /obj/structure/closet/crate + containername = "laser tag crate" + group = "Operations" /datum/supply_packs/vending name = "Bartending Supply Crate" @@ -1120,7 +1147,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee containertype = /obj/structure/closet/crate containername = "autodrobe supply crate" group = "Operations" - + /datum/supply_packs/clothingvendor name = "Clothing Vendor Supply crate" contains = list(/obj/item/weapon/vending_refill/hatdispenser, diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index 7e80ebcc381..2e71bd1ac69 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -108,14 +108,6 @@ var/list/uplink_items = list() cost = 8 job = list("Clown") -//Detective -/datum/uplink_item/jobspecific/evidenceforger - name = "Evidence Forger" - desc = "An evidence scanner that allows you forge evidence by setting the output before scanning the item." - item = /obj/item/device/detective_scanner/forger - cost = 6 - job = list("Detective") - /datum/uplink_item/jobspecific/conversionkit name = "Conversion Kit Bundle" desc = "A bundle that comes with a professional revolver conversion kit and 1 box of .357 ammo. The kit allows you to convert your revolver to fire lethal rounds or vice versa, modification is nearly perfect and will not result in catastrophic failure." @@ -205,28 +197,29 @@ var/list/uplink_items = list() /datum/uplink_item/dangerous category = "Highly Visible and Dangerous Weapons" -/datum/uplink_item/dangerous/revolver - name = "Fully Loaded Revolver" - desc = "A traditional handgun which fires .357 rounds. Has 7 chambers. Can down an unarmoured target with two shots." - item = /obj/item/weapon/gun/projectile/revolver - cost = 13 /datum/uplink_item/dangerous/pistol - name = "Stechkin Pistol" - desc = "A small, easily concealable handgun that uses 10mm magazines and is compatible with suppressors." + name = "Syndicate Pistol" + desc = "A small, easily concealable handgun that uses 10mm auto rounds in 8-round magazines and is compatible with suppressors." item = /obj/item/weapon/gun/projectile/automatic/pistol cost = 9 +/datum/uplink_item/dangerous/revolver + name = "Syndicate Revolver" + desc = "A brutally simple syndicate revolver that fires .357 Magnum cartridges and has 7 chambers." + item = /obj/item/weapon/gun/projectile/revolver + cost = 13 + /datum/uplink_item/dangerous/smg - name = "C-20r Submachine Gun" - desc = "A fully-loaded Scarborough Arms-developed submachine gun that fires 12mm automatic rounds with a 20-round magazine." + name = "Syndicate SMG" + desc = "A fully-loaded Scarborough Arms bullpup submachine gun that fires .45 rounds with a 20-round magazine and is compatible with suppressors." item = /obj/item/weapon/gun/projectile/automatic/c20r cost = 14 gamemodes = list("nuclear emergency") /datum/uplink_item/dangerous/machinegun - name = "L6 Squad Automatic Weapon" - desc = "A traditionally constructed machine gun made by AA-2531. This deadly weapon has a massive 50-round magazine of 7.62×51mm ammunition." + name = "Syndicate LMG" + desc = "A fully-loaded Aussec Armoury belt-fed machine gun. This deadly weapon has a massive 50-round magazine of devastating 7.62x51mm ammunition." item = /obj/item/weapon/gun/projectile/automatic/l6_saw cost = 40 gamemodes = list("nuclear emergency") @@ -304,53 +297,74 @@ var/list/uplink_items = list() /datum/uplink_item/ammo category = "Ammunition" -/datum/uplink_item/ammo/revolver - name = "Ammo-357" - desc = "A box that contains seven additional rounds for the revolver, made using an automatic lathe." - item = /obj/item/ammo_box/a357 - cost = 4 - /datum/uplink_item/ammo/pistol name = "Ammo-10mm" - desc = "An additional 8-round 10mm magazine for use in the Stetchkin pistol." + desc = "An additional 8-round 10mm magazine for use in the syndicate pistol. These subsonic rounds are dirt cheap but are half as effective as .357 rounds." item = /obj/item/ammo_box/magazine/m10mm cost = 1 +/datum/uplink_item/ammo/revolver + name = "Speed Loader - .357" + desc = "A speed loader that contains seven additional .357 Magnum rounds for the syndicate revolver. For when you really need a lot of things dead." + item = /obj/item/ammo_box/a357 + cost = 4 + /datum/uplink_item/ammo/smg - name = "Ammo-12mm" - desc = "A 20-round 12mm magazine for use in the C-20r submachine gun." - item = /obj/item/ammo_box/magazine/m12mm + name = "Magazine - .45" + desc = "An additional 20-round .45 magazine for use in the C-20r submachine gun. These bullets pack a lot of punch that can knock most targets down, but do limited overall damage." + item = /obj/item/ammo_box/magazine/smgm45 cost = 2 gamemodes = list("nuclear emergency") -/datum/uplink_item/ammo/machinegun - name = "Ammo-7.62×51mm" - desc = "A 50-round magazine of 7.62×51mm ammunition for use in the L6 SAW machinegun. By the time you need to use this, you'll already be on a pile of corpses." - item = /obj/item/ammo_box/magazine/m762 - cost = 12 +/datum/uplink_item/dangerous/car + name = "C-90gl Compact Assault Rifle" + desc = "A fully-loaded Zashchita Industriya toploading bullpup assault rifle that uses 30-round 5.45x39mm magazines with a togglable underslung 40mm grenade launcher." + item = /obj/item/weapon/gun/projectile/automatic/c90gl + cost = 18 gamemodes = list("nuclear emergency") /datum/uplink_item/ammo/bullstun - name = "Ammo-12g Stun Slug" + name = "Drum Magazine - 12g Stun Slug" desc = "An additional 8-round stun slug magazine for use in the Bulldog shotgun. Saying that they're non-lethal would be lying." item = /obj/item/ammo_box/magazine/m12g cost = 2 gamemodes = list("nuclear emergency") /datum/uplink_item/ammo/bullbuck - name = "Ammo-12g Buckshot" + name = "Drum Magazine - 12g Buckshot" desc = "An alternative 8-round buckshot magazine for use in the Bulldog shotgun. Front towards enemy." item = /obj/item/ammo_box/magazine/m12g/buckshot cost = 2 gamemodes = list("nuclear emergency") /datum/uplink_item/ammo/bulldragon - name = "Ammo-12g Dragon's Breath" + name = "Drum Magazine - 12g Dragon's Breath" desc = "An alternative 8-round dragon's breath magazine for use in the Bulldog shotgun. I'm a fire starter, twisted fire starter!" item = /obj/item/ammo_box/magazine/m12g/dragon cost = 3 gamemodes = list("nuclear emergency") +/datum/uplink_item/ammo/car + name = "Box Magazine - 5.45x39mm" + desc = "An additional 30-round 5.45x39mm magazine for use in the C-90gl assault rifle. These bullets don't have the punch to knock most targets down, but dish out higher overall damage." + item = /obj/item/ammo_box/magazine/m545 + cost = 2 + gamemodes = list("nuclear emergency") + +/datum/uplink_item/ammo/a40mm + name = "Ammo Box - 40mm grenades" + desc = "A box of 4 additional 40mm HE grenades for use the C-90gl's underbarrel grenade launcher. Your teammates will thank you to not shoot these down small hallways." + item = /obj/item/ammo_box/a40mm + cost = 4 + gamemodes = list("nuclear emergency") + +/datum/uplink_item/ammo/machinegun + name = "Box Magazine - 7.62×51mm" + desc = "A 50-round magazine of 7.62x51mm ammunition for use in the L6 SAW machinegun. By the time you need to use this, you'll already be on a pile of corpses." + item = /obj/item/ammo_box/magazine/m762 + cost = 12 + gamemodes = list("nuclear emergency") + // STEALTHY WEAPONS @@ -379,9 +393,9 @@ var/list/uplink_items = list() // Commented out until a fix can be found, currently doesn't work with the PDA NanoUI and people keep wasting Telecrystals on it. -- Dave /datum/uplink_item/stealthy_weapons/silencer - name = "Stetchkin Silencer" - desc = "Fitted for use on the Stetchkin pistol, this silencer will make its shots quieter when equipped onto it." - item = /obj/item/weapon/silencer + name = "Universal Suppressor" + desc = "Fitted for use on any small caliber weapon with a threaded barrel, this suppressor will silence the shots of the weapon for increased stealth and superior ambushing capability." + item = /obj/item/weapon/suppressor cost = 3 // STEALTHY TOOLS @@ -514,7 +528,7 @@ var/list/uplink_items = list() /datum/uplink_item/device_tools/cipherkey name = "Syndicate Encryption Key" desc = "A key, that when inserted into a radio headset, allows you to listen to all station department channels as well as talk on an encrypted Syndicate channel." - item = /obj/item/device/encryptionkey/syndicate + item = /obj/item/device/encryptionkey/syndicate/hacked cost = 5 /datum/uplink_item/device_tools/hacked_module diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index f53c822a027..3b6d009a5ff 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -34,12 +34,13 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048 /datum/wires/airlock/GetInteractWindow() var/obj/machinery/door/airlock/A = holder . += ..() - . += text("
\n[]
\n[]
\n[]
\n[]
\n[]
\n[]", (A.locked ? "The door bolts have fallen!" : "The door bolts look up."), + . += text("
\n[]
\n[]
\n[]
\n[]
\n[]
\n[]
\n[]", (A.locked ? "The door bolts have fallen!" : "The door bolts look up."), (A.lights ? "The door bolt lights are on." : "The door bolt lights are off!"), ((A.arePowerSystemsOn() && !(A.stat & NOPOWER)) ? "The test light is on." : "The test light is off!"), (A.aiControlDisabled==0 ? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."), (A.safe==0 ? "The 'Check Wiring' light is on." : "The 'Check Wiring' light is off."), - (A.normalspeed==0 ? "The 'Check Timing Mechanism' light is on." : "The 'Check Timing Mechanism' light is off.")) + (A.normalspeed==0 ? "The 'Check Timing Mechanism' light is on." : "The 'Check Timing Mechanism' light is off."), + (A.emergency==0 ? "The emergency lights are off." : "The emergency lights are on.")) /datum/wires/airlock/UpdateCut(var/index, var/mended) @@ -123,9 +124,12 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048 var/obj/machinery/door/airlock/A = holder switch(index) if(AIRLOCK_WIRE_IDSCAN) - //Sending a pulse through this flashes the red light on the door (if the door has power). + //Sending a pulse through this disables emergency access and flashes the red light on the door (if the door has power). if((A.arePowerSystemsOn()) && (!(A.stat & NOPOWER))) A.door_animate("deny") + if(A.emergency) + A.emergency = 0 + A.update_icon() if(AIRLOCK_WIRE_MAIN_POWER1 || AIRLOCK_WIRE_MAIN_POWER2) //Sending a pulse through either one causes a breaker to trip, disabling the door for 10 seconds if backup power is connected, or 1 minute if not (or until backup power comes back on, whichever is shorter). A.loseMainPower() diff --git a/code/datums/wires/autolathe.dm b/code/datums/wires/autolathe.dm new file mode 100644 index 00000000000..77a8ce6c03c --- /dev/null +++ b/code/datums/wires/autolathe.dm @@ -0,0 +1,58 @@ +/datum/wires/autolathe + + holder_type = /obj/machinery/autolathe + wire_count = 10 + +var/const/AUTOLATHE_HACK_WIRE = 1 +var/const/AUTOLATHE_SHOCK_WIRE = 2 +var/const/AUTOLATHE_DISABLE_WIRE = 4 + +/datum/wires/autolathe/GetInteractWindow() + var/obj/machinery/autolathe/A = holder + . += ..() + . += text("
The red light is [A.disabled ? "off" : "on"].
The green light is [A.shocked ? "off" : "on"].
The blue light is [A.hacked ? "off" : "on"].
") + +/datum/wires/autolathe/CanUse() + var/obj/machinery/autolathe/A = holder + if(A.panel_open) + return 1 + return 0 + +/datum/wires/autolathe/Interact(var/mob/living/user) + if(CanUse(user)) + var/obj/machinery/autolathe/V = holder + V.attack_hand(user) + +/datum/wires/autolathe/UpdateCut(index, mended) + var/obj/machinery/autolathe/A = holder + switch(index) + if(AUTOLATHE_HACK_WIRE) + A.adjust_hacked(!mended) + if(AUTOLATHE_SHOCK_WIRE) + A.shocked = !mended + if(AUTOLATHE_DISABLE_WIRE) + A.disabled = !mended + +/datum/wires/autolathe/UpdatePulsed(index) + if(IsIndexCut(index)) + return + var/obj/machinery/autolathe/A = holder + switch(index) + if(AUTOLATHE_HACK_WIRE) + A.adjust_hacked(!A.hacked) + spawn(50) + if(A && !IsIndexCut(index)) + A.adjust_hacked(0) + Interact(usr) + if(AUTOLATHE_SHOCK_WIRE) + A.shocked = !A.shocked + spawn(50) + if(A && !IsIndexCut(index)) + A.shocked = 0 + Interact(usr) + if(AUTOLATHE_DISABLE_WIRE) + A.disabled = !A.disabled + spawn(50) + if(A && !IsIndexCut(index)) + A.disabled = 0 + Interact(usr) \ No newline at end of file diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index e9bb526ec28..e8fba96a0d0 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -550,7 +550,7 @@ throwforce = 5.0 sharp = 1 edge = 1 - throw_speed = 1 + throw_speed = 2 throw_range = 3 w_class = 4.0 flags = FPRINT | TABLEPASS | NOSHIELD @@ -594,6 +594,7 @@ desc = "Special mechanical module made to store, sort, and apply standard machine parts." icon_state = "RPED" item_state = "RPED" + icon_override = 'icons/mob/in-hand/tools.dmi' w_class = 5 can_hold = list("/obj/item/weapon/stock_parts","/obj/item/weapon/cell") storage_slots = 50 diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index bb00904d72c..35ae358aea7 100644 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -56,6 +56,8 @@ NOTE: there are two lists of areas in the end of this file: centcom and station var/list/all_doors = list() //Added by Strumpetplaya - Alarm Change - Contains a list of doors adjacent to this area var/air_doors_activated = 0 + var/tele_proof = 0 + /*Adding a wizard area teleport list because motherfucking lag -- Urist*/ /*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/ var/list/teleportlocs = list() @@ -237,15 +239,15 @@ var/list/ghostteleportlocs = list() /area/shuttle/gamma/space icon_state = "shuttle" - name = "\improper Gamma Shuttle Space" - requires_power = 1 + name = "\improper Gamma Armory" + requires_power = 0 luminosity = 0 lighting_use_dynamic = 1 /area/shuttle/gamma/station icon_state = "shuttle" - name = "\improper Gamma Shuttle Station" - requires_power = 1 + name = "\improper Gamma Armory Station" + requires_power = 0 luminosity = 0 lighting_use_dynamic = 1 @@ -468,6 +470,12 @@ var/list/ghostteleportlocs = list() name = "\improper Syndicate Elite Squad" icon_state = "syndie-elite" +/area/syndicate_depot + name = "\improper Suspicious Supply Depot" + icon_state = "red" + tele_proof = 1 + requires_power = 0 + //EXTRA /area/asteroid // -- TLE @@ -626,37 +634,54 @@ var/list/ghostteleportlocs = list() requires_power = 0 /area/xenos_station/start - name = "\improper Start Area" + name = "\improper Alien Shuttle" icon_state = "north" + requires_power = 0 /area/xenos_station/transit name = "\improper Hyperspace" icon_state = "shuttle" + requires_power = 0 /area/xenos_station/southwest - name = "\improper Aft Port Solars" + name = "\improper Aft Port Solars Landing Area" icon_state = "southwest" + requires_power = 0 /area/xenos_station/northwest - name = "\improper Fore Port Solars" + name = "\improper Fore Port Solars Landing Area" icon_state = "northwest" + requires_power = 0 /area/xenos_station/northeast - name = "\improper Fore Starboard Solars" + name = "\improper Fore Starboard Solars Landing Area" icon_state = "northeast" requires_power = 0 /area/xenos_station/southeast - name = "\improper Aft Starboard Solars" + name = "\improper Aft Starboard Solars Landing Area" icon_state = "southeast" + requires_power = 0 -/area/xenos_station/north - name = "\improper West Landing Area" - icon_state = "north" - -/area/xenos_station/south +/area/xenos_station/east name = "\improper East Landing Area" + icon_state = "east" + requires_power = 0 + +/area/xenos_station/west + name = "\improper West Landing Area" + icon_state = "west" + requires_power = 0 + +/area/xenos_station/researchoutpost + name = "\improper Research Outpost Landing Area" + icon_state = "north" + requires_power = 0 + +/area/xenos_station/miningoutpost + name = "\improper Mining Outpost Landing Area" icon_state = "south" + requires_power = 0 //PRISON /area/prison @@ -978,6 +1003,10 @@ var/list/ghostteleportlocs = list() name = "\improper Blueshield's Office" icon_state = "blueold" +/area/centcomdocks + name = "\improper Central Command Docks" + icon_state = "centcom" + //Crew /area/crew_quarters @@ -1562,6 +1591,14 @@ area/security/podbay name = "\improper Vault" icon_state = "nuke_storage" +/area/security/customs + name = "\improper Customs" + icon_state = "checkpoint1" + +/area/security/customs2 + name = "\improper Customs" + icon_state = "security" + /area/security/checkpoint name = "\improper Security Checkpoint" icon_state = "checkpoint1" @@ -1660,8 +1697,12 @@ area/security/podbay name = "\improper Xenobiology Lab" icon_state = "toxlab" -/area/toxins/xenobiology/flora - name = "\improper Xenobiology Flora Lab" +/area/toxins/xenobiology/xenoflora_storage + name = "\improper Xenoflora Storage" + icon_state = "toxlab" + +/area/toxins/xenobiology/xenoflora + name = "\improper Xenoflora Lab" icon_state = "toxlab" /area/toxins/storage @@ -2017,8 +2058,20 @@ area/security/podbay name = "\improper AI Satellite" icon_state = "ai" +/area/aisat + name = "\improper AI Satellite Exterior" + icon_state = "yellow" + +/area/aisat/entrance + name = "\improper AI Satellite Entrance" + icon_state = "ai_foyer" + +/area/aisat/maintenance + name = "\improper AI Satellite Maintenance" + icon_state = "storage" + /area/turret_protected/aisat_interior - name = "\improper AI Satellite" + name = "\improper AI Satellite Antechamber" icon_state = "ai" /area/turret_protected/AIsatextFP diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index eb8a458c865..3c04e9cf951 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -1,6 +1,16 @@ // Areas.dm - +// Added to fix mech fabs 05/2013 ~Sayu +// This is necessary due to lighting subareas. If you were to go in assuming that things in +// the same logical /area have the parent /area object... well, you would be mistaken. If you +// want to find machines, mobs, etc, in the same logical area, you will need to check all the +// related areas. This returns a master contents list to assist in that. +/proc/area_contents(var/area/A) + if(!istype(A)) return null + var/list/contents = list() + for(var/area/LSA in A.related) + contents += LSA.contents + return contents // === /area diff --git a/code/game/asteroid.dm b/code/game/asteroid.dm index a37ac4c2ce4..c98607718f2 100644 --- a/code/game/asteroid.dm +++ b/code/game/asteroid.dm @@ -23,7 +23,7 @@ proc/spawn_room(var/atom/start_loc,var/x_size,var/y_size,var/wall,var/floor , va //world << "Room spawned at [start_loc.x],[start_loc.y],[start_loc.z]" if(!wall) - wall = pick(/turf/simulated/wall/r_wall,/turf/simulated/wall,/obj/effect/alien/resin) + wall = pick(/turf/simulated/wall/r_wall,/turf/simulated/wall,/obj/structure/alien/resin/wall) if(!floor) floor = pick(/turf/simulated/floor,/turf/simulated/floor/engine) @@ -44,9 +44,9 @@ proc/spawn_room(var/atom/start_loc,var/x_size,var/y_size,var/wall,var/floor , va if(x == 0 || x==x_size-1 || y==0 || y==y_size-1) - if(wall == /obj/effect/alien/resin) + if(wall == /obj/structure/alien/resin/wall) T = new floor(cur_loc) - new /obj/effect/alien/resin(T) + new /obj/structure/alien/resin/wall(T) else T = new wall(cur_loc) room_turfs["walls"] += T @@ -74,7 +74,7 @@ proc/admin_spawn_room_at_pos() if("Regular wall") wall=/turf/simulated/wall if("Resin wall") - wall=/obj/effect/alien/resin + wall=/obj/structure/alien/resin/wall switch(alert("Floor type",null,"Regular floor","Reinforced floor")) if("Regular floor") floor=/turf/simulated/floor diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 16a2426569e..b58e3bf099f 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -92,7 +92,8 @@ /atom/proc/emp_act(var/severity) return -/atom/proc/bullet_act(var/obj/item/projectile/Proj) +/atom/proc/bullet_act(var/obj/item/projectile/Proj, def_zone) + Proj.on_hit(src, 0, def_zone) return 0 /atom/proc/in_contents_of(container)//can take class or object instance as argument @@ -250,35 +251,32 @@ its easier to just keep the beam vertical. /atom/proc/add_hiddenprint(mob/living/M as mob) if(isnull(M)) return if(isnull(M.key)) return - if (!( src.flags ) & FPRINT) - return - if (ishuman(M)) + if(ishuman(M)) var/mob/living/carbon/human/H = M - if (!istype(H.dna, /datum/dna)) + if(!istype(H.dna, /datum/dna)) return 0 - if (H.gloves) - if(src.fingerprintslast != H.key) - src.fingerprintshidden += text("\[[time_stamp()]\] (Wearing gloves). Real name: [], Key: []",H.real_name, H.key) - src.fingerprintslast = H.key + if(H.gloves) + if(fingerprintslast != H.ckey) + fingerprintshidden += text("\[[time_stamp()]\] (Wearing gloves). Real name: [], Key: []",H.real_name, H.key) + fingerprintslast = H.ckey return 0 - if (!( src.fingerprints )) - if(src.fingerprintslast != H.key) - src.fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []",H.real_name, H.key) - src.fingerprintslast = H.key + if(!( fingerprints )) + if(fingerprintslast != H.ckey) + fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []",H.real_name, H.key) + fingerprintslast = H.ckey return 1 else - if(src.fingerprintslast != M.key) - src.fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []",M.real_name, M.key) - src.fingerprintslast = M.key + if(fingerprintslast != M.ckey) + fingerprintshidden += text("\[[time_stamp()]\] Real name: [], Key: []",M.real_name, M.key) + fingerprintslast = M.ckey return + +//Set ignoregloves to add prints irrespective of the mob having gloves on. /atom/proc/add_fingerprint(mob/living/M as mob, ignoregloves = 0) if(isnull(M)) return - if(isAI(M)) return if(isnull(M.key)) return - if (!( src.flags ) & FPRINT) - return - if (ishuman(M)) + if(ishuman(M)) //Add the list if it does not exist. if(!fingerprintshidden) fingerprintshidden = list() @@ -300,25 +298,25 @@ its easier to just keep the beam vertical. H.dna.real_name = H.real_name H.check_dna() - //Now, deal with gloves. - if (H.gloves && H.gloves != src) - if(fingerprintslast != H.key) - fingerprintshidden += text("\[[]\](Wearing gloves). Real name: [], Key: []",time_stamp(), H.real_name, H.key) - fingerprintslast = H.key - H.gloves.add_fingerprint(M) + //Check if the gloves (if any) hide fingerprints + if(H.gloves) + var/obj/item/clothing/gloves/G = H.gloves + if(G.transfer_prints) + ignoregloves = 1 - //Deal with gloves the pass finger/palm prints. + //Now, deal with gloves. if(!ignoregloves) - if(H.gloves != src) - if(prob(75) && istype(H.gloves, /obj/item/clothing/gloves/latex)) - return 0 - else if(H.gloves && !istype(H.gloves, /obj/item/clothing/gloves/latex)) - return 0 + if(H.gloves && H.gloves != src) + if(fingerprintslast != H.ckey) + fingerprintshidden += text("\[[]\](Wearing gloves). Real name: [], Key: []",time_stamp(), H.real_name, H.key) + fingerprintslast = H.ckey + H.gloves.add_fingerprint(M) + return 0 //More adminstuffz - if(fingerprintslast != H.key) + if(fingerprintslast != H.ckey) fingerprintshidden += text("\[[]\]Real name: [], Key: []",time_stamp(), H.real_name, H.key) - fingerprintslast = H.key + fingerprintslast = H.ckey //Make the list if it does not exist. if(!fingerprints) @@ -328,75 +326,37 @@ its easier to just keep the beam vertical. var/full_print = md5(H.dna.uni_identity) // Add the fingerprints - // - if(fingerprints[full_print]) - switch(stringpercent(fingerprints[full_print])) //tells us how many stars are in the current prints. - - if(28 to 32) - if(prob(1)) - fingerprints[full_print] = full_print // You rolled a one buddy. - else - fingerprints[full_print] = stars(full_print, rand(0,40)) // 24 to 32 - - if(24 to 27) - if(prob(3)) - fingerprints[full_print] = full_print //Sucks to be you. - else - fingerprints[full_print] = stars(full_print, rand(15, 55)) // 20 to 29 - - if(20 to 23) - if(prob(5)) - fingerprints[full_print] = full_print //Had a good run didn't ya. - else - fingerprints[full_print] = stars(full_print, rand(30, 70)) // 15 to 25 - - if(16 to 19) - if(prob(5)) - fingerprints[full_print] = full_print //Welp. - else - fingerprints[full_print] = stars(full_print, rand(40, 100)) // 0 to 21 - - if(0 to 15) - if(prob(5)) - fingerprints[full_print] = stars(full_print, rand(0,50)) // small chance you can smudge. - else - fingerprints[full_print] = full_print - - else - fingerprints[full_print] = stars(full_print, rand(0, 20)) //Initial touch, not leaving much evidence the first time. - + fingerprints[full_print] = full_print return 1 else //Smudge up dem prints some - if(fingerprintslast != M.key) + if(fingerprintslast != M.ckey) fingerprintshidden += text("\[[]\]Real name: [], Key: []",time_stamp(), M.real_name, M.key) - fingerprintslast = M.key + fingerprintslast = M.ckey - //Cleaning up shit. - if(fingerprints && !fingerprints.len) - del(fingerprints) return /atom/proc/transfer_fingerprints_to(var/atom/A) - if(!istype(A.fingerprints,/list)) + // Make sure everything are lists. + if(!islist(A.fingerprints)) A.fingerprints = list() - - if(!istype(A.fingerprintshidden,/list)) + if(!islist(A.fingerprintshidden)) A.fingerprintshidden = list() - if(!istype(fingerprintshidden, /list)) + if(!islist(fingerprints)) + fingerprints = list() + if(!islist(fingerprintshidden)) fingerprintshidden = list() - //skytodo - //A.fingerprints |= fingerprints //detective - //A.fingerprintshidden |= fingerprintshidden //admin - if(A.fingerprints && fingerprints) + // Transfer + if(fingerprints) A.fingerprints |= fingerprints.Copy() //detective - if(A.fingerprintshidden && fingerprintshidden) - A.fingerprintshidden |= fingerprintshidden.Copy() //admin A.fingerprintslast = fingerprintslast + if(fingerprintshidden) + A.fingerprintshidden |= fingerprintshidden.Copy() //admin + A.fingerprintslast = fingerprintslast //returns 1 if made bloody, returns 0 otherwise diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index 8ffe4d57791..c8e3b2aa347 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -74,8 +74,8 @@ for(var/obj/item/weapon/stock_parts/manipulator/P in component_parts) precision_coeff = P.rating for(var/obj/item/weapon/stock_parts/micro_laser/P in component_parts) - damage_coeff = P.rating - + damage_coeff = P.rating + /obj/machinery/dna_scannernew/allow_drop() return 0 @@ -186,8 +186,8 @@ default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]", item) if(exchange_parts(user, item)) - return - + return + if(istype(item, /obj/item/weapon/crowbar)) if(panel_open) for(var/obj/I in contents) // in case there is something in the scanner @@ -237,22 +237,21 @@ || locate(/obj/machinery/computer/cloning, get_step(src, EAST)) \ || locate(/obj/machinery/computer/cloning, get_step(src, WEST))) - if(!M.client && M.mind) - for(var/mob/dead/observer/ghost in player_list) - if(ghost.mind == M.mind) - ghost << "Your corpse has been placed into a cloning scanner. Return to your body if you want to be resurrected/cloned! (Verbs -> Ghost -> Re-enter corpse)" - break + var/mob/dead/observer/ghost = occupant.get_ghost() + if(ghost) + ghost << "Your corpse has been placed into a cloning scanner. Return to your body if you want to be cloned! (Verbs -> Ghost -> Re-enter corpse)" + ghost << sound('sound/effects/genetics.ogg') return /obj/machinery/dna_scannernew/proc/go_out() if (!src.occupant) usr << "The scanner is empty!" return - + if (src.locked) usr << "The scanner is locked!" return - + if (src.occupant.client) src.occupant.client.eye = src.occupant.client.mob src.occupant.client.perspective = MOB_PERSPECTIVE diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm index 0221d31c6f5..b4bdee1b464 100644 --- a/code/game/dna/genes/vg_powers.dm +++ b/code/game/dna/genes/vg_powers.dm @@ -222,19 +222,26 @@ Obviously, requires DNA2. /obj/effect/proc_holder/spell/wizard/targeted/remotetalk/choose_targets(mob/user = usr) var/list/targets = new /list() var/list/validtargets = new /list() - for(var/mob/M in view(usr)) - validtargets += M + for(var/mob/M in living_mob_list) + if(M && M.mind) + var/special_role = M.mind.special_role + if (special_role == "Wizard" || special_role == "Ninja" || special_role == "Syndicate" || special_role == "Syndicate Commando" || special_role == "Vox Raider" || special_role == "Alien") + continue + + validtargets += M + if(!validtargets.len || validtargets.len == 1) - usr << "There are no valid targets in range!" + usr << "There are no valid targets!" start_recharge() return + targets += input("Choose the target to talk to.", "Targeting") as mob in validtargets perform(targets) /obj/effect/proc_holder/spell/wizard/targeted/remotetalk/cast(list/targets) if(!ishuman(usr)) return - var/say = input("What do you wish to say") + var/say = strip_html(input("What do you wish to say")) for(var/mob/living/target in targets) if(M_REMOTE_TALK in target.mutations) diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm index 59225edc2b9..ccbff9b326d 100644 --- a/code/game/gamemodes/blob/blob.dm +++ b/code/game/gamemodes/blob/blob.dm @@ -30,7 +30,7 @@ var/list/blob_nodes = list() /datum/game_mode/blob/pre_setup() - var/list/possible_blobs = get_players_for_role(BE_ALIEN) + var/list/possible_blobs = get_players_for_role(BE_BLOB) // stop setup if no possible traitors if(!possible_blobs.len) @@ -182,7 +182,7 @@ var/list/blob_nodes = list() return if (2) - command_alert("The biohazard has grown out of control and will soon reach critical mass. Activate the nuclear failsafe to mantain quarantine. The Nuclear Authentication Code is [get_nuke_code()] ", "Biohazard Alert") + command_alert("The biohazard has grown out of control and will soon reach critical mass. Activate the nuclear failsafe to maintain quarantine. The Nuclear Authentication Code is [get_nuke_code()] ", "Biohazard Alert") set_security_level("gamma") var/obj/machinery/door/airlock/vault/V = locate(/obj/machinery/door/airlock/vault) in world if(V && V.z == 1) diff --git a/code/game/gamemodes/blob/blobs/core.dm b/code/game/gamemodes/blob/blobs/core.dm index 9aa2fb50d79..2dd69860b14 100644 --- a/code/game/gamemodes/blob/blobs/core.dm +++ b/code/game/gamemodes/blob/blobs/core.dm @@ -72,7 +72,7 @@ var/list/candidates = list() if(!new_overmind) - candidates = get_candidates(BE_ALIEN) + candidates = get_candidates(BE_BLOB) if(candidates.len) C = pick(candidates) else diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index 26ea6b40bd9..e8a7f68c5da 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -573,6 +573,8 @@ C.SetParalysis(0) C.SetStunned(0) C.SetWeakened(0) + C.adjustStaminaLoss(-75) + C.reagents.add_reagent("synaptizine", 20) C.lying = 0 C.update_canmove() @@ -685,7 +687,7 @@ var/list/datum/dna/hivemind_bank = list() /mob/proc/changeling_hivedownload() set category = "Changeling" set name = "Hive Absorb (20)" - set desc = "Allows you to absorb DNA that is being channeled in the airwaves." + set desc = "Allows you to absorb DNA that is being channelled in the airwaves." var/datum/changeling/changeling = changeling_power(20,1) if(!changeling) return @@ -770,6 +772,12 @@ var/list/datum/dna/hivemind_bank = list() if(!sting_can_reach(T, changeling.sting_range)) return if(!changeling_power(required_chems)) return + if(ishuman(T)) + var/mob/living/carbon/human/H = T + if(H.species.flags & IS_SYNTHETIC) + src << "This won't work on synthetics." + return + changeling.chem_charges -= required_chems changeling.sting_range = 1 src.verbs -= verb_path @@ -885,7 +893,7 @@ var/list/datum/dna/hivemind_bank = list() var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_unfat_sting) if(!T) return 0 - T << "you feel a small prick as stomach churns violently and you become to feel skinnier." + T << "You feel a small prick as stomach churns violently and you become to feel skinnier." T.overeatduration = 0 T.nutrition -= 100 feedback_add_details("changeling_powers","US") diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm index 63112829a84..2276eccbfac 100644 --- a/code/game/gamemodes/cult/talisman.dm +++ b/code/game/gamemodes/cult/talisman.dm @@ -2,7 +2,7 @@ icon_state = "paper_talisman" var/imbue = null var/uses = 0 - + info = "


" examine() set src in view(2) diff --git a/code/game/gamemodes/events/power_failure.dm b/code/game/gamemodes/events/power_failure.dm index f5c63e381bd..141efd60412 100644 --- a/code/game/gamemodes/events/power_failure.dm +++ b/code/game/gamemodes/events/power_failure.dm @@ -6,6 +6,7 @@ M << sound('sound/AI/poweroff.ogg') var/list/skipped_areas = list(/area/turret_protected/ai) + var/list/skipped_areas_apc = list(/area/engine/engineering) for(var/obj/machinery/power/smes/S in machines) var/area/current_area = get_area(S) @@ -19,18 +20,25 @@ for(var/obj/machinery/power/apc/C in world) - if(C.cell && C.z == 1) + var/area/current_area = get_area(C) + if(current_area.type in skipped_areas_apc || C.z != 1) + continue + if(C.cell) C.cell.charge = 0 /proc/power_restore(var/announce = 1) var/list/skipped_areas = list(/area/turret_protected/ai) + var/list/skipped_areas_apc = list(/area/engine/engineering) if(announce) command_alert("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal") for(var/mob/M in player_list) M << sound('sound/AI/poweron.ogg') for(var/obj/machinery/power/apc/C in machines) - if(C.cell && C.z == 1) + var/area/current_area = get_area(C) + if(current_area.type in skipped_areas_apc || C.z != 1) + continue + if(C.cell) C.cell.charge = C.cell.maxcharge for(var/obj/machinery/power/smes/S in machines) var/area/current_area = get_area(S) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 2ecd5bd3b8e..01ae08fdbff 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -280,7 +280,7 @@ Implants; for(var/mob/living/carbon/human/man in player_list) if(man.client && man.mind) // NT relation option var/special_role = man.mind.special_role - if (special_role == "Wizard" || special_role == "Ninja" || special_role == "Syndicate") + if (special_role == "Wizard" || special_role == "Ninja" || special_role == "Syndicate" || special_role == "Syndicate Commando" || special_role == "Vox Raider" || special_role == "Alien") continue //NT intelligence ruled out possiblity that those are too classy to pretend to be a crew. if(man.client.prefs.nanotrasen_relation == "Opposed" && prob(50) || \ man.client.prefs.nanotrasen_relation == "Skeptical" && prob(20)) diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 1eb60d3a301..844669ff039 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -48,7 +48,7 @@ rcd light flash thingy on matter drain for(var/mob/living/silicon/ai/ai in player_list) ai.fire_res_on_core = 1 src.verbs -= /mob/living/silicon/ai/proc/fireproof_core - src << "\red Core fireproofed." + src << "Core fireproofed." /datum/AI_Module/large/upgrade_turrets module_name = "AI Turret upgrade" @@ -66,6 +66,81 @@ rcd light flash thingy on matter drain for(var/obj/machinery/turret/turret in machines) turret.health += 30 turret.shot_delay = 20 + src << "Turrets upgraded." + +/datum/AI_Module/large/lockdown + module_name = "Hostile Station Lockdown" + mod_pick_name = "lockdown" + description = "Take control of the airlock, blast door and fire control networks, locking them down. Caution! This command also electrifies all airlocks." + cost = 20 + one_time = 1 + + power_type = /mob/living/silicon/ai/proc/lockdown + +/mob/living/silicon/ai/proc/lockdown() + set category = "Malfunction" + set name = "Initiate Hostile Lockdown" + + if(src.stat == 2) + src <<"You cannot begin a lockdown because you are dead!" + return + + if(malf_cooldown) + return + + var/obj/machinery/door/airlock/AL + for(var/obj/machinery/door/D in airlocks) + spawn() + if(istype(D, /obj/machinery/door/airlock)) + AL = D + if(AL.canAIControl() && !AL.stat) //Must be powered and have working AI wire. + AL.locked = 0 //For airlocks that were bolted open. + AL.safe = 0 //DOOR CRUSH + AL.close() + AL.locked = 1 //Bolt it! + AL.lights = 0 //Stealth bolt for a classic AI door trap. + AL.secondsElectrified = -1 //Shock it! + else if(!D.stat) //So that only powered doors are closed. + D.close() //Close ALL the doors! + + var/obj/machinery/computer/communications/C = locate() in machines + if(C) + C.post_status("alert", "lockdown") + + src.verbs += /mob/living/silicon/ai/proc/disablelockdown + src << "Lockdown Initiated." + malf_cooldown = 1 + spawn(30) + malf_cooldown = 0 + +/mob/living/silicon/ai/proc/disablelockdown() + set category = "Malfunction" + set name = "Disable Lockdown" + + if(src.stat == 2) + src <<"You cannot disable lockdown because you are dead!" + return + if(malf_cooldown) + return + + var/obj/machinery/door/airlock/AL + for(var/obj/machinery/door/D in airlocks) + spawn() + if(istype(D, /obj/machinery/door/airlock)) + AL = D + if(AL.canAIControl() && !AL.stat) //Must be powered and have working AI wire. + AL.locked = 0 + AL.secondsElectrified = 0 + AL.open() + AL.safe = 1 + AL.lights = 1 //Essentially reset the airlock to normal. + else if(!D.stat) //Opens only powered doors. + D.open() //Open everything! + + src << "Lockdown Lifted." + malf_cooldown = 1 + spawn(30) + malf_cooldown = 0 /datum/AI_Module/large/disable_rcd module_name = "RCD disable" @@ -85,8 +160,8 @@ rcd light flash thingy on matter drain rcd.disabled = 1 for(var/obj/item/mecha_parts/mecha_equipment/tool/rcd/rcd in world) rcd.disabled = 1 - src << "RCD-disabling pulse emitted." - else src << "Out of uses." + src << "Out of uses." /datum/AI_Module/small/overload_machine module_name = "Machine overload" @@ -101,17 +176,48 @@ rcd light flash thingy on matter drain set name = "Overload Machine" set category = "Malfunction" if (istype(M, /obj/machinery)) + if(istype(M, /obj/machinery/singularity) || istype(M,/obj/machinery/field_generator) || istype(M, /obj/machinery/singularity/narsie)) + src << "This machine can not be overloaded due to a firewall." + return for(var/datum/AI_Module/small/overload_machine/overload in current_modules) if(overload.uses > 0) overload.uses -- for(var/mob/V in hearers(M, null)) - V.show_message("\blue You hear a loud electrical buzzing sound!", 2) + V.show_message("You hear a loud electrical buzzing sound!", 2) spawn(50) explosion(get_turf(M), 0,1,1,0) del(M) - else src << "Out of uses." - else src << "That's not a machine." + else src << "Out of uses." + else src << "That's not a machine." +/datum/AI_Module/small/override_machine + module_name = "Machine override" + mod_pick_name = "override" + description = "Overrides a machine's programming, causing it to rise up and attack everyone except other machines. 4 uses." + uses = 4 + cost = 15 + + power_type = /mob/living/silicon/ai/proc/override_machine + + +/mob/living/silicon/ai/proc/override_machine(obj/machinery/M as obj in world) + set name = "Override Machine" + set category = "Malfunction" + if (istype(M, /obj/machinery)) + if(istype(M, /obj/machinery/singularity) || istype(M,/obj/machinery/field_generator) || istype(M, /obj/machinery/singularity/narsie)) + src << "This machine can not be overloaded due to a firewall." + return + for(var/datum/AI_Module/small/override_machine/override in current_modules) + if(override.uses > 0) + override.uses -- + for(var/mob/V in hearers(M, null)) + V.show_message("You hear a loud electrical buzzing sound!", 2) + src << "Reprogramming machine behaviour..." + spawn(50) + if(M) + new /mob/living/simple_animal/hostile/mimic/copy/machine(get_turf(M), M, src, 1) + else src << "Out of uses." + else src << "That's not a machine." /datum/AI_Module/large/place_cyborg_transformer module_name = "Robotic Factory (Removes Shunting)" @@ -173,7 +279,7 @@ rcd light flash thingy on matter drain playsound(middle, 'sound/effects/phasein.ogg', 100, 1) src.can_shunt = 0 PCT.uses -= 1 - src << "You cannot shunt anymore." + src << "You cannot shunt anymore." /datum/AI_Module/small/blackout @@ -195,33 +301,18 @@ rcd light flash thingy on matter drain if(prob(30*apc.overload)) apc.overload_lighting() else apc.overload++ - else src << "Out of uses." - -/datum/AI_Module/small/interhack - module_name = "Hack intercept" - mod_pick_name = "interhack" - description = "Hacks the status upgrade from Cent. Com, removing any information about malfunctioning electrical systems." - cost = 15 - one_time = 1 - - power_type = /mob/living/silicon/ai/proc/interhack - -/mob/living/silicon/ai/proc/interhack() - set category = "Malfunction" - set name = "Hack intercept" - src.verbs -= /mob/living/silicon/ai/proc/interhack - ticker.mode:hack_intercept() + src << "Overcurrent applied to the powernet." + else src << "Out of uses." /datum/AI_Module/small/reactivate_camera module_name = "Reactivate camera" mod_pick_name = "recam" - description = "Reactivates a currently disabled camera. 10 uses." - uses = 10 - cost = 15 + description = "Reactivates a currently disabled camera. 5 uses." + uses = 5 + cost = 5 power_type = /client/proc/reactivate_camera - /client/proc/reactivate_camera(obj/machinery/camera/C as obj in cameranet.viewpoints) set name = "Reactivate Camera" set category = "Malfunction" @@ -231,17 +322,18 @@ rcd light flash thingy on matter drain if(!C.status) C.deactivate(src) camera.uses -- + src << "Camera reactivated." else - src << "This camera is either active, or not repairable." - else src << "Out of uses." - else src << "That's not a camera." + src << "This camera is either active, or not repairable." + else src << "Out of uses." + else src << "That's not a camera." /datum/AI_Module/small/upgrade_camera module_name = "Upgrade Camera" mod_pick_name = "upgradecam" - description = "Upgrades a camera to have X-Ray vision, Motion and be EMP-Proof. 10 uses." - uses = 10 - cost = 15 + description = "Upgrades a camera to have X-Ray vision, Motion and be EMP-Proof. 5 uses." + uses = 5 + cost = 5 power_type = /client/proc/upgrade_camera @@ -274,11 +366,11 @@ rcd light flash thingy on matter drain if(upgraded) UC.uses -- C.visible_message("\icon[C] *beep*") - src << "Camera successully upgraded!" + src << "Camera successully upgraded!" else - src << "This camera is already upgraded!" + src << "This camera is already upgraded!" else - src << "Out of uses." + src << "Out of uses." /datum/module_picker diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index 79dd518948b..cc7456601c6 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -5,7 +5,7 @@ name = "AI malfunction" config_tag = "malfunction" required_players = 2 - required_players_secret = 15 + required_players_secret = 20 required_enemies = 1 recommended_enemies = 1 @@ -15,7 +15,7 @@ var/const/waittime_l = 600 var/const/waittime_h = 1800 // started at 1800 - var/AI_win_timeleft = 1800 //started at 1800, in case I change this for testing round end. + var/AI_win_timeleft = 5400 //started at 5400, in case I change this for testing round end. var/malf_mode_declared = 0 var/station_captured = 0 var/to_nuke_or_not_to_nuke = 0 @@ -88,8 +88,8 @@ /datum/game_mode/malfunction/process() - if (apcs >= 3 && malf_mode_declared) - AI_win_timeleft -= ((apcs/6)*last_tick_duration) //Victory timer now de-increments based on how many APCs are hacked. --NeoFite + if ((apcs > 0) && malf_mode_declared) + AI_win_timeleft -= apcs * last_tick_duration //Victory timer now de-increments based on how many APCs are hacked. --NeoFite ..() if (AI_win_timeleft<=0) check_win() @@ -106,8 +106,8 @@ /datum/game_mode/malfunction/proc/capture_the_station() - world << {"The AI has won!
- It has fully taken control of all of [station_name()]'s systems."} + world << "The AI has won!" + world << "It has fully taken control of all of [station_name()]'s systems." to_nuke_or_not_to_nuke = 1 for(var/datum/mind/AI_mind in malf_ai) @@ -170,6 +170,12 @@ command_alert("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert") set_security_level("delta") + for(var/obj/item/weapon/pinpointer/point in world) + for(var/datum/mind/AI_mind in ticker.mode.malf_ai) + var/mob/living/silicon/ai/A = AI_mind.current // the current mob the mind owns + if(A.stat != DEAD) + point.the_disk = A //The pinpointer now tracks the AI core. + ticker.mode:malf_mode_declared = 1 for(var/datum/mind/AI_mind in ticker.mode:malf_ai) AI_mind.current.verbs -= /datum/game_mode/malfunction/proc/takeover diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 25e50465723..78db5e77846 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -231,7 +231,7 @@ proc/issyndicate(mob/living/M as mob) synd_mob.equip_to_slot_or_del(R, slot_l_ear) synd_mob.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(synd_mob), slot_w_uniform) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(synd_mob), slot_shoes) + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(synd_mob), slot_shoes) synd_mob.equip_or_collect(new /obj/item/clothing/gloves/combat(synd_mob), slot_gloves) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/card/id/syndicate(synd_mob), slot_wear_id) if(synd_mob.backbag == 2) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(synd_mob), slot_back) diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index a207fec53c2..8cfa326239b 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -29,6 +29,7 @@ var/bomb_set var/uititle flags = FPRINT use_power = 0 + unacidable = 1 /obj/machinery/nuclearbomb/New() ..() diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index d75709ac2dc..200f9e60528 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -386,7 +386,7 @@ datum/objective/silence datum/objective/escape - explanation_text = "Escape on the shuttle or an escape pod alive and free." + explanation_text = "Escape on the shuttle alive and free." check_completion() if(issilicon(owner.current)) diff --git a/code/game/gamemodes/steal_items.dm b/code/game/gamemodes/steal_items.dm index c21cc4ff05e..5a92a88c673 100644 --- a/code/game/gamemodes/steal_items.dm +++ b/code/game/gamemodes/steal_items.dm @@ -52,6 +52,11 @@ name = "a functional AI" typepath = /obj/item/device/aicard +/datum/theft_objective/defib + name = "a defibrillator" + typepath = /obj/item/weapon/defibrillator + protected_jobs = list("Chief Medical Officer", "Medical Doctor", "Chemist", "Geneticist", "Virologist", "Psychiatrist", "Paramedic", "Brig Physician") + /datum/theft_objective/magboots name = "the chief engineer's advanced magnetic boots" typepath = /obj/item/clothing/shoes/magboots/advance diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index 73444923700..3ec453f56d7 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -78,6 +78,7 @@ M.current.weakened = 0 M.current.stunned = 0 M.current.paralysis = 0 + M.current.adjustStaminaLoss(-75) //M.vampire.bloodusable -= 10 M.current << "\blue You flush your system with clean blood and remove any incapacitating effects." spawn(1) diff --git a/code/game/gamemodes/vox/trade/trade.dm b/code/game/gamemodes/vox/trade/trade.dm index c25e9ebb854..38c42dc6fa3 100644 --- a/code/game/gamemodes/vox/trade/trade.dm +++ b/code/game/gamemodes/vox/trade/trade.dm @@ -9,9 +9,9 @@ VOX TRADE ROUNDTYPE /datum/game_mode/vox/trade name = "trade" config_tag = "trade" - required_players = 10 - required_players_secret = 10 - required_enemies = 1 + required_players = 15 + required_players_secret = 15 + required_enemies = 3 recommended_enemies = 3 var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) diff --git a/code/game/gamemodes/vox/vox.dm b/code/game/gamemodes/vox/vox.dm index 243b7b73ab7..16d5a66fddf 100644 --- a/code/game/gamemodes/vox/vox.dm +++ b/code/game/gamemodes/vox/vox.dm @@ -94,7 +94,7 @@ datum/objective/vox/heist/loot if(2) target = /obj/machinery/the_singularitygen target_amount = 1 - loot = "a gravitational generator" + loot = "a gravitational singularity generator" if(3) target = /obj/machinery/power/emitter target_amount = 4 @@ -216,7 +216,7 @@ datum/objective/vox/trade/trade if(2) target = /obj/machinery/the_singularitygen target_amount = 1 - loot = "a gravitational generator" + loot = "a gravitational singularity generator" if(3) target = /obj/machinery/power/emitter target_amount = 4 diff --git a/code/game/gamemodes/wizard/rightandwrong.dm b/code/game/gamemodes/wizard/rightandwrong.dm index 045809b422e..e1b0c7a65f3 100644 --- a/code/game/gamemodes/wizard/rightandwrong.dm +++ b/code/game/gamemodes/wizard/rightandwrong.dm @@ -19,12 +19,12 @@ for(var/datum/objective/OBJ in H.mind.objectives) H << "Objective #[obj_count]: [OBJ.explanation_text]" obj_count++ - var/randomizeguns = pick("taser","egun","laser","revolver","detective","smg","nuclear","deagle","gyrojet","pulse","silenced","cannon","doublebarrel","shotgun","combatshotgun","mateba","smg","uzi","crossbow","saw") + var/randomizeguns = pick("taser","egun","laser","revolver","detective","c20r","nuclear","deagle","gyrojet","pulse","silenced","cannon","doublebarrel","shotgun","combatshotgun","bulldog","mateba","sabr","crossbow","saw","car") var/randomizemagic = pick("fireball","smoke","blind","mindswap","forcewall","knock","horsemask","charge","wandnothing", "wanddeath", "wandresurrection", "wandpolymorph", "wandteleport", "wanddoor", "wandfireball", "staffchange", "staffhealing", "armor", "scrying") if(!summon_type) switch (randomizeguns) if("taser") - new /obj/item/weapon/gun/energy/taser(get_turf(H)) + new /obj/item/weapon/gun/energy/advtaser(get_turf(H)) if("egun") new /obj/item/weapon/gun/energy/gun(get_turf(H)) if("laser") @@ -33,7 +33,7 @@ new /obj/item/weapon/gun/projectile/revolver(get_turf(H)) if("detective") new /obj/item/weapon/gun/projectile/revolver/detective(get_turf(H)) - if("smg") + if("c20r") new /obj/item/weapon/gun/projectile/automatic/c20r(get_turf(H)) if("nuclear") new /obj/item/weapon/gun/energy/gun/nuclear(get_turf(H)) @@ -45,7 +45,7 @@ new /obj/item/weapon/gun/energy/pulse_rifle(get_turf(H)) if("silenced") new /obj/item/weapon/gun/projectile/automatic/pistol(get_turf(H)) - new /obj/item/weapon/silencer(get_turf(H)) + new /obj/item/weapon/suppressor(get_turf(H)) if("cannon") new /obj/item/weapon/gun/energy/lasercannon(get_turf(H)) if("doublebarrel") @@ -54,16 +54,18 @@ new /obj/item/weapon/gun/projectile/shotgun/(get_turf(H)) if("combatshotgun") new /obj/item/weapon/gun/projectile/shotgun/combat(get_turf(H)) + if("bulldog") + new /obj/item/weapon/gun/projectile/automatic/bulldog(get_turf(H)) if("mateba") new /obj/item/weapon/gun/projectile/revolver/mateba(get_turf(H)) - if("smg") + if("sabr") new /obj/item/weapon/gun/projectile/automatic(get_turf(H)) - if("uzi") - new /obj/item/weapon/gun/projectile/automatic/mini_uzi(get_turf(H)) if("crossbow") new /obj/item/weapon/gun/energy/crossbow(get_turf(H)) if("saw") new /obj/item/weapon/gun/projectile/automatic/l6_saw(get_turf(H)) + if("car") + new /obj/item/weapon/gun/projectile/automatic/c90gl(get_turf(H)) else switch (randomizemagic) if("fireball") diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index f365b298e5e..efb7538cdb0 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -373,7 +373,7 @@ /obj/item/weapon/spellbook/oneuse/fireball/recoil(mob/user as mob) ..() - explosion(user.loc, -1, 0, 2, 3, 0, flame_range = 2) + explosion(user.loc, -1, 0, 2, 3, 0) del(src) /obj/item/weapon/spellbook/oneuse/smoke @@ -406,6 +406,7 @@ spellname = "mindswap" icon_state ="bookmindswap" desc = "This book's cover is pristine, though its pages look ragged and torn." + var/mob/stored_swap = null //Used in used book recoils to store an identity for mindswaps /obj/item/weapon/spellbook/oneuse/mindswap/onlearned() spellname = pick("fireball","smoke","blind","forcewall","knock","horses","charge") @@ -415,8 +416,45 @@ /obj/item/weapon/spellbook/oneuse/mindswap/recoil(mob/user as mob) ..() - user <<"You suddenly don't feel like yourself!" - wabbajack(user) + if(stored_swap in dead_mob_list) + stored_swap = null + if(!stored_swap) + stored_swap = user + user <<"For a moment you feel like you don't even know who you are anymore." + return + if(stored_swap == user) + user <<"You stare at the book some more, but there doesn't seem to be anything else to learn..." + return + + if(user.mind.special_verbs.len) + for(var/V in user.mind.special_verbs) + user.verbs -= V + + if(stored_swap.mind.special_verbs.len) + for(var/V in stored_swap.mind.special_verbs) + stored_swap.verbs -= V + + var/mob/dead/observer/ghost = stored_swap.ghostize(0) + ghost.spell_list = stored_swap.spell_list + + user.mind.transfer_to(stored_swap) + stored_swap.spell_list = user.spell_list + + if(stored_swap.mind.special_verbs.len) + for(var/V in user.mind.special_verbs) + user.verbs += V + + ghost.mind.transfer_to(user) + user.key = ghost.key + user.spell_list = ghost.spell_list + + if(user.mind.special_verbs.len) + for(var/V in user.mind.special_verbs) + user.verbs += V + + stored_swap <<"You're suddenly somewhere else... and someone else?!" + user <<"Suddenly you're staring at [src] again... where are you, who are you?!" + stored_swap = null /obj/item/weapon/spellbook/oneuse/forcewall spell = /obj/effect/proc_holder/spell/wizard/aoe_turf/conjure/forcewall diff --git a/code/game/gamemodes/xenos/xenos.dm b/code/game/gamemodes/xenos/xenos.dm index 54d63a6948b..0d4c7f06b1b 100644 --- a/code/game/gamemodes/xenos/xenos.dm +++ b/code/game/gamemodes/xenos/xenos.dm @@ -8,20 +8,25 @@ required_players = 0 recommended_players = 30 required_players_secret = 20 - required_enemies = 5 - recommended_enemies = 8 + required_enemies = 3 + recommended_enemies = 3 + var/result = 0 + var/checkwin_counter = 0 + var/xenos_list = list() + var/gammacalled = 0 var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds) var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds) - var/list/raid_objectives = list() //Raid objectives. + var/xenoai = 0 //Should the Xenos have their own AI? + var/xenoborg = 0 //Should the Xenos have their own borg? + var/gammaratio = 4 //At what alien to human ratio will the Gamma security level be called and the nuke be made available? /datum/game_mode/xenos/announce() world << "The current game mode is - Xenos!" - world << "There is a \red Xenos Attack\black on the station. You can't let them take over!" + world << "There is an Xenomorph attack on the station.
Aliens - Kill or infect the crew. Protect the Queen.
Crew - Protect the station. Exterminate all aliens.
" /datum/game_mode/xenos/can_start() - if(!..()) return 0 @@ -32,7 +37,6 @@ if((player.client)&&(player.ready)) playersready += 1 - //Check that we have enough alien candidates if(candidates.len < required_enemies) return 0 @@ -67,15 +71,15 @@ continue var/xenoai_selected = 0 - var/xenoborg_selected=0 - var/xenoqueen_selected=0 + var/xenoborg_selected = 0 + var/xenoqueen_selected = 0 var/spawnpos = 1 for(var/datum/mind/xeno_mind in xenos) if(spawnpos > xenos_spawn.len) spawnpos = 1 -//XenoAI selection - if(!xenoai_selected) + //XenoAI selection + if(xenoai && !xenoai_selected) var/mob/living/silicon/ai/O = new(xenos_spawn[spawnpos],,,1)//No MMI but safety is in effect. O.invisibility = 0 O.aiRestorePowerRoutine = 0 @@ -85,7 +89,8 @@ O.mind.original = O else O.key = xeno_mind.current.key - del(xeno_mind) + + //del(xeno_mind) var/obj/loc_landmark for(var/obj/effect/landmark/start/sloc in landmarks_list) if (sloc.name == "XenoAI") @@ -99,6 +104,7 @@ O.laws = new /datum/ai_laws/alienmov O.name = "Alien AI" O.real_name = name + xeno_mind.name = O.name O.alienAI = 1 O.network = list("SS13","Xeno") O.holo_icon = getHologramIcon(icon('icons/mob/AI.dmi',"holo3")) @@ -106,34 +112,35 @@ xenoai_selected = 1 spawnpos++ continue -//XenoQueen Selection + //XenoQueen Selection if(!xenoqueen_selected) - var/mob/living/carbon/alien/humanoid/queen/large/O = new(xenos_spawn[spawnpos]) + var/mob/living/carbon/alien/humanoid/queen/O = new(xenos_spawn[spawnpos]) if(xeno_mind.current) xeno_mind.transfer_to(O) else O.key = xeno_mind.current.key - del(xeno_mind) + xeno_mind.name = O.name + //del(xeno_mind) xenoqueen_selected = 1 spawnpos++ continue -//XenoBorg Selection - if(!xenoborg_selected) + //XenoBorg Selection + if(xenoborg && !xenoborg_selected) var/mob/living/silicon/robot/O = new(xenos_spawn[spawnpos],0,0,1) O.mmi = new /obj/item/device/mmi(O) O.mmi.alien = 1 O.mmi.transfer_identity(xeno_mind.current)//Does not transfer key/client. O.cell = new(O) - O.cell.maxcharge = 15000 - O.cell.charge = 15000 + O.cell.maxcharge = 25000 + O.cell.charge = 25000 O.gender = xeno_mind.current.gender O.invisibility = 0 - O.key = xeno_mind.current.key - del(xeno_mind) + //del(xeno_mind) O.job = "Alien Cyborg" O.name = "Alien Cyborg" O.real_name = name + xeno_mind.name = O.name O.module = new /obj/item/weapon/robot_module/alien/hunter(src) O.hands.icon_state = "standard" O.icon = 'icons/mob/alien.dmi' @@ -142,24 +149,133 @@ O.connected_ai = select_active_alien_ai() O.laws = new /datum/ai_laws/alienmov() O.scrambledcodes = 1 + O.hiddenborg = 1 O.alien_talk_understand = 1 feedback_inc("xeborg_hunter",1) - - xenoborg_selected = 1 spawnpos++ continue -//Additional larvas if playercount > 20 + //Additional larvas if playercount > 20 else var/mob/living/carbon/alien/larva/O = new(xenos_spawn[spawnpos]) if(xeno_mind.current) xeno_mind.transfer_to(O) else O.key = xeno_mind.current.key - del(xeno_mind) + xeno_mind.name = O.name + //del(xeno_mind) spawnpos++ spawn (rand(waittime_l, waittime_h)) send_intercept() - return ..() \ No newline at end of file + return ..() + +/datum/game_mode/xenos/process() + checkwin_counter++ + if(checkwin_counter >= 5) + if(!result) + ticker.mode.check_win() + checkwin_counter = 0 + return 0 + + +/datum/game_mode/xenos/check_win() + var/xenosalive = xenos_alive() + var/playersalive = players_alive() + var/playeralienratio = 0 + if(playersalive) + playeralienratio = xenosalive / playersalive + if(emergency_shuttle && emergency_shuttle.returned()) + return ..() + if(!xenosalive) + result = 1 + return 1 + else if(!playersalive) + result = 2 + return 1 + else if(station_was_nuked) + result = 3 + return 1 + else + if(playeralienratio >= gammaratio && !gammacalled) + gammacalled = 1 + command_alert("The aliens have nearly succeeded in capturing the station and exterminating the crew. Activate the nuclear failsafe to stop the alien threat once and for all. The Nuclear Authentication Code is [get_nuke_code()] ", "Alien Lifeform Alert") + set_security_level("gamma") + var/obj/machinery/door/airlock/vault/V = locate(/obj/machinery/door/airlock/vault) in world + if(V && V.z == 1) + V.locked = 0 + V.update_icon() + return ..() + +/datum/game_mode/xenos/check_finished() + if(config.continous_rounds) + if(result) + return ..() + if(emergency_shuttle && emergency_shuttle.returned()) + return ..() + if(result || station_was_nuked) + return 1 + else + return 0 + +/datum/game_mode/xenos/proc/get_nuke_code() + var/nukecode = "ERROR" + for(var/obj/machinery/nuclearbomb/bomb in world) + if(bomb && bomb.r_code && bomb.z == 1) + nukecode = bomb.r_code + return nukecode + +/datum/game_mode/xenos/proc/xenos_alive() + var/list/livingxenos = list() + for(var/datum/mind/xeno in xenos) + if((xeno) && (xeno.current) && (xeno.current.stat != 2) && (xeno.current.client)) + if(istype(xeno.current,/mob/living/carbon/alien) || (xenoborg && isrobot(xeno.current)) || (xenoai && isAI(xeno.current))) + livingxenos += xeno + return livingxenos.len + +/datum/game_mode/xenos/proc/players_alive() + var/list/livingplayers = list() + for(var/mob/M in player_list) + var/turf/T = get_turf(M) + if((M) && (M.stat != 2) && M.client && T && (T.z == 1 || emergency_shuttle.departed && (T.z == 1 || T.z == 2))) + if(ishuman(M)) + livingplayers += 1 + return livingplayers.len + +/datum/game_mode/xenos/declare_completion() + if(station_was_nuked) + feedback_set_details("round_end_result","win - xenos nuked") + world << "Crew Victory" + world << "The station was destroyed in a nuclear explosion, preventing the aliens from overrunning it!" + else if(result == 1) + feedback_set_details("round_end_result","win - xenos killed") + world << "Crew Victory" + world << "The aliens did not succeed and were exterminated by the crew!" + else if(result == 2) + feedback_set_details("round_end_result","win - crew killed") + world << "Alien Victory" + world << "The aliens were successful and slaughtered the crew!" + else + feedback_set_details("round_end_result","win - crew escaped") + world << "Draw" + world << "The crew has escaped from the aliens but did not exterminate them, allowing them to overrun the station." + + var/text = "
There were [xenos.len] aliens." + text += "
The aliens were:" + for(var/datum/mind/xeno in xenos) + text += "
[xeno.key] was [xeno.name] (" + if(xeno.current) + if(xeno.current.stat == DEAD) + text += "died" + else if(!xeno.current.client) + text += "SSD" + else + text += "survived" + else + text += "body destroyed" + text += ")" + world << text + + ..() + return 1 \ No newline at end of file diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index 9e36b891c30..86390d70e15 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -71,7 +71,10 @@ /var/const/access_salvage_captain = 69 // Salvage ship captain's quarters /var/const/access_mechanic = 70 /var/const/access_pilot = 71 - +/var/const/access_ntrec = 72 +/var/const/access_ntrep = 73 +/var/const/access_magistrate = 74 +/var/const/access_minisat = 75 /var/const/access_weapons = 99 //Weapon authorization for secbots @@ -235,7 +238,7 @@ access_theatre, access_research, access_mining, access_mailsorting, access_heads_vault, access_mining_station, access_xenobiology, access_ce, access_hop, access_hos, access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_paramedic, access_blueshield, access_customs, access_mechanic,access_weapons, - access_pilot) + access_pilot, access_ntrec, access_ntrep, access_magistrate, access_minisat) /proc/get_all_centcom_access() return list(access_cent_general, access_cent_thunder, access_cent_specops, access_cent_medical, access_cent_living, access_cent_storage, access_cent_teleporter, access_cent_creed, access_cent_captain) @@ -248,17 +251,17 @@ if(0) return get_all_accesses() if(1) //security - return list(access_sec_doors, access_security, access_brig, access_armory, access_forensics_lockers, access_court, access_hos) + return list(access_sec_doors, access_security, access_brig, access_armory, access_forensics_lockers, access_court, access_customs, access_pilot, access_hos) if(2) //medbay return list(access_medical, access_genetics, access_morgue, access_chemistry, access_psychiatrist, access_virology, access_surgery, access_cmo, access_paramedic) if(3) //research - return list(access_research, access_tox, access_tox_storage, access_robotics, access_xenobiology, access_xenoarch, access_rd) + return list(access_research, access_tox, access_tox_storage, access_robotics, access_xenobiology, access_xenoarch, access_minisat, access_rd) if(4) //engineering and maintenance - return list(access_construction, access_maint_tunnels, access_engine, access_engine_equip, access_external_airlocks, access_tech_storage, access_atmospherics, access_ce, access_mechanic) + return list(access_construction, access_maint_tunnels, access_engine, access_engine_equip, access_external_airlocks, access_tech_storage, access_atmospherics, access_minisat, access_ce, access_mechanic) if(5) //command - return list(access_heads, access_RC_announce, access_keycard_auth, access_change_ids, access_ai_upload, access_teleporter, access_eva, access_tcomsat, access_gateway, access_all_personal_lockers, access_heads_vault, access_hop, access_captain, access_blueshield, access_customs) + return list(access_heads, access_RC_announce, access_keycard_auth, access_change_ids, access_ai_upload, access_teleporter, access_eva, access_tcomsat, access_gateway, access_all_personal_lockers, access_heads_vault, access_blueshield, access_ntrec, access_ntrep, access_hop, access_captain) if(6) //station general - return list(access_kitchen,access_bar, access_hydroponics, access_janitor, access_chapel_office, access_crematorium, access_library, access_theatre, access_lawyer, access_clown, access_mime) + return list(access_kitchen,access_bar, access_hydroponics, access_janitor, access_chapel_office, access_crematorium, access_library, access_theatre, access_lawyer, access_magistrate, access_clown, access_mime) if(7) //supply return list(access_mailsorting, access_mining, access_mining_station, access_cargo, access_qm) @@ -416,12 +419,22 @@ return "Brig" if(access_blueshield) return "Blueshield" + if(access_ntrec) + return "Nanotrasen Recruiter" + if(access_ntrep) + return "Nanotrasen Rep." if(access_paramedic) return "Paramedic" if(access_customs) return "Customs" if(access_mechanic) return "Mechanic Workshop" + if(access_pilot) + return "Security Pod Pilot" + if(access_magistrate) + return "Magistrate" + if(access_minisat) + return "AI Satellite" if(access_weapons) return "Weapon Permit" diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm index 991f04f86a6..71a8332239b 100644 --- a/code/game/jobs/job/engineering.dm +++ b/code/game/jobs/job/engineering.dm @@ -11,11 +11,11 @@ access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva, access_heads, access_construction, access_sec_doors, - access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload) + access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_minisat, access_mechanic) minimal_access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels, access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva, access_heads, access_construction, access_sec_doors, - access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload, access_mechanic) + access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_minisat, access_mechanic) minimal_player_age = 21 diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm index b62b846dae1..876dca62e30 100644 --- a/code/game/jobs/job/medical.dm +++ b/code/game/jobs/job/medical.dm @@ -48,7 +48,7 @@ selection_color = "#ffeef0" access = list(access_medical, access_morgue, access_surgery, access_chemistry, access_virology, access_genetics) minimal_access = list(access_medical, access_morgue, access_surgery, access_maint_tunnels) - alt_titles = list("Surgeon","Nurse","Mortician") + alt_titles = list("Surgeon","Nurse","Coroner") minimal_player_age = 3 equip(var/mob/living/carbon/human/H) @@ -60,10 +60,11 @@ if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) if (H.mind.role_alt_title) switch(H.mind.role_alt_title) - if("Mortician") + if("Coroner") H.equip_or_collect(new /obj/item/clothing/under/rank/medical/mortician(H), slot_w_uniform) H.equip_or_collect(new /obj/item/clothing/suit/storage/labcoat/mortician(H), slot_wear_suit) if(H.backbag != 1) + H.equip_or_collect(new /obj/item/clothing/head/surgery/black(H.back), slot_in_backpack) H.equip_or_collect(new /obj/item/weapon/autopsy_scanner(H.back), slot_in_backpack) H.equip_or_collect(new /obj/item/device/mass_spectrometer(H.back), slot_in_backpack) H.equip_or_collect(new /obj/item/weapon/storage/box/bodybags(H.back), slot_in_backpack) diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm index ae02acbf195..177bc7ecfc2 100644 --- a/code/game/jobs/job/science.dm +++ b/code/game/jobs/job/science.dm @@ -11,11 +11,11 @@ access = list(access_rd, access_heads, access_tox, access_genetics, access_morgue, access_tox_storage, access_tech_storage, access_teleporter, access_sec_doors, access_research, access_robotics, access_xenobiology, access_ai_upload, - access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch) + access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_minisat) minimal_access = list(access_eva, access_rd, access_heads, access_tox, access_genetics, access_morgue, access_tox_storage, access_tech_storage, access_teleporter, access_sec_doors, access_research, access_robotics, access_xenobiology, access_ai_upload, - access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_maint_tunnels) + access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_minisat, access_maint_tunnels) minimal_player_age = 21 // All science-y guys get bonuses for maxing out their tech. @@ -52,7 +52,7 @@ selection_color = "#ffeeff" access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology, access_xenoarch) minimal_access = list(access_tox, access_tox_storage, access_research, access_xenoarch, access_maint_tunnels) - alt_titles = list("Xenoarcheologist", "Anomalist", "Plasma Researcher") + alt_titles = list("Xenoarcheologist", "Anomalist", "Plasma Researcher", "Xenobotanist") minimal_player_age = 3 // All science-y guys get bonuses for maxing out their tech. diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm index cb576e4f8e2..51062f1c309 100644 --- a/code/game/jobs/job/security.dm +++ b/code/game/jobs/job/security.dm @@ -9,13 +9,13 @@ idtype = /obj/item/weapon/card/id/silver req_admin_notify = 1 access = list(access_security, access_sec_doors, access_brig, access_armory, access_court, - access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers, + access_forensics_lockers, access_customs, access_pilot, access_morgue, access_maint_tunnels, access_all_personal_lockers, access_research, access_engine, access_mining, access_medical, access_construction, access_mailsorting, access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_weapons) minimal_access = list(access_eva, access_security, access_sec_doors, access_brig, access_armory, access_court, access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers, access_research, access_engine, access_mining, access_medical, access_construction, access_mailsorting, - access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_customs,access_weapons) + access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_customs, access_pilot, access_weapons) minimal_player_age = 21 equip(var/mob/living/carbon/human/H) @@ -30,8 +30,7 @@ H.equip_or_collect(new /obj/item/clothing/suit/armor/hos(H), slot_wear_suit) H.equip_or_collect(new /obj/item/device/pda/heads/hos(H), slot_wear_pda) H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) - H.equip_or_collect(new /obj/item/clothing/head/helmet/HoS(H), slot_head) -// H.equip_or_collect(new /obj/item/clothing/mask/gas(H), slot_wear_mask) //Grab one from the armory you donk + H.equip_or_collect(new /obj/item/clothing/head/HoS(H), slot_head) H.equip_or_collect(new /obj/item/clothing/glasses/sunglasses/sechud(H), slot_glasses) H.equip_or_collect(new /obj/item/weapon/gun/energy/gun(H), slot_s_store) if(H.backbag == 1) @@ -72,11 +71,14 @@ if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) H.equip_or_collect(new /obj/item/clothing/under/rank/warden(H), slot_w_uniform) H.equip_or_collect(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) + H.equip_or_collect(new /obj/item/clothing/suit/armor/vest/warden(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/clothing/head/warden(H), slot_head) H.equip_or_collect(new /obj/item/device/pda/warden(H), slot_wear_pda) H.equip_or_collect(new /obj/item/clothing/gloves/black(H), slot_gloves) H.equip_or_collect(new /obj/item/clothing/glasses/sunglasses/sechud(H), slot_glasses) // H.equip_or_collect(new /obj/item/clothing/mask/gas(H), slot_wear_mask) //Grab one from the armory you donk H.equip_or_collect(new /obj/item/device/flash(H), slot_l_store) + H.equip_or_collect(new /obj/item/weapon/gun/energy/advtaser(H), slot_s_store) if(H.backbag == 1) H.equip_or_collect(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) H.equip_or_collect(new /obj/item/weapon/handcuffs(H), slot_l_hand) @@ -104,7 +106,7 @@ alt_titles = list("Forensic Technician") access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_court, access_weapons) - minimal_access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_court, access_weapons) + minimal_access = list(access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_court, access_weapons) alt_titles = list("Forensic Technician") minimal_player_age = 14 equip(var/mob/living/carbon/human/H) @@ -136,6 +138,7 @@ H.equip_or_collect(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack) H.equip_or_collect(new /obj/item/weapon/storage/box/evidence(H), slot_in_backpack) H.equip_or_collect(new /obj/item/device/detective_scanner(H), slot_in_backpack) + H.equip_or_collect(new /obj/item/weapon/melee/telebaton(H.back), slot_in_backpack) var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H) L.imp_in = H L.implanted = 1 @@ -170,8 +173,10 @@ if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) H.equip_or_collect(new /obj/item/clothing/under/rank/security(H), slot_w_uniform) H.equip_or_collect(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) + H.equip_or_collect(new /obj/item/clothing/suit/armor/vest/security(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/clothing/head/soft/sec(H), slot_head) H.equip_or_collect(new /obj/item/device/pda/security(H), slot_wear_pda) - H.equip_or_collect(new /obj/item/weapon/handcuffs(H), slot_s_store) + H.equip_or_collect(new /obj/item/weapon/gun/energy/advtaser(H), slot_s_store) H.equip_or_collect(new /obj/item/device/flash(H), slot_l_store) if(H.backbag == 1) H.equip_or_collect(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) @@ -208,9 +213,9 @@ if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) H.equip_or_collect(new /obj/item/clothing/under/fluff/milo_hachert(H), slot_w_uniform) H.equip_or_collect(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) - H.equip_or_collect(new /obj/item/clothing/head/helmet/customs(H), slot_head) + H.equip_or_collect(new /obj/item/clothing/head/customs(H), slot_head) H.equip_or_collect(new /obj/item/device/pda/security(H), slot_wear_pda) - H.equip_or_collect(new /obj/item/weapon/handcuffs(H), slot_s_store) + H.equip_or_collect(new /obj/item/weapon/gun/energy/advtaser(H), slot_s_store) H.equip_or_collect(new /obj/item/device/flash(H), slot_l_store) H.equip_or_collect(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack) H.equip_or_collect(new /obj/item/weapon/stamp(H), slot_in_backpack) @@ -279,10 +284,10 @@ if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_sec(H), slot_back) if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back) H.equip_or_collect(new /obj/item/clothing/under/rank/security(H), slot_w_uniform) - H.equip_or_collect(new /obj/item/clothing/suit/bomber(H), slot_wear_suit) + H.equip_or_collect(new /obj/item/clothing/suit/jacket(H), slot_wear_suit) H.equip_or_collect(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) H.equip_or_collect(new /obj/item/device/pda/security(H), slot_wear_pda) - H.equip_or_collect(new /obj/item/weapon/handcuffs(H), slot_s_store) + H.equip_or_collect(new /obj/item/weapon/gun/energy/advtaser(H), slot_belt) H.equip_or_collect(new /obj/item/device/flash(H), slot_l_store) if(H.backbag == 1) H.equip_or_collect(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) diff --git a/code/game/jobs/job/silicon.dm b/code/game/jobs/job/silicon.dm index 75c8555aca1..701b5133891 100644 --- a/code/game/jobs/job/silicon.dm +++ b/code/game/jobs/job/silicon.dm @@ -20,7 +20,7 @@ flag = CYBORG department_flag = ENGSEC total_positions = 0 - spawn_positions = 2 + spawn_positions = 1 supervisors = "your laws and the AI" //Nodrak selection_color = "#ddffdd" minimal_player_age = 21 diff --git a/code/game/jobs/job/supervisor.dm b/code/game/jobs/job/supervisor.dm index 21ba6fb0376..bdc080095b2 100644 --- a/code/game/jobs/job/supervisor.dm +++ b/code/game/jobs/job/supervisor.dm @@ -101,23 +101,23 @@ selection_color = "#ddddff" idtype = /obj/item/weapon/card/id/centcom req_admin_notify = 1 - minimal_player_age = 10 + minimal_player_age = 21 access = list(access_security, access_sec_doors, access_brig, access_court, access_forensics_lockers, - access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads, + access_medical, access_engine, access_change_ids, access_eva, access_heads, access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue, access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer, access_theatre, access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station, - access_clown, access_mime, access_hop, access_RC_announce, access_keycard_auth, access_gateway) + access_clown, access_mime, access_hop, access_RC_announce, access_keycard_auth, access_gateway, access_weapons, access_ntrep) minimal_access = list(access_security, access_sec_doors, access_brig, access_court, access_forensics_lockers, - access_medical, access_engine, access_ai_upload, access_eva, access_heads, + access_medical, access_engine, access_eva, access_heads, access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue, access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer, access_theatre, access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station, - access_clown, access_mime, access_hop, access_RC_announce, access_keycard_auth, access_gateway) + access_clown, access_mime, access_hop, access_RC_announce, access_keycard_auth, access_gateway, access_weapons, access_ntrep) equip(var/mob/living/carbon/human/H) if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/heads/hop(H), slot_l_ear) + H.equip_or_collect(new /obj/item/device/radio/headset/heads/ntrep(H), slot_l_ear) switch(H.backbag) if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) @@ -127,7 +127,7 @@ H.equip_or_collect(new /obj/item/weapon/lighter/zippo/fluff/nt_rep(H.back), slot_in_backpack) H.equip_if_possible(new /obj/item/clothing/under/rank/centcom/representative(H), slot_w_uniform) H.equip_if_possible(new /obj/item/clothing/shoes/centcom(H), slot_shoes) - H.equip_or_collect(new /obj/item/device/pda/heads/hop(H), slot_wear_pda) + H.equip_or_collect(new /obj/item/device/pda/heads/ntrep(H), slot_wear_pda) var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H) L.imp_in = H L.implanted = 1 @@ -146,23 +146,23 @@ selection_color = "#ddddff" idtype = /obj/item/weapon/card/id/centcom req_admin_notify = 1 - minimal_player_age = 10 + minimal_player_age = 21 access = list(access_security, access_sec_doors, access_brig, access_court, access_forensics_lockers, access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads, access_change_ids, access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue, access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer, access_theatre, access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station, - access_clown, access_mime, access_hop, access_RC_announce, access_keycard_auth, access_gateway) + access_clown, access_mime, access_hop, access_RC_announce, access_keycard_auth, access_gateway, access_ntrec) minimal_access = list(access_security, access_sec_doors, access_brig, access_court, access_forensics_lockers, access_medical, access_engine, access_ai_upload, access_eva, access_heads, access_change_ids, access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue, access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer, access_theatre, access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station, - access_clown, access_mime, access_hop, access_RC_announce, access_keycard_auth, access_gateway) + access_clown, access_mime, access_hop, access_RC_announce, access_keycard_auth, access_gateway, access_ntrec) equip(var/mob/living/carbon/human/H) if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/heads/hop(H), slot_l_ear) + H.equip_or_collect(new /obj/item/device/radio/headset/heads/ntrec(H), slot_l_ear) switch(H.backbag) if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) @@ -171,7 +171,7 @@ H.equip_or_collect(new /obj/item/weapon/lighter/zippo/fluff/nt_rep(H.back), slot_in_backpack) H.equip_if_possible(new /obj/item/clothing/under/rank/centcom/representative(H), slot_w_uniform) H.equip_if_possible(new /obj/item/clothing/shoes/centcom(H), slot_shoes) - H.equip_or_collect(new /obj/item/device/pda/heads/hop(H), slot_wear_pda) + H.equip_or_collect(new /obj/item/device/pda/heads/ntrec(H), slot_wear_pda) var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H) L.imp_in = H L.implanted = 1 @@ -190,9 +190,9 @@ selection_color = "#ddddff" idtype = /obj/item/weapon/card/id/centcom req_admin_notify = 1 - minimal_player_age = 10 + minimal_player_age = 21 access = list(access_security, access_sec_doors, access_brig, access_court, access_forensics_lockers, - access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads, + access_medical, access_engine, access_change_ids, access_eva, access_heads, access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue, access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer, access_theatre, access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station, @@ -206,7 +206,7 @@ equip(var/mob/living/carbon/human/H) if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/heads/hop(H), slot_l_ear) + H.equip_or_collect(new /obj/item/device/radio/headset/heads/blueshield(H), slot_l_ear) switch(H.backbag) if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack/security(H), slot_back) if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) @@ -215,9 +215,10 @@ H.equip_or_collect(new /obj/item/clothing/gloves/combat(H), slot_gloves) H.equip_or_collect(new /obj/item/clothing/shoes/jackboots(H), slot_shoes) H.equip_or_collect(new /obj/item/clothing/glasses/hud/health_advanced, slot_glasses) - H.equip_if_possible(new /obj/item/clothing/under/rank/centcom/representative(H), slot_w_uniform) + H.equip_if_possible(new /obj/item/clothing/under/rank/centcom/blueshield(H), slot_w_uniform) H.equip_if_possible(new /obj/item/clothing/suit/armor/vest/fluff/deus_blueshield(H), slot_wear_suit) - H.equip_or_collect(new /obj/item/device/pda/heads/hop(H), slot_wear_pda) + H.equip_or_collect(new /obj/item/weapon/gun/energy/advtaser(H), slot_s_store) + H.equip_or_collect(new /obj/item/device/pda/heads/blueshield(H), slot_wear_pda) if(H.backbag == 1) H.equip_or_collect(new /obj/item/weapon/storage/box/deathimp(H), slot_r_hand) else @@ -240,18 +241,18 @@ selection_color = "#ddddff" idtype = /obj/item/weapon/card/id/centcom req_admin_notify = 1 - minimal_player_age = 10 + minimal_player_age = 21 access = list(access_security, access_sec_doors, access_brig, access_court, access_forensics_lockers, - access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads, + access_medical, access_engine, access_change_ids, access_eva, access_heads, access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue, access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer, access_theatre, access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station, - access_clown, access_mime, access_hop, access_RC_announce, access_keycard_auth, access_gateway) - minimal_access = list(access_security, access_sec_doors, access_brig, access_court, access_maint_tunnels, access_lawyer) + access_clown, access_mime, access_hop, access_RC_announce, access_keycard_auth, access_gateway, access_magistrate) + minimal_access = list(access_security, access_sec_doors, access_brig, access_court, access_maint_tunnels, access_lawyer, access_magistrate) equip(var/mob/living/carbon/human/H) if(!H) return 0 - H.equip_or_collect(new /obj/item/device/radio/headset/heads/hop(H), slot_l_ear) + H.equip_or_collect(new /obj/item/device/radio/headset/heads/magistrate(H), slot_l_ear) switch(H.backbag) if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back) if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back) @@ -261,7 +262,8 @@ H.equip_if_possible(new /obj/item/clothing/suit/judgerobe(H), slot_wear_suit) H.equip_if_possible(new /obj/item/clothing/shoes/centcom(H), slot_shoes) H.equip_or_collect(new /obj/item/clothing/head/powdered_wig(H), slot_head) - H.equip_or_collect(new /obj/item/device/pda/heads/hop(H), slot_wear_pda) + H.equip_or_collect(new /obj/item/clothing/glasses/sunglasses/sechud(H), slot_glasses) + H.equip_or_collect(new /obj/item/device/pda/heads/magistrate(H), slot_wear_pda) var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H) L.imp_in = H L.implanted = 1 diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm index 020a952925c..6c25f2e2d04 100644 --- a/code/game/jobs/job/support.dm +++ b/code/game/jobs/job/support.dm @@ -263,7 +263,7 @@ H.equip_or_collect(new /obj/item/device/radio/headset/headset_service(H), slot_l_ear) H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes) H.equip_or_collect(new /obj/item/device/pda/mime(H), slot_wear_pda) - H.equip_or_collect(new /obj/item/clothing/gloves/white(H), slot_gloves) + H.equip_or_collect(new /obj/item/clothing/gloves/color/white(H), slot_gloves) H.equip_or_collect(new /obj/item/clothing/head/beret(H), slot_head) H.equip_or_collect(new /obj/item/clothing/suit/suspenders(H), slot_wear_suit) if(H.backbag == 1) diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm index 36984e5c314..837759072ed 100644 --- a/code/game/machinery/OpTable.dm +++ b/code/game/machinery/OpTable.dm @@ -73,7 +73,7 @@ /obj/machinery/optable/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) - if(usr.stat || !ishuman(usr) || usr.restrained() || !check_table(usr)) + if(usr.stat || !ishuman(usr) || usr.restrained() || !check_table(usr) || usr.weakened || usr.stunned) return var/mob/living/L = O diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index 3a510151f20..7afabaa849d 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -36,7 +36,7 @@ _color = "blue" can_label = 0 /obj/machinery/portable_atmospherics/canister/toxins - name = "Canister \[Toxin (Bio)\]" + name = "Canister \[Toxin (Plasma)\]" icon_state = "orange" _color = "orange" can_label = 0 @@ -252,6 +252,9 @@ update_flag /obj/machinery/portable_atmospherics/canister/attack_paw(var/mob/user as mob) return src.attack_hand(user) + +/obj/machinery/portable_atmospherics/canister/attack_alien(mob/living/carbon/alien/humanoid/user) + return /obj/machinery/portable_atmospherics/canister/attack_hand(var/mob/user as mob) return src.ui_interact(user) @@ -333,7 +336,7 @@ update_flag "\[N2O\]" = "redws", \ "\[N2\]" = "red", \ "\[O2\]" = "blue", \ - "\[Toxin (Bio)\]" = "orange", \ + "\[Toxin (Plasma)\]" = "orange", \ "\[CO2\]" = "black", \ "\[Air\]" = "grey", \ "\[CAUTION\]" = "yellow", \ diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index cb9e2d89985..ccf95a5b417 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -1,73 +1,3 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 - -var/global/list/autolathe_recipes = list( \ - new /obj/item/stack/sheet/metal(), \ - new /obj/item/stack/sheet/glass(), \ - new /obj/item/stack/sheet/rglass(), \ - new /obj/item/stack/sheet/fur(), \ - new /obj/item/stack/rods(), \ - new /obj/item/weapon/crowbar(), \ - new /obj/item/weapon/screwdriver(), \ - new /obj/item/weapon/weldingtool(), \ - new /obj/item/weapon/wirecutters(), \ - new /obj/item/weapon/wrench(), \ - new /obj/item/device/multitool(), \ - new /obj/item/device/analyzer(), \ - new /obj/item/device/t_scanner(), \ - new /obj/item/device/flashlight(), \ - new /obj/item/weapon/extinguisher(), \ - new /obj/item/clothing/head/welding(), \ - new /obj/item/weapon/stock_parts/console_screen(), \ - new /obj/item/weapon/airlock_electronics(), \ - new /obj/item/weapon/airalarm_electronics(), \ - new /obj/item/weapon/firealarm_electronics(), \ - new /obj/item/weapon/kitchenknife(), \ - new /obj/item/weapon/scalpel(), \ - new /obj/item/weapon/circular_saw(), \ - new /obj/item/weapon/surgicaldrill(),\ - new /obj/item/weapon/retractor(),\ - new /obj/item/weapon/cautery(),\ - new /obj/item/weapon/hemostat(),\ - new /obj/item/weapon/reagent_containers/glass/beaker(), \ - new /obj/item/weapon/reagent_containers/glass/beaker/large(), \ - new /obj/item/weapon/reagent_containers/glass/bucket(), \ - new /obj/item/device/taperecorder(), \ - new /obj/item/device/assembly/igniter(), \ - new /obj/item/device/assembly/signaler(), \ - new /obj/item/device/radio/headset(), \ - new /obj/item/device/radio/off(), \ - new /obj/item/device/assembly/infra(), \ - new /obj/item/device/assembly/timer(), \ - new /obj/item/device/assembly/prox_sensor(), \ - new /obj/item/device/assembly/voice(), \ - new /obj/item/weapon/light/tube(), \ - new /obj/item/weapon/light/bulb(), \ - new /obj/item/weapon/camera_assembly(), \ - new /obj/item/weapon/rcd_ammo(), \ - new /obj/item/ammo_casing/shotgun/beanbag(), \ - new /obj/item/ammo_box/c38(), \ - new /obj/item/clothing/ears/earmuffs/tribblemuffs(), \ - new /obj/item/clothing/gloves/furgloves(), \ - new /obj/item/clothing/head/furcap(), \ - new /obj/item/clothing/shoes/furboots(), \ - new /obj/item/clothing/suit/furcoat(), \ - new /obj/item/clothing/suit/furcape(), \ - ) - -var/global/list/autolathe_recipes_hidden = list( \ - new /obj/item/weapon/flamethrower/full(), \ - new /obj/item/weapon/rcd(), \ - new /obj/item/device/radio/electropack(), \ - new /obj/item/weapon/weldingtool/largetank(), \ - new /obj/item/weapon/handcuffs(), \ - new /obj/item/weapon/hatchet(), \ - new /obj/item/ammo_box/a357(), \ - new /obj/item/ammo_casing/shotgun(), \ - new /obj/item/ammo_casing/shotgun/buck(), \ - new /obj/item/ammo_casing/shotgun/incendiary(), \ - /*new /obj/item/ammo_casing/shotgun/dart(), \ - new /obj/item/weapon/shield/riot(), */ \ - ) /obj/machinery/autolathe name = "autolathe" desc = "It produces items using metal and glass." @@ -80,18 +10,13 @@ var/global/list/autolathe_recipes_hidden = list( \ var/g_amount = 0.0 var/max_g_amount = 75000.0 - var/f_amount = 0.0 - var/max_f_amount = 50000.0 - var/operating = 0.0 - var/opened = 0.0 anchored = 1.0 var/list/L = list() var/list/LL = list() var/hacked = 0 var/disabled = 0 var/shocked = 0 - var/list/wires = list() var/hack_wire var/disable_wire var/shock_wire @@ -100,70 +25,278 @@ var/global/list/autolathe_recipes_hidden = list( \ active_power_usage = 100 var/busy = 0 var/prod_coeff + var/datum/wires/autolathe/wires = null - l_color = "#7BF9FF" - power_change() - ..() - if(!(stat & (BROKEN|NOPOWER))) - SetLuminosity(2) - else - SetLuminosity(0) + var/datum/design/being_built + var/datum/research/files + var/selected_category + var/screen = 1 + + var/list/categories = list( + "Communication", + "Construction", + "Electronics", + "Medical", + "Miscellaneous", + "Security", + "Tools" + ) /obj/machinery/autolathe/New() ..() component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/autolathe(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/console_screen(src) + component_parts += new /obj/item/weapon/circuitboard/autolathe(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + component_parts += new /obj/item/weapon/stock_parts/console_screen(null) RefreshParts() wires = new(src) - src.L = autolathe_recipes - src.LL = autolathe_recipes_hidden + files = new /datum/research/autolathe(src) -/obj/machinery/autolathe/proc/wires_win(mob/user as mob) - var/dat as text - dat += "Autolathe Wires:
" - for(var/wire in src.wires) - dat += text("[wire] Wire: [src.wires[wire] ? "Mend" : "Cut"] Pulse
") +/obj/machinery/autolathe/interact(mob/user) + if(shocked && !(stat & NOPOWER)) + shock(user,50) - dat += text("The red light is [src.disabled ? "off" : "on"].
") - dat += text("The green light is [src.shocked ? "off" : "on"].
") - dat += text("The blue light is [src.hacked ? "off" : "on"].
") - user << browse("Autolathe Hacking[dat]","window=autolathe_hack") - onclose(user, "autolathe_hack") + user.set_machine(src) + var/dat -/obj/machinery/autolathe/proc/regular_win(mob/user as mob) - var/coeff = 2 ** prod_coeff - var/dat as text - dat = text("Metal Amount: [src.m_amount] cm3 (MAX: [max_m_amount])
\nGlass Amount: [src.g_amount] cm3 (MAX: [max_g_amount])
\nFur Amount: [src.f_amount] cm3 (MAX: [max_f_amount])
") - var/list/objs = list() - objs += src.L - if (src.hacked) - objs += src.LL - for(var/obj/t in objs) - var/title = "[t.name] ([t.m_amt/coeff] m / [t.g_amt/coeff] g / [t.f_amt/coeff] f)" - if (m_amount" + if(panel_open) + dat = wires.GetInteractWindow() + + else + if(screen == 1) + dat = main_win(user) + else + dat += category_win(user,selected_category) + + var/datum/browser/popup = new(user, "autolathe", name, 500, 500) + popup.set_content(dat) + popup.open() + + return + +/obj/machinery/autolathe/attackby(obj/item/O, mob/user) + if (busy) + user << "The autolathe is busy. Please wait for completion of previous operation." + return 1 + + if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", O)) + updateUsrDialog() + return + + if(exchange_parts(user, O)) + return + + if (panel_open) + if(istype(O, /obj/item/weapon/crowbar)) + if(m_amount >= MINERAL_MATERIAL_AMOUNT) + var/obj/item/stack/sheet/metal/G = new /obj/item/stack/sheet/metal(src.loc) + G.amount = round(m_amount / MINERAL_MATERIAL_AMOUNT) + if(g_amount >= MINERAL_MATERIAL_AMOUNT) + var/obj/item/stack/sheet/glass/G = new /obj/item/stack/sheet/glass(src.loc) + G.amount = round(g_amount / MINERAL_MATERIAL_AMOUNT) + default_deconstruction_crowbar(O) + return 1 + else + attack_hand(user) + return 1 + if (stat) + return 1 + + if (src.m_amount + O.m_amt > max_m_amount) + user << "The autolathe is full. Please remove metal from the autolathe in order to insert more." + return 1 + if (src.g_amount + O.g_amt > max_g_amount) + user << "The autolathe is full. Please remove glass from the autolathe in order to insert more." + return 1 + if (O.m_amt == 0 && O.g_amt == 0) + user << "This object does not contain significant amounts of metal or glass, or cannot be accepted by the autolathe due to size or hazardous materials." + return 1 + + var/amount = 1 + var/obj/item/stack/stack + var/m_amt = O.m_amt + var/g_amt = O.g_amt + if (istype(O, /obj/item/stack)) + stack = O + amount = stack.amount + if (m_amt) + amount = min(amount, round((max_m_amount-src.m_amount)/m_amt)) + flick("autolathe_o",src)//plays metal insertion animation + if (g_amt) + amount = min(amount, round((max_g_amount-src.g_amount)/g_amt)) + flick("autolathe_r",src)//plays glass insertion animation + stack.use(amount) + else + if(!user.before_take_item(O)) + user << "/the [O] is stuck to your hand, you can't put it in \the [src]!" + O.loc = src + icon_state = "autolathe" + busy = 1 + use_power(max(1000, (m_amt+g_amt)*amount/10)) + src.m_amount += m_amt * amount + src.g_amount += g_amt * amount + user << "You insert [amount] sheet[amount>1 ? "s" : ""] to the autolathe." + if (O && O.loc == src) + qdel(O) + busy = 0 + src.updateUsrDialog() + +/obj/machinery/autolathe/attack_paw(mob/user) + return attack_hand(user) + +/obj/machinery/autolathe/attack_hand(mob/user) + if(..(user, 0)) + return + interact(user) + +/obj/machinery/autolathe/Topic(href, href_list) + if(..()) + return + if (!busy) + if(href_list["menu"]) + screen = text2num(href_list["menu"]) + + if(href_list["category"]) + selected_category = href_list["category"] + + if(href_list["make"]) + + var/turf/T = get_step(src.loc, get_dir(src,usr)) + + ///////////////// + //href protection + being_built = files.FindDesignByID(href_list["make"]) //check if it's a valid design + if(!being_built) + return + + //multiplier checks : only stacks can have one and its value is 1, 10 ,25 or max_multiplier + var/multiplier = text2num(href_list["multiplier"]) + var/max_multiplier = min(50, being_built.materials["$metal"] ?round(m_amount/being_built.materials["$metal"]):INFINITY,being_built.materials["$glass"]?round(g_amount/being_built.materials["$glass"]):INFINITY) + var/is_stack = ispath(being_built.build_path, /obj/item/stack) + + if(!is_stack && (multiplier > 1)) + return + if (!(multiplier in list(1,10,25,max_multiplier))) //"enough materials ?" is checked further down + return + ///////////////// + + var/coeff = (is_stack ? 1 : 2 ** prod_coeff) //stacks are unaffected by production coefficient + var/metal_cost = being_built.materials["$metal"] + var/glass_cost = being_built.materials["$glass"] + + var/power = max(2000, (metal_cost+glass_cost)*multiplier/5) + + if((m_amount >= metal_cost*multiplier/coeff) && (g_amount >= glass_cost*multiplier/coeff)) + busy = 1 + use_power(power) + icon_state = "autolathe" + flick("autolathe_n",src) + spawn(32/coeff) + use_power(power) + if(is_stack) + m_amount -= metal_cost*multiplier + g_amount -= glass_cost*multiplier + var/obj/item/stack/S = new being_built.build_path(T) + S.amount = multiplier + else + m_amount -= metal_cost/coeff + g_amount -= glass_cost/coeff + var/obj/item/new_item = new being_built.build_path(T) + new_item.m_amt /= coeff + new_item.g_amt /= coeff + if(m_amount < 0) + m_amount = 0 + if(g_amount < 0) + g_amount = 0 + busy = 0 + src.updateUsrDialog() + else + usr << "The autolathe is busy. Please wait for completion of previous operation." + + src.updateUsrDialog() + + return + +/obj/machinery/autolathe/RefreshParts() + var/tot_rating = 0 + prod_coeff = 0 + for(var/obj/item/weapon/stock_parts/matter_bin/MB in component_parts) + tot_rating += MB.rating + tot_rating *= 25000 + max_m_amount = tot_rating * 2 + max_g_amount = tot_rating + for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) + prod_coeff += M.rating - 1 + +/obj/machinery/autolathe/proc/main_win(mob/user) + var/dat = "

Autolathe Menu:


" + dat += "Metal amount: [src.m_amount] / [max_m_amount] cm3
" + dat += "Glass amount: [src.g_amount] / [max_g_amount] cm3
" + + var/line_length = 1 + dat += "" + + for(var/C in categories) + if(line_length > 2) + dat += "" + line_length = 1 + + dat += "" + line_length++ + + dat += "
[C]
" + return dat + +/obj/machinery/autolathe/proc/category_win(mob/user,var/selected_category) + var/dat = "Return to category screen" + dat += "

Browsing [selected_category]:


" + dat += "Metal amount: [src.m_amount] / [max_m_amount] cm3
" + dat += "Glass amount: [src.g_amount] / [max_g_amount] cm3
" + + for(var/datum/design/D in files.known_designs) + if(!(selected_category in D.category)) continue - dat += "[title]" - if (istype(t, /obj/item/stack)) - var/obj/item/stack/S = t - var/max_multiplier = min(S.max_amount, S.m_amt?round(m_amount/S.m_amt):INFINITY, S.g_amt?round(g_amount/S.g_amt):INFINITY, S.f_amt?round(f_amount/S.f_amt):INFINITY) - if (max_multiplier>1) - dat += " |" - if (max_multiplier>10) - dat += " x[10]" - if (max_multiplier>25) - dat += " x[25]" - if (max_multiplier>1) - dat += " x[max_multiplier]" - dat += "
" - user << browse("Autolathe Control Panel[dat]", "window=autolathe_regular") - onclose(user, "autolathe_regular") + + if(disabled || !can_build(D)) + dat += "[D.name]" + else + dat += "[D.name]" + + if(ispath(D.build_path, /obj/item/stack)) + var/max_multiplier = min(50, D.materials["$metal"] ?round(m_amount/D.materials["$metal"]):INFINITY,D.materials["$glass"]?round(g_amount/D.materials["$glass"]):INFINITY) + if (max_multiplier>10 && !disabled) + dat += " x10" + if (max_multiplier>25 && !disabled) + dat += " x25" + if(max_multiplier > 0 && !disabled) + dat += " x[max_multiplier]" + + dat += "[get_design_cost(D)]
" + + dat += "
" + return dat + +/obj/machinery/autolathe/proc/can_build(var/datum/design/D) + var/coeff = (ispath(D.build_path,/obj/item/stack) ? 1 : 2 ** prod_coeff) + + if(D.materials["$metal"] && (m_amount < (D.materials["$metal"] / coeff))) + return 0 + if(D.materials["$glass"] && (g_amount < (D.materials["$glass"] / coeff))) + return 0 + return 1 + +/obj/machinery/autolathe/proc/get_design_cost(var/datum/design/D) + var/coeff = (ispath(D.build_path,/obj/item/stack) ? 1 : 2 ** prod_coeff) + var/dat + if(D.materials["$metal"]) + dat += "[D.materials["$metal"] / coeff] metal " + if(D.materials["$glass"]) + dat += "[D.materials["$glass"] / coeff] glass" + return dat /obj/machinery/autolathe/proc/shock(mob/user, prb) if(stat & (BROKEN|NOPOWER)) // unpowered, no shock @@ -178,290 +311,14 @@ var/global/list/autolathe_recipes_hidden = list( \ else return 0 -/obj/machinery/autolathe/interact(mob/user as mob) - if(..()) - return +/obj/machinery/autolathe/proc/adjust_hacked(var/hack) + hacked = hack - if (src.shocked) - src.shock(user,50) - - if (src.panel_open) - wires_win(user,50) - return - - if (src.disabled) - user << "\red You press the button, but nothing happens." - return - - regular_win(user) - return - -/obj/machinery/autolathe/attackby(var/obj/item/O as obj, var/mob/user as mob) - if (stat) - return 1 - - if (busy) - user << "\red The autolathe is busy. Please wait for completion of previous operation." - return 1 - - if (istype(O, /obj/item/weapon/screwdriver)) - default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", O) - return 1 - - if(exchange_parts(user, O)) - return - - if (panel_open) - //Don't eat multitools or wirecutters used on an open lathe. - if(istype(O, /obj/item/device/multitool) || istype(O, /obj/item/weapon/wirecutters)) - attack_hand(user) - return - - //Dismantle the frame. - if(istype(O, /obj/item/weapon/crowbar)) - for(var/obj/I in component_parts) - if(I.reliability != 100 && crit_fail) - I.crit_fail = 1 - I.loc = src.loc - if(m_amount >= 3750) - var/obj/item/stack/sheet/metal/G = new /obj/item/stack/sheet/metal(src.loc) - G.amount = round(m_amount / 3750) - if(g_amount >= 3750) - var/obj/item/stack/sheet/glass/G = new /obj/item/stack/sheet/glass(src.loc) - G.amount = round(g_amount / 3750) - default_deconstruction_crowbar(O) - return 1 - else - user.set_machine(src) - interact(user) - return 1 - - if (src.m_amount + O.m_amt > max_m_amount) - user << "\red The autolathe is full. Please remove metal from the autolathe in order to insert more." - return 1 - if (src.g_amount + O.g_amt > max_g_amount) - user << "\red The autolathe is full. Please remove glass from the autolathe in order to insert more." - return 1 - if (src.f_amount + O.f_amt > max_f_amount) - user << "\red The autolathe is full. Please remove fur from the autolathe in order to insert more." - return 1 - if (O.m_amt == 0 && O.g_amt == 0 && O.f_amt == 0) - user << "\red This object does not contain significant amounts of metal or glass, or cannot be accepted by the autolathe due to size or hazardous materials." - return 1 - /* - if (istype(O, /obj/item/weapon/grab) && src.hacked) - var/obj/item/weapon/grab/G = O - if (prob(25) && G.affecting) - G.affecting.gib() - m_amount += 50000 - f_amount += 1000 - return - */ - - var/amount = 1 - var/obj/item/stack/stack - var/m_amt = O.m_amt - var/g_amt = O.g_amt - var/f_amt = O.f_amt - if (istype(O, /obj/item/stack)) - stack = O - amount = stack.amount - if (m_amt) - amount = min(amount, round((max_m_amount-src.m_amount)/m_amt)) - flick("autolathe_o",src)//plays metal insertion animation - if (g_amt) - amount = min(amount, round((max_g_amount-src.g_amount)/g_amt)) - flick("autolathe_r",src)//plays glass insertion animation - if (f_amt) - amount = min(amount, round((max_f_amount-src.f_amount)/f_amt)) - flick("autolathe_f",src)//plays fur insertion animation - stack.use(amount) + if(hack) + for(var/datum/design/D in files.possible_designs) + if((D.build_type & 4) && ("hacked" in D.category)) + files.known_designs += D else - usr.before_take_item(O) - O.loc = src - icon_state = "autolathe" - busy = 1 - use_power(max(1000, (m_amt+g_amt)*amount/10)) - src.m_amount += m_amt * amount - src.g_amount += g_amt * amount - src.f_amount += f_amt * amount - user << "You insert [amount] sheet[amount>1 ? "s" : ""] to the autolathe." - if (O && O.loc == src) - del(O) - busy = 0 - src.updateUsrDialog() - -/obj/machinery/autolathe/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/autolathe/attack_hand(mob/user as mob) - user.set_machine(src) - interact(user) - - -/obj/machinery/autolathe/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) - src.add_fingerprint(usr) - if (!busy) - if(href_list["make"]) - var/coeff = 2 ** prod_coeff - var/turf/T = get_step(src.loc, get_dir(src,usr)) - - // critical exploit fix start -walter0o - var/obj/item/template = null - var/attempting_to_build = locate(href_list["make"]) - - if(!attempting_to_build) - return - - if(locate(attempting_to_build, src.L) || locate(attempting_to_build, src.LL)) // see if the requested object is in one of the construction lists, if so, it is legit -walter0o - template = attempting_to_build - - else // somebody is trying to exploit, alert admins -walter0o - - var/turf/LOC = get_turf(usr) - message_admins("[key_name_admin(usr)] tried to exploit an autolathe to duplicate [attempting_to_build] ! ([LOC ? "JMP" : "null"])", 0) - log_admin("EXPLOIT : [key_name(usr)] tried to exploit an autolathe to duplicate [attempting_to_build] !") - return - - // now check for legit multiplier, also only stacks should pass with one to prevent raw-materials-manipulation -walter0o - - var/multiplier = text2num(href_list["multiplier"]) - - if (!multiplier) multiplier = 1 - var/max_multiplier = 1 - - if(istype(template, /obj/item/stack)) // stacks are the only items which can have a multiplier higher than 1 -walter0o - var/obj/item/stack/S = template - max_multiplier = min(S.max_amount, S.m_amt?round(m_amount/S.m_amt):INFINITY, S.g_amt?round(g_amount/S.g_amt):INFINITY) // pasta from regular_win() to make sure the numbers match -walter0o - - if( (multiplier > max_multiplier) || (multiplier <= 0) ) // somebody is trying to exploit, alert admins-walter0o - - var/turf/LOC = get_turf(usr) - message_admins("[key_name_admin(usr)] tried to exploit an autolathe with multiplier set to [multiplier] on [template] ! ([LOC ? "JMP" : "null"])" , 0) - log_admin("EXPLOIT : [key_name(usr)] tried to exploit an autolathe with multiplier set to [multiplier] on [template] !") - return - - var/power = max(2000, (template.m_amt+template.g_amt+template.f_amt)*multiplier/5) - if(src.m_amount >= template.m_amt*multiplier/coeff && src.g_amount >= template.g_amt*multiplier/coeff && src.f_amount >= template.f_amt*multiplier/coeff) - busy = 1 - use_power(power) - icon_state = "autolathe" - flick("autolathe_n",src) - spawn(32/coeff) - use_power(power) - if(istype(template, /obj/item/stack)) - src.m_amount -= template.m_amt*multiplier - src.g_amount -= template.g_amt*multiplier - src.f_amount -= template.f_amt*multiplier - var/obj/new_item = new template.type(T) - var/obj/item/stack/S = new_item - S.amount = multiplier - else - src.m_amount -= template.m_amt/coeff - src.g_amount -= template.g_amt/coeff - src.f_amount -= template.f_amt/coeff - var/obj/item/new_item = new template.type(T) - new_item.m_amt /= coeff - new_item.g_amt /= coeff - new_item.f_amt /= coeff - if(src.m_amount < 0) - src.m_amount = 0 - if(src.g_amount < 0) - src.g_amount = 0 - if(src.f_amount < 0) - src.f_amount = 0 - busy = 0 - - if(href_list["act"]) - var/temp_wire = href_list["wire"] - if(href_list["act"] == "pulse") - if (!istype(usr.get_active_hand(), /obj/item/device/multitool)) - usr << "You need a multitool!" - else - if(src.wires[temp_wire]) - usr << "You can't pulse a cut wire." - else - if(src.hack_wire == temp_wire) - src.hacked = !src.hacked - spawn(100) src.hacked = !src.hacked - if(src.disable_wire == temp_wire) - src.disabled = !src.disabled - src.shock(usr,50) - spawn(100) src.disabled = !src.disabled - if(src.shock_wire == temp_wire) - src.shocked = !src.shocked - src.shock(usr,50) - spawn(100) src.shocked = !src.shocked - if(href_list["act"] == "wire") - if (!istype(usr.get_active_hand(), /obj/item/weapon/wirecutters)) - usr << "You need wirecutters!" - else - wires[temp_wire] = !wires[temp_wire] - if(src.hack_wire == temp_wire) - src.hacked = !src.hacked - if(src.disable_wire == temp_wire) - src.disabled = !src.disabled - src.shock(usr,50) - if(src.shock_wire == temp_wire) - src.shocked = !src.shocked - src.shock(usr,50) - else - usr << "\red The autolathe is busy. Please wait for completion of previous operation." - src.updateUsrDialog() - return - -/obj/machinery/autolathe/RefreshParts() - var/tot_rating = 0 - prod_coeff = 0 - for(var/obj/item/weapon/stock_parts/matter_bin/MB in component_parts) - tot_rating += MB.rating - tot_rating *= 25000 - max_m_amount = tot_rating * 2 - max_g_amount = tot_rating - max_f_amount = tot_rating - for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) - prod_coeff += M.rating - 1 - -/obj/machinery/autolathe/RefreshParts() - ..() - var/tot_rating = 0 - for(var/obj/item/weapon/stock_parts/matter_bin/MB in component_parts) - tot_rating += MB.rating - tot_rating *= 25000 - max_m_amount = tot_rating * 2 - max_g_amount = tot_rating - max_f_amount = tot_rating - -/obj/machinery/autolathe/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/autolathe(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/console_screen(src) - RefreshParts() - - src.L = autolathe_recipes - src.LL = autolathe_recipes_hidden - src.wires["Light Red"] = 0 - src.wires["Dark Red"] = 0 - src.wires["Blue"] = 0 - src.wires["Green"] = 0 - src.wires["Yellow"] = 0 - src.wires["Black"] = 0 - src.wires["White"] = 0 - src.wires["Gray"] = 0 - src.wires["Orange"] = 0 - src.wires["Pink"] = 0 - var/list/w = list("Light Red","Dark Red","Blue","Green","Yellow","Black","White","Gray","Orange","Pink") - src.hack_wire = pick(w) - w -= src.hack_wire - src.shock_wire = pick(w) - w -= src.shock_wire - src.disable_wire = pick(w) - w -= src.disable_wire + for(var/datum/design/D in files.known_designs) + if("hacked" in D.category) + files.known_designs -= D diff --git a/code/game/machinery/biogenerator.dm b/code/game/machinery/biogenerator.dm index 94e3e75a1ea..f834719c9e0 100644 --- a/code/game/machinery/biogenerator.dm +++ b/code/game/machinery/biogenerator.dm @@ -10,6 +10,7 @@ var/processing = 0 var/obj/item/weapon/reagent_containers/glass/beaker = null var/points = 0 + var/in_beaker = 1 var/menustat = "menu" var/efficiency = 0 var/productivity = 0 @@ -137,11 +138,12 @@ menustat = "menu" if(beaker) dat += "
Biomass: [points] units.

" - dat += "ActivateDetach Container" + dat += "ActivateDetach Container
" + dat += "Put fertilizer in: [in_beaker ? "Beaker" : "Bottle"]" dat += "

Food:

" dat += "
" dat += "10 milk: Make ([20/efficiency])
" - /*dat += "10 cream: Make ([30/efficiency])
"*/ + dat += "10 cream: Make ([30/efficiency])
" dat += "Monkey cube: Make ([250/efficiency])" dat += "
" dat += "

Nutrients:

" @@ -153,14 +155,14 @@ dat += "

Leather:

" dat += "
" dat += "Wallet: Make ([100/efficiency])
" - /*dat += "Book bag: Make ([200/efficiency])
" + dat += "Book bag: Make ([200/efficiency])
" dat += "Plant bag: Make ([200/efficiency])
" - dat += "Mining satchel: Make ([200/efficiency])
"*/ + dat += "Mining satchel: Make ([200/efficiency])
" dat += "Botanical gloves: Make ([250/efficiency])
" dat += "Utility belt: Make ([300/efficiency])
" dat += "Leather Satchel: Make ([400/efficiency])
" dat += "Cash Bag: Make ([400/efficiency])
" - /*dat += "Leather Jacket: Make ([500/efficiency])
"*/ + dat += "Leather Jacket: Make ([500/efficiency])
" //dat += "

Other:

" //dat += "Monkey: Make ([400/efficiency])
" dat += "
" @@ -225,26 +227,38 @@ if(check_container_volume(10)) return 0 else if (check_cost(20/efficiency)) return 0 else beaker.reagents.add_reagent("milk",10) - /*if("cream") + if("cream") if(check_container_volume(10)) return 0 else if (check_cost(30/efficiency)) return 0 - else beaker.reagents.add_reagent("cream",10)*/ + else beaker.reagents.add_reagent("cream",10) if("meat") if (check_cost(250/efficiency)) return 0 else new/obj/item/weapon/reagent_containers/food/snacks/monkeycube(src.loc) if("ez") if (check_cost(10/efficiency)) return 0 - else new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(src.loc) + if(in_beaker) + if(check_container_volume(10)) return 0 + else beaker.reagents.add_reagent("eznutrient",10) + else + new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(src.loc) if("l4z") if (check_cost(20/efficiency)) return 0 - else new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(src.loc) + if(in_beaker) + if(check_container_volume(10)) return 0 + else beaker.reagents.add_reagent("left4zed",10) + else + new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(src.loc) if("rh") if (check_cost(25/efficiency)) return 0 - else new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(src.loc) + if(in_beaker) + if(check_container_volume(10)) return 0 + else beaker.reagents.add_reagent("robustharvest",10) + else + new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(src.loc) if("wallet") if (check_cost(100/efficiency)) return 0 else new/obj/item/weapon/storage/wallet(src.loc) - /*if("bkbag") + if("bkbag") if (check_cost(200/efficiency)) return 0 else new/obj/item/weapon/storage/bag/books(src.loc) if("ptbag") @@ -252,7 +266,7 @@ else new/obj/item/weapon/storage/bag/plants(src.loc) if("mnbag") if (check_cost(200/efficiency)) return 0 - else new/obj/item/weapon/storage/bag/ore(src.loc)*/ + else new/obj/item/weapon/storage/bag/ore(src.loc) if("gloves") if (check_cost(250/efficiency)) return 0 else new/obj/item/clothing/gloves/botanic_leather(src.loc) @@ -265,9 +279,9 @@ if("cashbag") if (check_cost(400/efficiency)) return 0 else new/obj/item/weapon/storage/bag/cash(src.loc) - /*if("jacket") + if("jacket") if (check_cost(500/efficiency)) return 0 - else new/obj/item/clothing/suit/jacket/leather(src.loc)*/ + else new/obj/item/clothing/suit/jacket/leather(src.loc) //if("monkey") // if (check_cost(500)) return 0 // else new/mob/living/carbon/monkey(src.loc) @@ -309,4 +323,8 @@ else if(href_list["menu"]) menustat = "menu" + updateUsrDialog() + + else if(href_list["inbeaker"]) + in_beaker = !in_beaker updateUsrDialog() \ No newline at end of file diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm index 41cf368ecef..d1edd7f2564 100644 --- a/code/game/machinery/bots/bots.dm +++ b/code/game/machinery/bots/bots.dm @@ -30,6 +30,7 @@ var/mob/living/silicon/ai/calling_ai //Links a bot to the AI calling it. var/obj/item/device/radio/Radio //The bot's radio, for speaking to people. var/radio_frequency //The bot's default radio speaking freqency. Recommended to be on a department frequency. + var/radio_name = "Common" //var/emagged = 0 //Urist: Moving that var to the general /bot tree as it's used by most bots var/auto_patrol = 0// set to make bot automatically patrol var/turf/patrol_target // this is turf to navigate to (location of beacon) @@ -55,6 +56,7 @@ #define FLOOR_BOT 3 // Floorbots #define CLEAN_BOT 4 // Cleanbots #define MED_BOT 5 // Medibots + var/bot_type_name = "Bot" #define DEFAULT_SCAN_RANGE 7 //default view range for finding targets. @@ -101,6 +103,7 @@ set_custom_texts() Radio = new /obj/item/device/radio(src) Radio.listening = 0 //Makes bot radios transmit only so no one hears things while adjacent to one. + Radio.config(list("[radio_name]" = 0)) /obj/machinery/bot/proc/add_to_beacons(bot_filter) //Master filter control for bots. Must be placed in the bot's local New() to support map spawned bots. @@ -335,14 +338,13 @@ /obj/machinery/bot/attack_ai(mob/user as mob) attack_hand(user) -/obj/machinery/bot/proc/speak(var/message, freq) //Pass a message to have the bot say() it. Pass a frequency to say it on the radio. +/obj/machinery/bot/proc/speak(var/message, freq, var/freqname = null) //Pass a message to have the bot say() it. Pass a frequency to say it on the radio. if((!on) || (!message)) return if(freq) - return - // Commenting out the radio code until our say code's compatible with /tg/'s - /* Radio.set_frequency(radio_frequency) - Radio.talk_into_atom(src, message, radio_frequency) */ + Radio.set_frequency(radio_frequency) + if(freqname) + Radio.autosay(message, src.name, freqname, list(src.z)) else for(var/mob/O in hearers(src, null)) O.show_message("[src] beeps, \"[message]\"",2) @@ -413,13 +415,13 @@ obj/machinery/bot/proc/bot_move(var/dest, var/move_speed) obj/machinery/bot/proc/bot_step(var/dest) if(path && path.len > 1) - step_to(src, path[1]) + step_towards(src, path[1]) if(get_turf(src) == path[1]) //Successful move path -= path[1] else return 0 else if(path.len == 1) - step_to(src, dest) + step_towards(src, dest) path = list() return 1 @@ -651,7 +653,7 @@ obj/machinery/bot/proc/start_patrol() botcard.access = user_access + prev_access //Adds the user's access, if any. mode = BOT_SUMMON calc_summon_path() - speak("Responding."/*, radio_frequency*/) + speak("Responding.", radio_frequency, radio_name) return // receive response from beacon @@ -738,7 +740,7 @@ obj/machinery/bot/proc/bot_summon() check_bot_access() path = AStar(loc, summon_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance_cardinal, 0, 150, id=botcard, exclude=avoid) if(!path || tries >= 5) //Cannot reach target. Give up and announce the issue. - speak("Summon command failed, destination unreachable."/*,radio_frequency*/) + speak("Summon command failed, destination unreachable.", radio_frequency, radio_name) bot_reset() /obj/machinery/bot/proc/summon_step() @@ -776,7 +778,7 @@ obj/machinery/bot/proc/bot_summon() /obj/machinery/bot/Bump(M as mob|obj) //Leave no door unopened! - if((istype(M, /obj/machinery/door/airlock) || istype(M, /obj/machinery/door/window)) && (!isnull(botcard))) + if((istype(M, /obj/machinery/door/airlock) || istype(M, /obj/machinery/door/window)) && (!isnull(botcard))) var/obj/machinery/door/D = M if(D.check_access(botcard)) D.open() @@ -785,4 +787,5 @@ obj/machinery/bot/proc/bot_summon() var/mob/living/Mb = M loc = Mb.loc frustration = 0 - return \ No newline at end of file + return + \ No newline at end of file diff --git a/code/game/machinery/bots/cleanbot.dm b/code/game/machinery/bots/cleanbot.dm index c4d15103cd9..5c4d3bf9200 100644 --- a/code/game/machinery/bots/cleanbot.dm +++ b/code/game/machinery/bots/cleanbot.dm @@ -39,7 +39,9 @@ var/next_dest var/next_dest_loc radio_frequency = SRV_FREQ //Service + radio_name = "Service" bot_type = CLEAN_BOT + bot_type_name = "Cleanbot" bot_filter = RADIO_CLEANBOT /obj/machinery/bot/cleanbot/New() @@ -120,6 +122,7 @@ text("[on ? "On" : "Off"]")) if(allowed(usr) && !open && !emagged) locked = !locked user << "You [ locked ? "lock" : "unlock"] the [src] behaviour controls." + updateUsrDialog() else if(emagged) user << "ERROR" @@ -234,7 +237,7 @@ text("[on ? "On" : "Off"]")) icon_state = "cleanbot-c" visible_message("[src] begins to clean up [target]") mode = BOT_CLEANING - spawn(50) + spawn(25) if(mode == BOT_CLEANING) qdel(target) anchored = 0 diff --git a/code/game/machinery/bots/ed209bot.dm b/code/game/machinery/bots/ed209bot.dm index 1209b955ce4..f3363665d59 100644 --- a/code/game/machinery/bots/ed209bot.dm +++ b/code/game/machinery/bots/ed209bot.dm @@ -34,7 +34,9 @@ var/projectile = /obj/item/projectile/energy/electrode //Holder for projectile type var/shoot_sound = 'sound/weapons/Taser.ogg' radio_frequency = SEC_FREQ + radio_name = "Security" bot_type = SEC_BOT + bot_type_name = "ED-209" bot_filter = RADIO_SECBOT //List of weapons that secbots will not arrest for @@ -43,8 +45,7 @@ /obj/item/weapon/gun/energy/laser/redtag,\ /obj/item/weapon/gun/energy/laser/practice,\ /obj/item/weapon/melee/telebaton,\ - /obj/item/weapon/gun/energy/kinetic_accelerator,\ - /obj/item/weapon/melee/baton/loaded/ntcane) + /obj/item/weapon/gun/energy/kinetic_accelerator) /obj/item/weapon/ed209_assembly @@ -113,6 +114,7 @@ . = ..() if (.) return + usr.set_machine(src) var/dat dat += hack(user) dat += text({" @@ -267,8 +269,8 @@ Auto Patrol[]"}, M.Stun(5) if(declare_arrests) - //var/area/location = get_area(src) - declare_arrest() + var/area/location = get_area(src) + speak("[arrest_type ? "Detaining" : "Arresting"] level [threatlevel] scumbag [target] in [location].",radio_frequency, radio_name) target.visible_message("[target] has been stunned by [src]!",\ "[target] has been stunned by [src]!") @@ -400,25 +402,6 @@ Auto Patrol[]"}, return 1 return 0 -/obj/machinery/bot/ed209/Bump(M as mob|obj) //Leave no door unopened! - if ((istype(M, /obj/machinery/door)) && (!isnull(botcard))) - var/obj/machinery/door/D = M - if (!istype(D, /obj/machinery/door/firedoor) && D.check_access(botcard)) - D.open() - frustration = 0 - else if ((istype(M, /mob/living/)) && (!anchored)) - loc = M:loc - frustration = 0 - return - -/* terrible -/obj/machinery/bot/ed209/Bumped(atom/movable/M as mob|obj) - spawn(0) - if (M) - var/turf/T = get_turf(src) - M:loc = T -*/ - /obj/machinery/bot/ed209/explode() walk_to(src,0) visible_message("[src] blows apart!") @@ -431,7 +414,7 @@ Auto Patrol[]"}, new /obj/item/device/assembly/prox_sensor(Tsec) if(!lasercolor) - var/obj/item/weapon/gun/energy/taser/G = new /obj/item/weapon/gun/energy/taser(Tsec) + var/obj/item/weapon/gun/energy/advtaser/G = new /obj/item/weapon/gun/energy/advtaser(Tsec) G.power_supply.charge = 0 G.update_icon() else if(lasercolor == "b") @@ -661,7 +644,7 @@ Auto Patrol[]"}, return name = "redtag ED-209 assembly" if("") - if(!istype(W, /obj/item/weapon/gun/energy/taser)) + if(!istype(W, /obj/item/weapon/gun/energy/advtaser)) return name = "taser ED-209 assembly" else @@ -725,10 +708,4 @@ Auto Patrol[]"}, /obj/machinery/bot/ed209/redtag/New() new /obj/machinery/bot/ed209(get_turf(src),null,"r") - qdel(src) - -/obj/machinery/bot/ed209/proc/declare_arrest() - var/area/location = get_area(src) - for(var/mob/living/carbon/human/human in world) - if((human.z == src.z) && istype(human.glasses, /obj/item/clothing/glasses/hud/security) || istype(human.glasses, /obj/item/clothing/glasses/sunglasses/sechud) && !human.blinded) - human << "\icon[human.glasses] [src.name] is [arrest_type ? "detaining" : "arresting"] level [threatlevel] threat [target] in [location]" + qdel(src) \ No newline at end of file diff --git a/code/game/machinery/bots/floorbot.dm b/code/game/machinery/bots/floorbot.dm index dda1b8afcd0..eede1892d76 100644 --- a/code/game/machinery/bots/floorbot.dm +++ b/code/game/machinery/bots/floorbot.dm @@ -50,7 +50,9 @@ req_one_access = list(access_construction, access_robotics) var/targetdirection radio_frequency = ENG_FREQ //Engineering channel + radio_name = "Engineering" bot_type = FLOOR_BOT + bot_type_name = "Floorbot" bot_filter = RADIO_FLOORBOT var/process_type //Determines what to do when process_scan() recieves a target. See process_scan() for details. #define HULL_BREACH 1 @@ -150,6 +152,7 @@ if(allowed(user) && !open && !emagged) locked = !locked user << "You [locked ? "lock" : "unlock"] \the [src] behaviour controls." + updateUsrDialog() else if(emagged) user << "ERROR" @@ -270,9 +273,9 @@ if(path.len == 0) if(!istype(target, /turf/)) var/turf/TL = get_turf(target) - path = AStar(loc, TL, /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30, id=botcard) + path = get_path_to(loc, TL, /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30, id=botcard) else - path = AStar(loc, target, /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30, id=botcard) + path = get_path_to(loc, target, /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30, id=botcard) if(!bot_move(target)) add_to_ignore(target) @@ -307,14 +310,15 @@ anchored = 0 mode = BOT_IDLE target = null - path = new() + path = list() return oldloc = loc /obj/machinery/bot/floorbot/proc/nag() //Annoy everyone on the channel to refill us! if(!nagged) - speak("Requesting refill at [get_area(src)]!"/*, radio_frequency*/) + var/area/location = get_area(src) + speak("Requesting refill at [location]!", radio_frequency, radio_name) nagged = 1 /obj/machinery/bot/floorbot/proc/is_hull_breach(var/turf/t) //Ignore space tiles not considered part of a structure, also ignores shuttle docking areas. @@ -343,9 +347,8 @@ obj/machinery/bot/floorbot/process_scan(var/scan_target) result = F if(FIX_TILE) //Selects only damaged floors. F = scan_target - if(istype(F, /turf)) - if(F.broken || F.burnt) - result = F + if(istype(F) && (F.broken || F.burnt)) + result = F if(TILE_EMAG) //Emag mode! Rip up the floor and cause breaches to space! F = scan_target if(!istype(F, /turf/simulated/floor/plating)) @@ -370,7 +373,7 @@ obj/machinery/bot/floorbot/process_scan(var/scan_target) anchored = 1 icon_state = "floorbot-c" if(istype(target_turf, /turf/space/)) //If we are fixing an area not part of pure space, it is - visible_message(" [targetdirection ? "[src] begins installing a bridge plating." : "[src] begins to repair the hole."] ") + visible_message("[targetdirection ? "[src] begins installing a bridge plating." : "[src] begins to repair the hole."] ") mode = BOT_REPAIRING spawn(50) if(mode == BOT_REPAIRING) @@ -385,32 +388,18 @@ obj/machinery/bot/floorbot/process_scan(var/scan_target) target = null else var/turf/simulated/floor/F = target_turf - if(F.burnt || F.broken) - mode = BOT_REPAIRING - visible_message(" [src] begins repairing the floor.") - spawn(50) - if(mode == BOT_REPAIRING) - F.burnt = 0 - F.broken = 0 - F.icon_state = "floor" - mode = BOT_IDLE - amount -= 1 - updateicon() - anchored = 0 - target = null - else - mode = BOT_REPAIRING - visible_message(" [src] begins repairing the floor.") - spawn(50) - if(mode == BOT_REPAIRING) - F.burnt = 0 - F.broken = 0 - target_turf.ChangeTurf(/turf/simulated/floor) - mode = BOT_IDLE - amount -= 1 - updateicon() - anchored = 0 - target = null + mode = BOT_REPAIRING + visible_message("[src] begins repairing the floor.") + spawn(50) + if(mode == BOT_REPAIRING) + F.broken = 0 + F.burnt = 0 + F.ChangeTurf(/turf/simulated/floor) + mode = BOT_IDLE + amount -= 1 + updateicon() + anchored = 0 + target = null /obj/machinery/bot/floorbot/proc/eattile(var/obj/item/stack/tile/plasteel/T) if(!istype(T, /obj/item/stack/tile/plasteel)) diff --git a/code/game/machinery/bots/medbot.dm b/code/game/machinery/bots/medbot.dm index 19a89339c62..c77a5477e13 100644 --- a/code/game/machinery/bots/medbot.dm +++ b/code/game/machinery/bots/medbot.dm @@ -31,6 +31,7 @@ var/declare_cooldown = 0 //Prevents spam of critical patient alerts. var/stationary_mode = 0 //If enabled, the Medibot will not move automatically. radio_frequency = MED_FREQ //Medical frequency + radio_name = "Medical" //Setting which reagents to use to treat what by default. By id. var/treatment_brute = "tricordrazine" var/treatment_oxy = "tricordrazine" @@ -40,6 +41,7 @@ var/treat_virus = 1 //If on, the bot will attempt to treat viral infections, curing them if possible. var/shut_up = 0 //self explanatory :) bot_type = MED_BOT + bot_type_name = "Medbot" bot_filter = RADIO_MEDBOT /obj/machinery/bot/medbot/syndicate @@ -49,8 +51,8 @@ treatment_oxy = "dexalin" treatment_brute = "bicaridine" treatment_fire = "kelotane" - treatment_tox = "anti_toxin" - + treatment_tox = "anti_toxin" + /obj/machinery/bot/medbot/mysterious name = "\improper Mysterious Medibot" desc = "International Medibot of mystery." @@ -135,6 +137,7 @@ . = ..() if (.) return + usr.set_machine(src) var/dat dat += hack(user) dat += "Medical Unit Controls v1.1

" @@ -326,12 +329,17 @@ return //Patient has moved away from us! - else if(patient && path && path.len && (get_dist(patient,path[path.len]) > 2)) + else if(patient && path.len && (get_dist(patient,path[path.len]) > 2)) path = list() mode = BOT_IDLE last_found = world.time - if(!stationary_mode && patient && path.len == 0 && (get_dist(src,patient) > 1)) + else if(stationary_mode && patient) + patient = null + mode = BOT_IDLE + last_found = world.time + return + if(patient && path.len == 0 && (get_dist(src,patient) > 1)) spawn(0) path = AStar(loc, get_turf(patient), /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance_cardinal, 0, 30,id=botcard) if(!path) @@ -367,10 +375,10 @@ if(emagged == 2) //Everyone needs our medicine. (Our medicine is toxins) return 1 - + if((skin == "bezerk") && (!("syndicate" in C.faction))) return 0 - + if(declare_crit && C.health <= 0) //Critical condition! Call for help! declare(C) @@ -393,7 +401,7 @@ if((C.getToxLoss() >= heal_threshold) && (!C.reagents.has_reagent(treatment_tox))) return 1 - if((C.virus2.len) && (!C.reagents.has_reagent(treatment_virus))) + if((C.virus2.len) && (!C.reagents.has_reagent(treatment_virus))) for (var/ID in C.virus2) if (ID in virusDB) // If the virus is known, the medbot is aware of it return 1 @@ -424,18 +432,18 @@ if(emagged == 2) //Emagged! Time to poison everybody. reagent_id = "toxin" - if(treat_virus) - var/virus = 0 - if(C:virus2.len) - for (var/ID in C.virus2) - if (ID in virusDB) // If the virus is known, the medbot is aware of it and will try to cure it - virus = 1 - - if (!reagent_id && (virus)) - if(!C.reagents.has_reagent(treatment_virus)) - reagent_id = treatment_virus - else + if(treat_virus) + var/virus = 0 + if(C:virus2.len) + for (var/ID in C.virus2) + if (ID in virusDB) // If the virus is known, the medbot is aware of it and will try to cure it + virus = 1 + + if (!reagent_id && (virus)) + if(!C.reagents.has_reagent(treatment_virus)) + reagent_id = treatment_virus + if (!reagent_id && (C.getBruteLoss() >= heal_threshold)) if(!C.reagents.has_reagent(treatment_brute)) reagent_id = treatment_brute @@ -522,11 +530,13 @@ /obj/machinery/bot/medbot/proc/declare(var/crit_patient) if(declare_cooldown) return - //var/area/location = get_area(src) - declare_critical(crit_patient) + if((skin == "bezerk")) + return + var/area/location = get_area(src) + speak("Medical emergency! [crit_patient ? "[crit_patient]" : "A patient"] is in critical condition at [location]!",radio_frequency, radio_name) declare_cooldown = 1 spawn(200) //Twenty seconds - declare_cooldown = 0 + declare_cooldown = 0 /* * Medbot Assembly -- Can be made out of all three medkits. @@ -589,18 +599,4 @@ S.skin = skin S.name = created_name user.before_take_item(src, 1) - qdel(src) - -/obj/machinery/bot/medbot/proc/declare_critical(var/crit_patient) - var/area/location = get_area(src) - for(var/mob/living/carbon/human/human in world) - if((human.z == src.z) && istype(human.glasses, /obj/item/clothing/glasses/hud/health) || istype(human.glasses, /obj/item/clothing/glasses/hud/health_advanced) && !human.blinded) - if((skin == "bezerk") && (!("syndicate" in human.faction))) - continue - human << "\icon[human.glasses] Medical emergency! [crit_patient ? "[crit_patient]" : "A patient"] is in critical condition at [location]!" - for(var/mob/living/silicon/robot in world) - if((robot.z == src.z) && !robot.blinded) - if((skin == "bezerk") && (!("syndicate" in robot.faction))) - continue - if(robot.sensor_mode == 2) - robot << "Medical emergency! [crit_patient ? "[crit_patient]" : "A patient"] is in critical condition at [location]!" \ No newline at end of file + qdel(src) \ No newline at end of file diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm index 0a6f58b0f31..bd1ee21a88c 100644 --- a/code/game/machinery/bots/mulebot.dm +++ b/code/game/machinery/bots/mulebot.dm @@ -23,6 +23,7 @@ var/global/mulebot_count = 0 beacon_freq = 1400 control_freq = 1447 bot_type = MULE_BOT + bot_type_name = "MULEbot" bot_filter = RADIO_MULEBOT suffix = "" @@ -94,7 +95,7 @@ var/global/mulebot_count = 0 else if(istype(I, /obj/item/weapon/card/id) || istype(I, /obj/item/device/pda)) if(toggle_lock(user)) user << "Controls [(locked ? "locked" : "unlocked")]." - + updateUsrDialog() else if(istype(I,/obj/item/weapon/cell) && open && !cell) var/obj/item/weapon/cell/C = I user.drop_item() @@ -237,7 +238,7 @@ var/global/mulebot_count = 0 //user << browse("M.U.L.E. Mk. III [suffix ? "([suffix])" : ""][dat]", "window=mulebot;size=350x500") //onclose(user, "mulebot") - var/datum/browser/popup = new(user, "mulebot", "M.U.L.E. Mk. V [suffix ? "([suffix])" : ""]", 350, 500) + var/datum/browser/popup = new(user, "mulebot", "M.U.L.E. Mk. V [suffix ? "([suffix])" : ""]", 350, 535) popup.set_content(dat) popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) popup.open() @@ -683,6 +684,8 @@ var/global/mulebot_count = 0 /obj/machinery/bot/mulebot/proc/at_target() if(!reached_target) radio_frequency = SUP_FREQ //Supply channel + radio_name = "Supply" + Radio.config(list("[radio_name]" = 0)) visible_message("[src] makes a chiming sound!", "You hear a chime.") playsound(loc, 'sound/machines/chime.ogg', 50, 0) reached_target = 1 @@ -694,9 +697,11 @@ var/global/mulebot_count = 0 playsound(calling_ai, 'sound/machines/chime.ogg',40, 0) calling_ai = null radio_frequency = AIPRIV_FREQ //Report on AI Private instead if the AI is controlling us. + radio_name = "AI Private" + Radio.config(list("[radio_name]" = 0)) if(load) // if loaded, unload at target - speak("Destination [destination] reached. Unloading [load]."/*,radio_frequency*/) + speak("Destination [destination] reached. Unloading [load].", radio_frequency, radio_name) unload(loaddir) else // not loaded @@ -712,7 +717,7 @@ var/global/mulebot_count = 0 if(AM) load(AM) if(report_delivery) - speak("Now loading [load] at [get_area(src)]."/*,radio_frequency*/) + speak("Now loading [load] at [get_area(src)].", radio_frequency, radio_name) // whatever happened, check to see if we return home if(auto_return && destination != home_destination) diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm index 995f0a17378..f6499bcb2df 100644 --- a/code/game/machinery/bots/secbot.dm +++ b/code/game/machinery/bots/secbot.dm @@ -23,8 +23,12 @@ var/weaponscheck = 1 //If true, arrest people for weapons if they lack access var/check_records = 1 //Does it check security records? var/arrest_type = 0 //If true, don't handcuff + var/harmbaton = 0 + var/base_icon = "secbot" radio_frequency = SEC_FREQ //Security channel + radio_name = "Security" bot_type = SEC_BOT + bot_type_name = "Secbot" bot_filter = RADIO_SECBOT //List of weapons that secbots will not arrest for @@ -33,21 +37,31 @@ /obj/item/weapon/gun/energy/laser/redtag,\ /obj/item/weapon/gun/energy/laser/practice,\ /obj/item/weapon/melee/telebaton,\ - /obj/item/weapon/gun/energy/kinetic_accelerator,\ - /obj/item/weapon/melee/baton/loaded/ntcane) + /obj/item/weapon/gun/energy/kinetic_accelerator) /obj/machinery/bot/secbot/beepsky name = "Officer Beepsky" desc = "It's Officer Beepsky! Powered by a potato and a shot of whiskey." idcheck = 0 - weaponscheck = 0 + weaponscheck = 1 auto_patrol = 1 /obj/machinery/bot/secbot/pingsky name = "Officer Pingsky" desc = "It's Officer Pingsky! Delegated to satellite guard duty for harbouring anti-human sentiment." radio_frequency = AIPRIV_FREQ + radio_name = "AI Private" + +/obj/machinery/bot/secbot/buzzsky + name = "Officer Buzzsky" + desc = "It's Officer Buzzsky! Rusted and falling apart, he seems less than thrilled with the crew for leaving him in his current state." + base_icon = "rustbot" + icon_state = "rustbot0" + declare_arrests = 0 + arrest_type = 1 + harmbaton = 1 + emagged = 2 /obj/item/weapon/secbot_assembly name = "incomplete securitron assembly" @@ -62,7 +76,7 @@ /obj/machinery/bot/secbot/New() ..() - icon_state = "secbot[on]" + icon_state = "[base_icon][on]" spawn(3) var/datum/job/detective/J = new/datum/job/detective @@ -73,12 +87,12 @@ /obj/machinery/bot/secbot/turn_on() ..() - icon_state = "secbot[on]" + icon_state = "[base_icon][on]" updateUsrDialog() /obj/machinery/bot/secbot/turn_off() ..() - icon_state = "secbot[on]" + icon_state = "[base_icon][on]" updateUsrDialog() /obj/machinery/bot/secbot/bot_reset() @@ -189,7 +203,7 @@ Auto Patrol: []"}, oldtarget_name = user.name visible_message("[src] buzzes oddly!") declare_arrests = 0 - icon_state = "secbot[on]" + icon_state = "[base_icon][on]" /obj/machinery/bot/secbot/bot_process() if (!..()) @@ -215,13 +229,17 @@ Auto Patrol: []"}, if(target) // make sure target exists if(Adjacent(target) && isturf(target.loc)) // if right next to perp playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) - icon_state = "secbot-c" + if(harmbaton) + playsound(loc, 'sound/weapons/genhit1.ogg', 50, 1, -1) + icon_state = "[base_icon]-c" spawn(2) - icon_state = "secbot[on]" + icon_state = "[base_icon][on]" var/mob/living/carbon/M = target if(istype(M, /mob/living/carbon/human)) if( M.stuttering < 5 && !(M_HULK in M.mutations) ) M.stuttering = 5 + if(harmbaton) // Bots with harmbaton enabled become shitcurity. - Dave + M.apply_damage(10) M.Stun(5) M.Weaken(5) else @@ -230,10 +248,10 @@ Auto Patrol: []"}, M.Stun(5) if(declare_arrests) - //var/area/location = get_area(src) - declare_arrest() - target.visible_message("[target] has been stunned by [src]!",\ - "[target] has been stunned by [src]!") + var/area/location = get_area(src) + speak("[arrest_type ? "Detaining" : "Arresting"] level [threatlevel] scumbag [target] in [location].",radio_frequency, radio_name) + target.visible_message("[target] has been [harmbaton ? "beaten" : "stunned"] by [src]!",\ + "[target] has been [harmbaton ? "beaten" : "stunned"] by [src]!") mode = BOT_PREP_ARREST anchored = 1 @@ -475,13 +493,4 @@ Auto Patrol: []"}, overlays -= "hs_arm" new /obj/item/robot_parts/l_arm(get_turf(src)) user << "You remove the robot arm from [src]." - build_step-- - -/obj/machinery/bot/secbot/proc/declare_arrest() - var/area/location = get_area(src) - for(var/mob/living/carbon/human/human in world) - if((human.z == src.z) && istype(human.glasses, /obj/item/clothing/glasses/hud/security) || istype(human.glasses, /obj/item/clothing/glasses/sunglasses/sechud) && !human.blinded) - human << "\icon[human.glasses] [src.name] is [arrest_type ? "detaining" : "arresting"] level [threatlevel] threat [target] in [location]" - for(var/mob/living/silicon/robot in world) - if((robot.z == src.z) && !robot.blinded && robot.sensor_mode == 1) - robot << "[src.name] is [arrest_type ? "detaining" : "arresting"] level [threatlevel] threat [target] in [location]" \ No newline at end of file + build_step-- \ No newline at end of file diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index b0d44d31d9b..977c1bd3d3e 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -28,6 +28,7 @@ var/light_disabled = 0 var/alarm_on = 0 var/busy = 0 + var/indestructible = 0 // If set, prevents aliens from destroying it /obj/machinery/camera/New() wires = new(src) @@ -97,6 +98,8 @@ /obj/machinery/camera/attack_paw(mob/living/carbon/alien/humanoid/user as mob) if(!istype(user)) return + if(indestructible) + return status = 0 visible_message("\The [user] slashes at [src]!") playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1) diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index 738a704bf7b..47b2edf9fac 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -155,7 +155,7 @@ else src << "\red You've failed to open an airlock for [target]" return -/mob/living/silicon/ai/proc/ai_actual_track(mob/living/target as mob) +/mob/living/silicon/ai/proc/ai_actual_track(atom/target as mob|obj) if(!istype(target)) return var/mob/living/silicon/ai/U = usr diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm index 094619a5a53..cd78210b41f 100644 --- a/code/game/machinery/computer/HolodeckControl.dm +++ b/code/game/machinery/computer/HolodeckControl.dm @@ -479,7 +479,7 @@ ..() /obj/item/weapon/holo - damtype = HALLOSS + damtype = STAMINA /obj/item/weapon/holo/esword desc = "May the force be within you. Sorta" diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 29b6edf937f..3256818b3df 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -25,6 +25,7 @@ networks["Fire Alarms"] = list(access_ce,access_hos,access_captain) networks["Power Alarms"] = list(access_ce,access_hos,access_captain) networks["Supermatter"] = list(access_ce,access_hos,access_captain) + networks["MiniSat"] = list(access_rd,access_hos,access_captain) networks["Singularity"] = list(access_ce,access_hos,access_captain) networks["Anomaly Isolation"] = list(access_rd,access_hos,access_captain) networks["Toxins"] = list(access_rd,access_hos,access_captain) @@ -34,10 +35,7 @@ networks["Thunderdome"] = list(access_cent_captain) attack_ai(var/mob/user as mob) - if(isAI(user)) - return ui_interact(user) - else - return attack_hand(user) + return attack_hand(user) attack_paw(var/mob/user as mob) return attack_hand(user) @@ -50,6 +48,7 @@ // Network configuration attackby(I as obj, user as mob) + access = list() if(istype(I,/obj/item/weapon/card/emag)) // If hit by an emag. var/obj/item/weapon/card/emag/E = I if(!emagged) @@ -70,18 +69,45 @@ ..() ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - if(..()) - return - if(stat & (NOPOWER|BROKEN)) - return + if(src.z > 6) return + if(stat & (NOPOWER|BROKEN)) return + if(user.stat) return + + var/data[0] + + data["current"] = null + + var/list/L = list() + for (var/obj/machinery/camera/C in cameranet.viewpoints) + if(can_access_camera(C)) + L.Add(C) + + camera_sort(L) + + var/cameras[0] + for(var/obj/machinery/camera/C in L) + var/cam[0] + cam["name"] = C.c_tag + cam["deact"] = !C.can_use() + cam["camera"] = "\ref[C]" + cam["x"] = C.x + cam["y"] = C.y + cam["z"] = C.z + + cameras[++cameras.len] = cam + + if(C == current) + data["current"] = cam + + data["cameras"] = cameras - data.Cut() tempnets.Cut() if(emagged) access = list(access_captain) // Assume captain level access when emagged data["emagged"] = 1 - if(isAI(user)) + if(isAI(user) || isrobot (user)) access = list(access_captain) // Assume captain level access when AI + // Loop through the ID's permission, and check which networks the ID has access to. for(var/l in networks) // Loop through networks. for(var/m in networks[l]) // Loop through access levels of the networks. @@ -92,16 +118,36 @@ tempnets.Add(list(list("name" = l, "active" = 0))) break data["networks"] = tempnets + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "camera_console.tmpl", "Camera Monitor UI", 660, 280) + if (!ui) + ui = new(user, src, ui_key, "sec_camera.tmpl", "Camera Console", 900, 800) + + // adding a template with the key "mapContent" enables the map ui functionality + ui.add_template("mapContent", "sec_camera_map_content.tmpl") + // adding a template with the key "mapHeader" replaces the map header content + ui.add_template("mapHeader", "sec_camera_map_header.tmpl") + ui.set_initial_data(data) ui.open() - + ui.set_auto_update(1) + Topic(href, href_list) - if(..()) - return - if(href_list["activate"]) // Activate: enable or disable networks + if(href_list["switchTo"]) + if(src.z>6 || stat&(NOPOWER|BROKEN)) return + if(usr.stat || ((get_dist(usr, src) > 1 || !( usr.canmove ) || usr.blinded) && !istype(usr, /mob/living/silicon))) return + var/obj/machinery/camera/C = locate(href_list["switchTo"]) in cameranet.viewpoints + if(!C) return + + switch_to_camera(usr, C) + return 1 + else if(href_list["reset"]) + if(src.z>6 || stat&(NOPOWER|BROKEN)) return + if(usr.stat || ((get_dist(usr, src) > 1 || !( usr.canmove ) || usr.blinded) && !istype(usr, /mob/living/silicon))) return + current = null + usr.check_eye(current) + return 1 + else if(href_list["activate"]) // Activate: enable or disable networks var/net = href_list["activate"] // Network to be enabled or disabled. var/active = href_list["active"] // Is the network currently active. for(var/a in networks[net]) @@ -113,50 +159,26 @@ src.network += net break nanomanager.update_uis(src) + else + . = ..() attack_hand(var/mob/user as mob) - if(src.z > 6) - user << "\red Unable to establish a connection: \black You're too far away from the station!" - return - if(stat & (NOPOWER|BROKEN)) + access = list() + if (src.z > 6) + user << "\red Unable to establish a connection: \black You're too far away from the station!" return + if(stat & (NOPOWER|BROKEN)) return if(!isAI(user)) user.set_machine(src) - if(network.len == 0) - user << "\red No networks configured! Swipe the monitor with an authorized ID to configure them." - return - - // Camera listing - var/list/L = list() - for (var/obj/machinery/camera/C in cameranet.viewpoints) - L.Add(C) - camera_sort(L) - - var/list/D = list() - D["Cancel"] = "Cancel" - for(var/obj/machinery/camera/C in L) - if(can_access_camera(C)) - D[text("[][]", C.c_tag, (C.status ? null : " (Deactivated)"))] = C - C.watcherslist -= user - var/t = input(user, "Which camera should you change to?") as null|anything in D - if(!t) - user.unset_machine() - return 0 - - var/obj/machinery/camera/C = D[t] + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.wear_id) + var/obj/item/weapon/card/id/gold/C = H.wear_id + access = C.access - if(t == "Cancel") - user.unset_machine() - return 0 - - if(C) - C.watcherslist += user - switch_to_camera(user, C) - spawn(5) - attack_hand(user) - return + ui_interact(user) // Check if camera is accessible when jumping proc/can_access_camera(var/obj/machinery/camera/C) diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index e87f9003383..a007c324ac4 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -1,5 +1,5 @@ /obj/machinery/computer/crew - name = "Crew monitoring computer" + name = "Crew Monitoring Computer" desc = "Used to monitor active health sensors built into most of the crew's uniforms." icon_state = "crew" use_power = 1 diff --git a/code/game/machinery/computer/specops_shuttle.dm b/code/game/machinery/computer/specops_shuttle.dm index 4d3f28f91d0..bdfa06eeba4 100644 --- a/code/game/machinery/computer/specops_shuttle.dm +++ b/code/game/machinery/computer/specops_shuttle.dm @@ -23,14 +23,13 @@ var/specops_shuttle_timeleft = 0 var/specops_shuttle_timereset = 0 /proc/specops_return() - var/area/centcom/control/command = locate()//To find announcer. This area should exist for this proc to work. - var/mob/living/silicon/decoy/announcer = locate() in command//We need a fake AI to announce some stuff below. Otherwise it will be wonky. + var/obj/item/device/radio/intercom/announcer = new /obj/item/device/radio/intercom(null)//We need a fake AI to announce some stuff below. Otherwise it will be wonky. + announcer.config(list("Response Team" = 0)) var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. var/message = "\"THE SPECIAL OPERATIONS SHUTTLE IS PREPARING TO RETURN\""//Initial message shown. if(announcer) - announcer.say(message) - announcer.say(message) + announcer.autosay(message, "A.L.I.C.E.", "Response Team", list(1,2)) while(specops_shuttle_time - world.timeofday > 0) var/ticksleft = specops_shuttle_time - world.timeofday @@ -46,7 +45,7 @@ var/specops_shuttle_timeleft = 0 message = "\"ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN\"" if(rounded_time_left==0) message = "\"ALERT: TAKEOFF\"" - announcer.say(message) + announcer.autosay(message, "A.L.I.C.E.", "Response Team") message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. @@ -94,21 +93,20 @@ var/specops_shuttle_timeleft = 0 for(var/obj/machinery/computer/specops_shuttle/S in world) S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY + + del(announcer) /proc/specops_process() var/area/centcom/specops/special_ops = locate()//Where is the specops area located? - var/area/centcom/control/command = locate()//To find announcer. This area should exist for this proc to work. - var/mob/living/silicon/decoy/announcer = locate() in command//We need a fake AI to announce some stuff below. Otherwise it will be wonky. - + var/obj/item/device/radio/intercom/announcer = new /obj/item/device/radio/intercom(null)//We need a fake AI to announce some stuff below. Otherwise it will be wonky. + announcer.config(list("Response Team" = 0)) + var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. var/message = "\"THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH\""//Initial message shown. if(announcer) - announcer.say(message) - announcer.say(message) - /* - message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" - announcer.say(message) - */ + announcer.autosay(message, "A.L.I.C.E.", "Response Team") + //message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" + //announcer.autosay(message, "A.L.I.C.E.", "Response Team") while(specops_shuttle_time - world.timeofday > 0) var/ticksleft = specops_shuttle_time - world.timeofday @@ -124,8 +122,7 @@ var/specops_shuttle_timeleft = 0 message = "\"ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN\"" if(rounded_time_left==0) message = "\"ALERT: TAKEOFF\"" - announcer.say(message) - announcer.say(message) + announcer.autosay(message, "A.L.I.C.E.", "Response Team") message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. @@ -237,6 +234,8 @@ var/specops_shuttle_timeleft = 0 for(var/obj/machinery/computer/specops_shuttle/S in world) S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY + + del(announcer) /proc/specops_can_move() if(specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) @@ -247,7 +246,8 @@ var/specops_shuttle_timeleft = 0 return 1 /obj/machinery/computer/specops_shuttle/attack_ai(var/mob/user as mob) - return attack_hand(user) + user << "\red Access Denied." + return 1 /obj/machinery/computer/specops_shuttle/attack_paw(var/mob/user as mob) return attack_hand(user) @@ -339,248 +339,4 @@ var/specops_shuttle_timeleft = 0 add_fingerprint(usr) updateUsrDialog() - return - -/*//Config stuff -#define SPECOPS_MOVETIME 600 //Time to station is milliseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves. -#define SPECOPS_STATION_AREATYPE "/area/shuttle/specops/station" //Type of the spec ops shuttle area for station -#define SPECOPS_DOCK_AREATYPE "/area/shuttle/specops/centcom" //Type of the spec ops shuttle area for dock - -var/specops_shuttle_moving_to_station = 0 -var/specops_shuttle_moving_to_centcom = 0 -var/specops_shuttle_at_station = 0 -var/specops_shuttle_can_send = 1 -var/specops_shuttle_time = 0 -var/specops_shuttle_timeleft = 0 - -/obj/machinery/computer/specops_shuttle - name = "Spec. Ops. Shuttle Console" - icon = 'icons/obj/computer.dmi' - icon_state = "shuttle" - req_access = list(access_cent_specops) - var/temp = null - var/hacked = 0 - var/allowedtocall = 0 - -/proc/specops_process() - var/area/centcom/control/cent_com = locate()//To find announcer. This area should exist for this proc to work. - var/area/centcom/specops/special_ops = locate()//Where is the specops area located? - var/mob/living/silicon/decoy/announcer = locate() in cent_com//We need a fake AI to announce some stuff below. Otherwise it will be wonky. - - var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values. - var/message = "THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown. - if(announcer) - announcer.say(message) - message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" - announcer.say(message) - - while(specops_shuttle_time - world.timeofday > 0) - var/ticksleft = specops_shuttle_time - world.timeofday - - if(ticksleft > 1e5) - specops_shuttle_time = world.timeofday + 10 // midnight rollover - specops_shuttle_timeleft = (ticksleft / 10) - - //All this does is announce the time before launch. - if(announcer) - var/rounded_time_left = round(specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions. - if(rounded_time_left in message_tracker)//If that time is in the list for message announce. - message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN" - if(rounded_time_left==0) - message = "ALERT: TAKEOFF" - announcer.say(message) - message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle. - //Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that. - - sleep(5) - - specops_shuttle_moving_to_station = 0 - specops_shuttle_moving_to_centcom = 0 - - specops_shuttle_at_station = 1 - if (specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return - - if (!specops_can_move()) - usr << "\red The Special Operations shuttle is unable to leave." - return - - //Begin Marauder launchpad. - spawn(0)//So it parallel processes it. - for(var/obj/machinery/door/poddoor/M in special_ops) - switch(M.id) - if("ASSAULT0") - spawn(10)//1 second delay between each. - M.open() - if("ASSAULT1") - spawn(20) - M.open() - if("ASSAULT2") - spawn(30) - M.open() - if("ASSAULT3") - spawn(40) - M.open() - - sleep(10) - - var/spawn_marauder[] = new() - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "Marauder Entry") - spawn_marauder.Add(L) - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "Marauder Exit") - var/obj/effect/portal/P = new(L.loc) - P.invisibility = 101//So it is not seen by anyone. - P.failchance = 0//So it has no fail chance when teleporting. - P.target = pick(spawn_marauder)//Where the marauder will arrive. - spawn_marauder.Remove(P.target) - - sleep(10) - - for(var/obj/machinery/mass_driver/M in special_ops) - switch(M.id) - if("ASSAULT0") - spawn(10) - M.drive() - if("ASSAULT1") - spawn(20) - M.drive() - if("ASSAULT2") - spawn(30) - M.drive() - if("ASSAULT3") - spawn(40) - M.drive() - - sleep(50)//Doors remain open for 5 seconds. - - for(var/obj/machinery/door/poddoor/M in special_ops) - switch(M.id)//Doors close at the same time. - if("ASSAULT0") - spawn(0) - M.close() - if("ASSAULT1") - spawn(0) - M.close() - if("ASSAULT2") - spawn(0) - M.close() - if("ASSAULT3") - spawn(0) - M.close() - special_ops.readyreset()//Reset firealarm after the team launched. - //End Marauder launchpad. - - var/area/start_location = locate(/area/shuttle/specops/centcom) - var/area/end_location = locate(/area/shuttle/specops/station) - - var/list/dstturfs = list() - var/throwy = world.maxy - - for(var/turf/T in end_location) - dstturfs += T - if(T.y < throwy) - throwy = T.y - - // hey you, get out of the way! - for(var/turf/T in dstturfs) - // find the turf to move things to - var/turf/D = locate(T.x, throwy - 1, 1) - //var/turf/E = get_step(D, SOUTH) - for(var/atom/movable/AM as mob|obj in T) - AM.Move(D) - if(istype(T, /turf/simulated)) - del(T) - - start_location.move_contents_to(end_location) - - for(var/turf/T in get_area_turfs(end_location) ) - var/mob/M = locate(/mob) in T - M << "\red You have arrived to [station_name]. Commence operation!" - -/proc/specops_can_move() - if(specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return 0 - else return 1 - -/obj/machinery/computer/specops_shuttle/attackby(I as obj, user as mob) - return attack_hand(user) - -/obj/machinery/computer/specops_shuttle/attack_ai(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer/specops_shuttle/attack_paw(var/mob/user as mob) - return attack_hand(user) - -/obj/machinery/computer/specops_shuttle/attackby(I as obj, user as mob) - if(istype(I,/obj/item/weapon/card/emag)) - user << "\blue The electronic systems in this console are far too advanced for your primitive hacking peripherals." - else - return attack_hand(user) - -/obj/machinery/computer/specops_shuttle/attack_hand(var/mob/user as mob) - if(!allowed(user)) - user << "\red Access Denied." - return - -// if (sent_strike_team == 0) -// usr << "\red The strike team has not yet deployed." -// return - - if(..()) - return - - user.set_machine(src) - var/dat - if (temp) - dat = temp - else - dat += {"
Special Operations Shuttle
- \nLocation: [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "Departing for [station_name] in ([specops_shuttle_timeleft] seconds.)":specops_shuttle_at_station ? "Station":"Dock"]
- [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "\n*The Special Ops. shuttle is already leaving.*
\n
":specops_shuttle_at_station ? "\nShuttle Offline
\n
":"\nDepart to [station_name]
\n
"] - \nClose"} - - user << browse(dat, "window=computer;size=575x450") - onclose(user, "computer") - return - -/obj/machinery/computer/specops_shuttle/Topic(href, href_list) - if(..()) - return - - if ((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon))) - usr.set_machine(src) - - if (href_list["sendtodock"]) - if(!specops_shuttle_at_station|| specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return - - usr << "\blue Central Command will not allow the Special Operations shuttle to return." - return - - else if (href_list["sendtostation"]) - if(specops_shuttle_at_station || specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return - - if (!specops_can_move()) - usr << "\red The Special Operations shuttle is unable to leave." - return - - usr << "\blue The Special Operations shuttle will arrive on [station_name] in [(SPECOPS_MOVETIME/10)] seconds." - - temp += "Shuttle departing.

OK" - updateUsrDialog() - - var/area/centcom/specops/special_ops = locate() - if(special_ops) - special_ops.readyalert()//Trigger alarm for the spec ops area. - specops_shuttle_moving_to_station = 1 - - specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME - spawn(0) - specops_process() - - else if (href_list["mainmenu"]) - temp = null - - add_fingerprint(usr) - updateUsrDialog() - return - */ \ No newline at end of file + return \ No newline at end of file diff --git a/code/game/machinery/computer/syndicate_specops_shuttle.dm b/code/game/machinery/computer/syndicate_specops_shuttle.dm index 41a6f9b7307..a095dc495f0 100644 --- a/code/game/machinery/computer/syndicate_specops_shuttle.dm +++ b/code/game/machinery/computer/syndicate_specops_shuttle.dm @@ -180,7 +180,8 @@ var/syndicate_elite_shuttle_timeleft = 0 return attack_hand(user) /obj/machinery/computer/syndicate_elite_shuttle/attack_ai(var/mob/user as mob) - return attack_hand(user) + user << "\red Access Denied." + return 1 /obj/machinery/computer/syndicate_elite_shuttle/attack_paw(var/mob/user as mob) return attack_hand(user) diff --git a/code/game/machinery/computer/telescience.dm b/code/game/machinery/computer/telescience.dm deleted file mode 100644 index 6df9127872f..00000000000 --- a/code/game/machinery/computer/telescience.dm +++ /dev/null @@ -1,315 +0,0 @@ -/obj/machinery/computer/telescience - name = "Telepad Control Console" - desc = "Used to teleport objects to and from the telescience telepad." - icon_state = "teleport-sci" - circuit = "/obj/item/weapon/circuitboard/telesci_console" - var/teles_left // How many teleports left until it becomes uncalibrated - var/x_off // X offset - var/y_off // Y offset - var/x_co // X coordinate - var/y_co // Y coordinate - var/z_co // Z coordinate - var/trueX // X + offset - var/trueY // Y + offset - var/obj/machinery/telepad/telepad - var/tele_id = "Telesci" - var/obj/item/device/sps/inserted_sps - var/last_target - -/obj/machinery/computer/telescience/update_icon() - if(stat & BROKEN) - icon_state = "telescib" - else - if(stat & NOPOWER) - src.icon_state = "teleport0" - stat |= NOPOWER - else - icon_state = initial(icon_state) - stat &= ~NOPOWER - -/obj/machinery/computer/telescience/Destroy() - if(inserted_sps) - inserted_sps.loc = loc - inserted_sps = null - ..() - -/obj/machinery/computer/telescience/attack_paw(mob/user) - usr << "You are too primitive to use this computer." - return - -/obj/machinery/telescience/station/attack_ai(mob/user) - src.attack_hand() - -/obj/machinery/computer/telescience/attack_hand(mob/user) - ui_interact(user) - -/obj/machinery/computer/telescience/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - if(..()) - return - if(stat & (NOPOWER|BROKEN)) - return - - // On first use, the coordinates are null. Rather than displaying null, we'll set them to unset. - if(!x_co) - x_co = "Unset" - if(!y_co) - y_co = "Unset" - if(!z_co) - z_co = "Unset" - - var/data[0] - data["coordx"] = x_co - data["coordy"] = y_co - data["coordz"] = z_co - data["sps"] = inserted_sps - - // Set up the Nano UI - ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "telescience_console.tmpl", "Telescience Console UI", 640, 300) - ui.set_initial_data(data) - ui.open() - -/obj/machinery/computer/telescience/proc/telefail(var/level) - var/teleturf = get_turf(telepad) - switch(level) - if(1) - for(var/mob/O in hearers(telepad, null)) - O.show_message("\red The telepad weakly fizzles.", 2) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, teleturf) - s.start() - if(2) - for(var/mob/living/carbon/human/M in viewers(telepad, null)) - if(M.loc.loc == telepad.loc.loc) // Stops the geneticists with X-Ray vision getting irradiated - M.apply_effect((rand(50, 100)), IRRADIATE, 0) - M << "\red You feel irradiated." - if(3) - for(var/turf/simulated/floor/target_tile in range(0,telepad)) - var/datum/gas_mixture/napalm = new - napalm.toxins = 25 - napalm.temperature = 2000 - target_tile.assume_air(napalm) - spawn (0) target_tile.hotspot_expose(700, 400) - for(var/mob/O in hearers(telepad, null)) - O.show_message("\red The telepad sets on fire!", 2) - if(4) - var/blocked = list(/mob/living/simple_animal/hostile, - /mob/living/simple_animal/hostile/alien/queen/large, - /mob/living/simple_animal/hostile/pirate, - /mob/living/simple_animal/hostile/pirate/ranged, - /mob/living/simple_animal/hostile/russian, - /mob/living/simple_animal/hostile/russian/ranged, - /mob/living/simple_animal/hostile/syndicate, - /mob/living/simple_animal/hostile/syndicate/melee, - /mob/living/simple_animal/hostile/syndicate/melee/space, - /mob/living/simple_animal/hostile/syndicate/ranged, - /mob/living/simple_animal/hostile/syndicate/ranged/space, - /mob/living/simple_animal/hostile/retaliate, - /mob/living/simple_animal/hostile/giant_spider/nurse) - var/list/hostiles = typesof(/mob/living/simple_animal/hostile) - blocked - playsound(teleturf, 'sound/effects/phasein.ogg', 100, 1) - for(var/mob/living/carbon/human/M in viewers(telepad, null)) - flick("e_flash", M.flash) - var/chosen = pick(hostiles) - var/mob/living/simple_animal/hostile/H = new chosen - H.loc = teleturf - return - -/obj/machinery/computer/telescience/proc/teleprep(var/type) - if(!telepad) - usr << "\red Error: No associated telepad. Please recalibrate and try again." - return - if(telepad.panel_open) - usr << "\red Error: The telepad can not be used while in maintenance mode." - return - var/numpick - var/failure = checkFail() - if(failure > 0) - numpick = pick(1,1,1,1,1,2,2,2,2,3) - telefail(numpick) - return - if(teles_left > 0) - if(prob(70 + (5 * telepad.efficiency))) - teles_left -= 1 - tele(type) - if(teles_left == 0) - for(var/mob/O in hearers(src, null)) - O.show_message("\red The telepad has become uncalibrated.", 2) - return - else - if(prob(25 + (10 * telepad.efficiency))) - tele(type) - else - numpick = pick(1,1,1,2,2,3,4) - telefail(numpick) - return - numpick = pick(1,1,1,1,1,2,2,2,2,3) - telefail(numpick) - return - -/obj/machinery/computer/telescience/proc/tele(var/type) - var/tele = get_turf(telepad) - trueX = (x_co + x_off) - trueY = (y_co + y_off) - var/target = locate(trueX, trueY, z_co) - last_target = target - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, tele) - s.start() - flick("pad-beam", telepad) - var/list/teleportables = list() - switch(type) - if(0) - for(var/atom/A in tele) - if(!istype(A, /obj/effect) && !istype(A, /mob/living/silicon/ai) && !istype(A, /obj/item/device/radio/intercom) && !istype(A, /obj/structure/closet/secure_closet/brig)) - if(istype(A, /obj/structure)) - var/obj/structure/S = A - if(!S.anchored) - teleportables += S - else if(istype(A, /obj/machinery)) - var/obj/machinery/M = A - if(!M.anchored) - teleportables += M - else - teleportables += A - for(var/atom/T in teleportables) - do_teleport(T, target, 0) - usr << "\blue Teleport successful." - if(1) - for(var/atom/A in target) - if(!istype(A, /obj/effect) && !istype(A, /mob/living/silicon/ai) && !istype(A, /obj/item/device/radio/intercom)) - if(istype(A, /obj/structure)) - var/obj/structure/S = A - if(!S.anchored) - teleportables += S - else if(istype(A, /obj/machinery)) - var/obj/machinery/M = A - if(!M.anchored) - teleportables += M - else - teleportables += A - for(var/atom/T in teleportables) - do_teleport(T, tele, 0) - usr << "\blue Teleport successful." - return - -/obj/machinery/computer/telescience/proc/checkFail() - var/fail = 0 - if(x_co == "" || x_co == "Unset") - usr << "\red Error: set X coordinate." - fail = 1 - return fail - if(y_co == "" || y_co == "Unset") - usr << "\red Error: set Y coordinate." - fail = 1 - return fail - if(z_co == "" || z_co == "Unset") - usr << "\red Error: set Z coordinate." - fail = 1 - return fail - if(x_co < 11 || x_co > 245) - usr << "\red Error: X is less than 11 or greater than 245." - fail = 1 - return fail - if(y_co < 11 || y_co > 245) - usr << "\red Error: Y is less than 11 or greater than 245." - fail = 1 - return fail - if(z_co == 2 || z_co < 1 || z_co > 6) - if (z_co == 7 & src.emagged == 1) - // This should be empty, allows for it to continue if the z-level is 7 and the machine is emagged. - else - usr << "\red Error: Z is less than 1, greater than [src.emagged ? "7" : "6"], or equal to 2." - fail = 1 - return fail - if(istype(get_area(locate(x_co,y_co,z_co)), /area/security/armoury/gamma)) - usr << "\red Error: Attempting to access telescience-protected area." - fail = 1 - return fail - return fail - -/obj/machinery/computer/telescience/Topic(href, href_list) - if(..()) - return - if(href_list["ejectSPS"]) - inserted_sps.loc = loc - inserted_sps = null - nanomanager.update_uis(src) - if(href_list["setMemory"]) - if(last_target) - inserted_sps.locked_location = last_target - usr << "\blue Location saved." - else - usr << "\red Error: No data stored." - nanomanager.update_uis(src) - if(href_list["setx"]) - var/a = input("Please input desired X coordinate.", name, x_co) as num - a = copytext(sanitize(a), 1, 20) - x_co = a - x_co = text2num(x_co) - nanomanager.update_uis(src) - return - if(href_list["sety"]) - var/b = input("Please input desired Y coordinate.", name, y_co) as num - b = copytext(sanitize(b), 1, 20) - y_co = b - y_co = text2num(y_co) - nanomanager.update_uis(src) - return - if(href_list["setz"]) - var/c = input("Please input desired Z coordinate.", name, z_co) as num - c = copytext(sanitize(c), 1, 20) - z_co = c - z_co = text2num(z_co) - nanomanager.update_uis(src) - return - if(href_list["send"]) - teleprep(0) - nanomanager.update_uis(src) - return - if(href_list["receive"]) - teleprep(1) - nanomanager.update_uis(src) - return - if(href_list["recal"]) - if(telepad == null) - for(var/obj/machinery/telepad/T in range(src,10)) - telepad = T - if(!telepad) - usr << "\red Error: No telepads in range were found." - nanomanager.update_uis(src) - return - var/teleturf = get_turf(telepad) - teles_left = rand(8,12) - x_off = rand(-10,10) - y_off = rand(-10,10) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, teleturf) - s.start() - usr << "\blue Calibration successful." - nanomanager.update_uis(src) - return - -/obj/machinery/computer/telescience/attackby(I as obj, var/mob/user as mob) // Emagging - if(istype(I,/obj/item/weapon/card/emag)) - if (src.emagged == 0) - user << "\blue You scramble the Telescience authentication key to an unknown signal. You should be able to teleport to more places now!" - src.emagged = 1 - else - user << "\red The machine seems unaffected by the card swipe..." - else if(istype(I, /obj/item/device/sps)) - if(!inserted_sps) - inserted_sps = I - user.before_take_item(I) - inserted_sps.loc = src - user.visible_message("You insert [I] into the SPS device slot.") - attack_hand(user) - else if(istype(I, /obj/item/device/multitool)) - var/obj/item/device/multitool/M = I - if(M.buffer && istype(M.buffer, /obj/machinery/telepad)) - telepad = M.buffer - M.buffer = null - user << "You upload the data from [I]'s buffer." - else - ..() \ No newline at end of file diff --git a/code/game/machinery/computer/xenos_shuttle.dm b/code/game/machinery/computer/xenos_shuttle.dm index 398df2389d7..1944274965a 100644 --- a/code/game/machinery/computer/xenos_shuttle.dm +++ b/code/game/machinery/computer/xenos_shuttle.dm @@ -9,10 +9,11 @@ var/area/curr_location var/moving = 0 var/lastMove = 0 + unacidable = 1 /obj/machinery/computer/xenos_station/New() - curr_location= locate(/area/xenos_station/start) + curr_location = locate(/area/xenos_station/start) /obj/machinery/computer/xenos_station/proc/xenos_move_to(area/destination as area) @@ -23,13 +24,61 @@ moving = 1 lastMove = world.time + + for(var/obj/machinery/door/airlock/alien/A in world) + A.close() + A.locked = 1 + A.update_icon() + for(var/mob/M in curr_location) + if(M.client) + spawn(0) + if(M.buckled) + M << "\red Sudden acceleration presses you into your chair!" + shake_camera(M, 3, 1) + else + M << "\red The floor lurches beneath you!" + shake_camera(M, 10, 1) + if(istype(M, /mob/living/carbon) && !isalien(M)) + if(!M.buckled) + M.Weaken(3) + if(curr_location.z != dest_location.z) var/area/transit_location = locate(/area/xenos_station/transit) curr_location.move_contents_to(transit_location) curr_location = transit_location sleep(XENOS_SHUTTLE_MOVE_TIME) + + for(var/obj/machinery/door/airlock/alien/A in world) + A.close() + if(dest_location != locate(/area/xenos_station/start)) + A.locked = 0 + A.update_icon() + + var/list/dstturfs = list() + var/throwy = world.maxy + for(var/turf/T in dest_location) + dstturfs += T + if(T.y < throwy) + throwy = T.y + + // hey you, get out of the way! + for(var/turf/T in dstturfs) + // find the turf to move things to + var/turf/D = locate(T.x, throwy - 1, 1) + //var/turf/E = get_step(D, SOUTH) + for(var/atom/movable/AM as mob|obj in T) + AM.Move(D) + if(istype(T, /turf/simulated)) + del(T) + + for(var/mob/living/carbon/bug in dest_location) // If someone somehow is still in the shuttle's docking area... + bug.gib() + + for(var/mob/living/simple_animal/pest in dest_location) // And for the other kind of bug... + pest.gib() + curr_location.move_contents_to(dest_location) curr_location = dest_location moving = 0 @@ -47,20 +96,25 @@ /obj/machinery/computer/xenos_station/attack_hand(mob/user as mob) if(!allowed(user)) - user << "\red Access Denied" + user << "\red Access denied." + return + + if(!isalien(user) && !isrobot(user) && !isAI(user)) + user << "You do not know how to operate this terminal." return user.set_machine(src) var/dat = {"Location: [curr_location]
Ready to move[max(lastMove + XENOS_SHUTTLE_COOLDOWN - world.time, 0) ? " in [max(round((lastMove + XENOS_SHUTTLE_COOLDOWN - world.time) * 0.1), 0)] seconds" : ": now"]
- Xenos Space
- North West of SS13 | - North of SS13 | - North East of SS13
- South West of SS13 | - South of SS13 | - South East of SS13
+ Alien Space
+ North-West of SS13 | + North-East of SS13
+ East of SS13
+ South-West of SS13 | + South-East of SS13
+ West of SS13
+ North of Research Outpost
Close"} user << browse(dat, "window=computer;size=575x450") @@ -79,17 +133,18 @@ xenos_move_to(/area/xenos_station/start) else if(href_list["station_nw"]) xenos_move_to(/area/xenos_station/northwest) - else if(href_list["station_n"]) - xenos_move_to(/area/xenos_station/north) else if(href_list["station_ne"]) xenos_move_to(/area/xenos_station/northeast) + else if(href_list["station_e"]) + xenos_move_to(/area/xenos_station/east) else if(href_list["station_sw"]) xenos_move_to(/area/xenos_station/southwest) - else if(href_list["station_s"]) - xenos_move_to(/area/xenos_station/south) else if(href_list["station_se"]) xenos_move_to(/area/xenos_station/southeast) - + else if(href_list["station_w"]) + xenos_move_to(/area/xenos_station/west) + else if(href_list["station_ro"]) + xenos_move_to(/area/xenos_station/researchoutpost) add_fingerprint(usr) updateUsrDialog() diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 5cf1a6f04ce..3858b6c50aa 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -266,7 +266,15 @@ obj/machinery/computer/cryopod/Topic(href, href_list) //Make an announcement and log the person entering storage. frozen_crew += "[occupant.real_name]" - announce.autosay("[occupant.real_name] has entered long-term storage.", "Cryogenic Oversight") + var/ailist[] = list() + for (var/mob/living/silicon/ai/A in living_mob_list) + ailist += A + if (ailist.len) + var/mob/living/silicon/ai/announcer = pick(ailist) + announcer.say(";[occupant.real_name] has entered long-term storage.") + else + announce.autosay("[occupant.real_name] has entered long-term storage.", "Cryogenic Oversight") + visible_message("\blue The crypod hums and hisses as it moves [occupant.real_name] into storage.", 3) // Delete the mob. diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index a198028a7ff..24076937260 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -284,6 +284,26 @@ name = "Secure Armory Airlock" hackProof = 1 aiControlDisabled = 1 + +/obj/machinery/door/airlock/alien + name = "Alien Airlock" + desc = "A mysterious alien airlock with a complicated opening mechanism." + hackProof = 1 + icon = 'icons/obj/doors/Doorplasma.dmi' + +/obj/machinery/door/airlock/alien/bumpopen(mob/living/user as mob) + if(istype(user,/mob/living/carbon/alien) || isrobot(user) || isAI(user)) + ..(user) + else + user << "You do not know how to operate this airlock's mechanism." + return + +/obj/machinery/door/airlock/alien/attackby(C as obj, mob/user as mob) + if(isalien(user) || isrobot(user) || isAI(user)) + ..(C, user) + else + user << "You do not know how to operate this airlock's mechanism." + return /* About the new airlock wires panel: @@ -314,174 +334,14 @@ About the new airlock wires panel: return else if(user.hallucination > 50 && prob(10) && src.operating == 0) user << "\red You feel a powerful shock course through your body!" - user.halloss += 10 - user.stunned += 10 + user.staminaloss += 50 + user.stunned += 5 return ..(user) /obj/machinery/door/airlock/bumpopen(mob/living/simple_animal/user as mob) ..(user) - -/* -/obj/machinery/door/airlock/proc/pulse(var/wireColor) - //var/wireFlag = airlockWireColorToFlag[wireColor] //not used in this function - var/wireIndex = airlockWireColorToIndex[wireColor] - switch(wireIndex) - if(AIRLOCK_WIRE_IDSCAN) - //Sending a pulse through this flashes the red light on the door (if the door has power). - if((src.arePowerSystemsOn()) && (!(stat & NOPOWER))) - do_animate("deny") - if(AIRLOCK_WIRE_MAIN_POWER1 || AIRLOCK_WIRE_MAIN_POWER2) - //Sending a pulse through either one causes a breaker to trip, disabling the door for 10 seconds if backup power is connected, or 1 minute if not (or until backup power comes back on, whichever is shorter). - src.loseMainPower() - if(AIRLOCK_WIRE_DOOR_BOLTS) - //one wire for door bolts. Sending a pulse through this drops door bolts if they're not down (whether power's on or not), - //raises them if they are down (only if power's on) - if(!src.locked) - src.lock() - else - src.unlock() - src.updateUsrDialog() - - if(AIRLOCK_WIRE_BACKUP_POWER1 || AIRLOCK_WIRE_BACKUP_POWER2) - //two wires for backup power. Sending a pulse through either one causes a breaker to trip, but this does not disable it unless main power is down too (in which case it is disabled for 1 minute or however long it takes main power to come back, whichever is shorter). - src.loseBackupPower() - if(AIRLOCK_WIRE_AI_CONTROL) - if(src.aiControlDisabled == 0) - src.aiControlDisabled = 1 - else if(src.aiControlDisabled == -1) - src.aiControlDisabled = 2 - src.updateDialog() - spawn(10) - if(src.aiControlDisabled == 1) - src.aiControlDisabled = 0 - else if(src.aiControlDisabled == 2) - src.aiControlDisabled = -1 - src.updateDialog() - if(AIRLOCK_WIRE_ELECTRIFY) - //one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. - if(src.secondsElectrified==0) - shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])") - usr.attack_log += text("\[[time_stamp()]\] Electrified the [name] at [x] [y] [z]") - src.secondsElectrified = 30 - spawn(10) - //TODO: Move this into process() and make pulsing reset secondsElectrified to 30 - while (src.secondsElectrified>0) - src.secondsElectrified-=1 - if(src.secondsElectrified<0) - src.secondsElectrified = 0 -// src.updateUsrDialog() //Commented this line out to keep the airlock from clusterfucking you with electricity. --NeoFite - sleep(10) - if(AIRLOCK_WIRE_OPEN_DOOR) - //tries to open the door without ID - //will succeed only if the ID wire is cut or the door requires no access - if(!src.requiresID() || src.check_access(null)) - if(density) open() - else close() - if(AIRLOCK_WIRE_SAFETY) - safe = !safe - if(!src.density) - close() - src.updateUsrDialog() - - if(AIRLOCK_WIRE_SPEED) - normalspeed = !normalspeed - src.updateUsrDialog() - - if(AIRLOCK_WIRE_LIGHT) - lights = !lights - src.updateUsrDialog() - - -/obj/machinery/door/airlock/proc/cut(var/wireColor) - var/wireFlag = airlockWireColorToFlag[wireColor] - var/wireIndex = airlockWireColorToIndex[wireColor] - wires &= ~wireFlag - switch(wireIndex) - if(AIRLOCK_WIRE_MAIN_POWER1 || AIRLOCK_WIRE_MAIN_POWER2) - //Cutting either one disables the main door power, but unless backup power is also cut, the backup power re-powers the door in 10 seconds. While unpowered, the door may be crowbarred open, but bolts-raising will not work. Cutting these wires may electocute the user. - src.loseMainPower() - src.shock(usr, 50) - src.updateUsrDialog() - if(AIRLOCK_WIRE_DOOR_BOLTS) - //Cutting this wire also drops the door bolts, and mending it does not raise them. (This is what happens now, except there are a lot more wires going to door bolts at present) - src.lock() - src.updateUsrDialog() - if(AIRLOCK_WIRE_BACKUP_POWER1 || AIRLOCK_WIRE_BACKUP_POWER2) - //Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. - src.loseBackupPower() - src.shock(usr, 50) - src.updateUsrDialog() - if(AIRLOCK_WIRE_AI_CONTROL) - //one wire for AI control. Cutting this prevents the AI from controlling the door unless it has hacked the door through the power connection (which takes about a minute). If both main and backup power are cut, as well as this wire, then the AI cannot operate or hack the door at all. - //aiControlDisabled: If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in. - if(src.aiControlDisabled == 0) - src.aiControlDisabled = 1 - else if(src.aiControlDisabled == -1) - src.aiControlDisabled = 2 - src.updateUsrDialog() - if(AIRLOCK_WIRE_ELECTRIFY) - //Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. - if(src.secondsElectrified != -1) - shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])") - usr.attack_log += text("\[[time_stamp()]\] Electrified the [name] at [x] [y] [z]") - src.secondsElectrified = -1 - if (AIRLOCK_WIRE_SAFETY) - safe = 0 - src.updateUsrDialog() - - if(AIRLOCK_WIRE_SPEED) - autoclose = 0 - src.updateUsrDialog() - - if(AIRLOCK_WIRE_LIGHT) - lights = 0 - src.updateUsrDialog() - -/obj/machinery/door/airlock/proc/mend(var/wireColor) - var/wireFlag = airlockWireColorToFlag[wireColor] - var/wireIndex = airlockWireColorToIndex[wireColor] //not used in this function - wires |= wireFlag - switch(wireIndex) - if(AIRLOCK_WIRE_MAIN_POWER1 || AIRLOCK_WIRE_MAIN_POWER2) - if((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) - src.regainMainPower() - src.shock(usr, 50) - src.updateUsrDialog() - if(AIRLOCK_WIRE_BACKUP_POWER1 || AIRLOCK_WIRE_BACKUP_POWER2) - if((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - src.regainBackupPower() - src.shock(usr, 50) - src.updateUsrDialog() - if(AIRLOCK_WIRE_AI_CONTROL) - //one wire for AI control. Cutting this prevents the AI from controlling the door unless it has hacked the door through the power connection (which takes about a minute). If both main and backup power are cut, as well as this wire, then the AI cannot operate or hack the door at all. - //aiControlDisabled: If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in. - if(src.aiControlDisabled == 1) - src.aiControlDisabled = 0 - else if(src.aiControlDisabled == 2) - src.aiControlDisabled = -1 - src.updateUsrDialog() - if(AIRLOCK_WIRE_ELECTRIFY) - if(src.secondsElectrified == -1) - src.secondsElectrified = 0 - - if (AIRLOCK_WIRE_SAFETY) - safe = 1 - src.updateUsrDialog() - - if(AIRLOCK_WIRE_SPEED) - autoclose = 1 - if(!src.density) - close() - src.updateUsrDialog() - - if(AIRLOCK_WIRE_LIGHT) - lights = 1 - src.updateUsrDialog() - -*/ - /obj/machinery/door/airlock/proc/isElectrified() if(src.secondsElectrified != 0) return 1 @@ -575,13 +435,14 @@ About the new airlock wires panel: /obj/machinery/door/airlock/update_icon() if(overlays) overlays.Cut() + overlays = list() + if(emergency) overlays += image('icons/obj/doors/doorint.dmi', "elights") if(density) if(locked && lights) icon_state = "door_locked" else icon_state = "door_closed" if(p_open || welded || frozen) - overlays = list() if(p_open) overlays += image(icon, "panel_open") if(welded) @@ -648,6 +509,11 @@ About the new airlock wires panel: else t1 += text("IdScan enabled. Disable?
\n", src) + if(src.emergency) + t1 += text("Emergency Access Override is enabled. Disable?
\n", src) + else + t1 += text("Emergency Access Override is disabled. Enable?
\n", src) + if(src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) t1 += text("Main Power Input wire is cut.
\n") if(src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) @@ -826,8 +692,9 @@ About the new airlock wires panel: return 1 /obj/machinery/door/airlock/Topic(href, href_list, var/nowindow = 0) - // If you add an if(..()) check you must first remove the var/nowindow parameter. - // Otherwise it will runtime with this kind of error: null.Topic() + //AI + //aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door, 8 door safties, 9 door speed, 11 emergency access + //aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door, 8 door safties, 9 door speed, 11 emergency access if(!nowindow) ..() if(usr.stat || usr.restrained()|| usr.small) @@ -966,6 +833,13 @@ About the new airlock wires panel: usr << "The door bolt lights have been disabled." else usr << "The door bolt lights are already disabled!" + if(11) + // Emergency access + if (src.emergency) + emergency = 0 + else + usr << text("Emergency access is already disabled!") + else if(href_list["aiEnable"]) var/code = text2num(href_list["aiEnable"]) @@ -1057,6 +931,13 @@ About the new airlock wires panel: usr << "The door bolt lights have been enabled" else usr << "The door bolt lights are already enabled!" + if(11) + // Emergency access + if (!src.emergency) + emergency = 1 + else + usr << text("Emergency access is already enabled!") + add_fingerprint(usr) update_icon() @@ -1349,3 +1230,8 @@ About the new airlock wires panel: return else return + + +/obj/machinery/door/airlock/CanAStarPass(var/obj/item/weapon/card/id/ID) +//Airlock is passable if it is open (!density), bot has access, and is not bolted shut) + return !density || (check_access(ID) && !locked) diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index f7410d589f0..2aefc60be27 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -18,6 +18,7 @@ var/glass = 0 var/normalspeed = 1 var/heat_proof = 0 // For glass airlocks/opacity firedoors + var/emergency = 0 var/air_properties_vary_with_direction = 0 //Multi-tile doors @@ -44,12 +45,14 @@ bound_height = width * world.icon_size update_nearby_tiles(need_rebuild=1) + airlocks += src return /obj/machinery/door/Destroy() density = 0 update_nearby_tiles() + airlocks -= src ..() return @@ -68,7 +71,7 @@ if(istype(AM, /obj/machinery/bot)) var/obj/machinery/bot/bot = AM - if(src.check_access(bot.botcard)) + if(src.check_access(bot.botcard) || emergency == 1) if(density) open() return @@ -76,7 +79,7 @@ if(istype(AM, /obj/mecha)) var/obj/mecha/mecha = AM if(density) - if(mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access))) + if(mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access) || emergency == 1)) open() else flick("door_deny", src) @@ -101,7 +104,7 @@ //used in the AStar algorithm to determinate if the turf the door is on is passable /obj/machinery/door/proc/CanAStarPass(var/obj/item/weapon/card/id/ID) - return !density || check_access(ID) + return !density /obj/machinery/door/proc/bumpopen(mob/user as mob) if(operating) return @@ -113,8 +116,10 @@ user = null if(density) - if(allowed(user)) open() - else flick("door_deny", src) + if(allowed(user) || src.emergency == 1) + open() + else + flick("door_deny", src) return /obj/machinery/door/meteorhit(obj/M as obj) @@ -153,7 +158,7 @@ open() operating = -1 return 1 - if(src.allowed(user)) + if(src.allowed(user) || src.emergency == 1) if(src.density) open() else diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 16ce04eb3c5..a6609c03ec1 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -56,7 +56,7 @@ desc = "Emergency air-tight shutter, capable of sealing off breached areas." icon = 'icons/obj/doors/DoorHazard.dmi' icon_state = "door_open" - req_one_access = list(access_atmospherics, access_engine_equip) + req_one_access = list(access_atmospherics, access_engine) opacity = 0 density = 0 @@ -132,9 +132,9 @@ o += "" else o += "" - o += "[celsius]Celsius " + o += "[celsius] Celsius " o += "" - o += "[pressure]kPa" + o += "[pressure] kPa
" usr << o if( islist(users_to_open) && users_to_open.len) @@ -468,7 +468,3 @@ /obj/machinery/door/firedoor/multi_tile/triple icon = 'icons/obj/doors/DoorHazard3x1.dmi' width = 3 - -//used in the AStar algorithm to determinate if the turf the door is on is passable -/obj/machinery/door/firedoor/CanAStarPass() - return !density diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index a49fb60ab5c..265145b4a04 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -81,13 +81,13 @@ var/const/HOLOPAD_MODE = 0 /*This is the proc for special two-way communication between AI and holopad/people talking near holopad. For the other part of the code, check silicon say.dm. Particularly robot talk.*/ -/obj/machinery/hologram/holopad/hear_talk(mob/living/M, text) +/obj/machinery/hologram/holopad/hear_talk(mob/living/M, text, verb) if(M&&hologram&&master)//Master is mostly a safety in case lag hits or something. if(!master.say_understands(M))//The AI will be able to understand most mobs talking through the holopad. text = stars(text) var/name_used = M.GetVoice() //This communication is imperfect because the holopad "filters" voices and is only designed to connect to the master only. - var/rendered = "Holopad received, [name_used] [M.say_quote(text)]" + var/rendered = "Holopad received, [name_used] [verb], \"[text]\"" master.show_message(rendered, 2) return @@ -101,7 +101,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ hologram.SetLuminosity(2) //hologram lighting SetLuminosity(2) //pad lighting icon_state = "holopad1" - A.current = src + A.holo = src master = A//AI is the master. use_power = 2//Active power usage. return 1 @@ -109,8 +109,8 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ /obj/machinery/hologram/holopad/proc/clear_holo() // hologram.SetLuminosity(0)//Clear lighting. //handled by the lighting controller when its ower is deleted del(hologram)//Get rid of hologram. - if(master.current == src) - master.current = null + if(master.holo == src) + master.holo = null master = null//Null the master, since no-one is using it now. SetLuminosity(0) //pad lighting (hologram lighting will be handled automatically since its owner was deleted) icon_state = "holopad0" @@ -141,6 +141,25 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ hologram.loc = get_turf(master.eyeobj) return 1 + +// Simple helper to face what you clicked on, in case it should be needed in more than one place +/obj/machinery/hologram/holopad/proc/face_atom(var/atom/A) + if( !hologram || !A || !hologram.x || !hologram.y || !A.x || !A.y ) return + var/dx = A.x - hologram.x + var/dy = A.y - hologram.y + if(!dx && !dy) // Wall items are graphically shifted but on the floor + if(A.pixel_y > 16) hologram.dir = NORTH + else if(A.pixel_y < -16)hologram.dir = SOUTH + else if(A.pixel_x > 16) hologram.dir = EAST + else if(A.pixel_x < -16)hologram.dir = WEST + return + + if(abs(dx) < abs(dy)) + if(dy > 0) hologram.dir = NORTH + else hologram.dir = SOUTH + else + if(dx > 0) hologram.dir = EAST + else hologram.dir = WEST /* * Hologram @@ -153,23 +172,17 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ active_power_usage = 100 var/obj/effect/overlay/hologram//The projection itself. If there is one, the instrument is on, off otherwise. -/obj/machinery/hologram/power_change() - if (powered()) - stat &= ~NOPOWER - else - stat |= ~NOPOWER - //Destruction procs. /obj/machinery/hologram/ex_act(severity) switch(severity) if(1.0) - qdel(src) + del(src) if(2.0) if (prob(50)) - qdel(src) + del(src) if(3.0) if (prob(5)) - qdel(src) + del(src) return /obj/machinery/hologram/blob_act() @@ -180,7 +193,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ del(src) return -/obj/machinery/hologram/Destroy() +/obj/machinery/hologram/Del() if(hologram) src:clear_holo() ..() @@ -213,4 +226,4 @@ Holographic project of everything else. name = "hologram projector" desc = "It makes a hologram appear...with magnets or something..." icon = 'icons/obj/stationobjs.dmi' - icon_state = "hologram0" + icon_state = "hologram0" diff --git a/code/game/machinery/hydroponics.dm b/code/game/machinery/hydroponics.dm index f985dbc2f30..5a6a82507c6 100644 --- a/code/game/machinery/hydroponics.dm +++ b/code/game/machinery/hydroponics.dm @@ -713,24 +713,19 @@ check_level_sanity() update_icon() - //Check if container is Plant-B-Gone spray (doesn't work with other sprays, may add in future) - else if (istype(O, /obj/item/weapon/reagent_containers/spray/plantbgone)) + //Check if container is any spray container + else if (istype(O, /obj/item/weapon/reagent_containers/spray)) + var/obj/item/weapon/reagent_containers/spray/S = O //Check if there is a plant in the tray if(seed) - health -= rand(5,20) - - if(pestlevel > 0) - pestlevel -= 2 - - if(weedlevel > 0) - weedlevel -= 3 - - toxins += 4 - - check_level_sanity() - + if(!S.reagents.total_volume) + user << "\red [S] is empty." + return + //Container not empty, transfer contents to tray + S.reagents.trans_to(src, S.amount_per_transfer_from_this) visible_message("\red \The [src] has been sprayed with \the [O][(user ? " by [user]." : ".")]") playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) + check_level_sanity() update_icon() else user << "There's nothing in [src] to spray!" diff --git a/code/game/machinery/kitchen/processor.dm b/code/game/machinery/kitchen/processor.dm index 344a4d16f71..aea4592faae 100644 --- a/code/game/machinery/kitchen/processor.dm +++ b/code/game/machinery/kitchen/processor.dm @@ -56,8 +56,20 @@ slime + process(loc, what) + var/mob/living/carbon/slime/S = what + var/C = S.cores + if(S.stat != DEAD) + S.loc = loc + S.visible_message("[C] crawls free of the processor!") + return + for(var/i = 1, i <= C, i++) + new S.coretype(loc) + feedback_add_details("slime_core_harvested","[replacetext(S.colour," ","_")]") + ..() + input = /mob/living/carbon/slime - output = /obj/item/weapon/reagent_containers/glass/beaker/slime + output = null monkey process(loc, what) diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 02c7069d66f..564e25f1aad 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -127,7 +127,7 @@ iconholder = 1 reqpower = 700 - if(/obj/item/weapon/gun/energy/taser) + if(/obj/item/weapon/gun/energy/advtaser) projectile = /obj/item/projectile/energy/electrode eprojectile = projectile iconholder = 1 diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index f2fc01d10d0..7d98671321f 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -81,7 +81,7 @@ var/obj/item/weapon/melee/baton/B = charging if(B.bcell && B.bcell.charge < B.bcell.maxcharge) B.bcell.charge += 1750 - icon_state = "recharger1" + icon_state = icon_state_charging use_power(2000) else icon_state = icon_state_charged diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index c70505b2d27..7b5ba784ef8 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -22,6 +22,14 @@ component_parts += new /obj/item/weapon/cell/high(src) RefreshParts() build_icon() + +/obj/machinery/recharge_station/upgraded/New() + ..() + component_parts += new /obj/item/weapon/stock_parts/capacitor/super(src) + component_parts += new /obj/item/weapon/stock_parts/capacitor/super(src) + component_parts += new /obj/item/weapon/stock_parts/manipulator/pico(src) + component_parts += new /obj/item/weapon/cell/hyper(src) + RefreshParts() /obj/machinery/recharge_station/RefreshParts() recharge_speed = 0 diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index 7345612bbff..ea63a0d6fa0 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -1,4 +1,4 @@ -#define FONT_SIZE "5pt" +#define FONT_SIZE "4pt" #define FONT_COLOR "#09f" #define FONT_STYLE "Arial Black" #define SCROLL_SPEED 2 diff --git a/code/game/machinery/supply_display.dm b/code/game/machinery/supply_display.dm index aacd770d790..394ea4a3534 100644 --- a/code/game/machinery/supply_display.dm +++ b/code/game/machinery/supply_display.dm @@ -1,4 +1,5 @@ /obj/machinery/status_display/supply_display + name = "supply status display" ignore_friendc = 1 /obj/machinery/status_display/supply_display/update() @@ -31,4 +32,4 @@ if(signal.data["command"] == "supply") mode = STATUS_DISPLAY_CUSTOM else - ..(signal) + return diff --git a/code/game/machinery/telepad.dm b/code/game/machinery/telepad.dm deleted file mode 100644 index e1a1a2afd9e..00000000000 --- a/code/game/machinery/telepad.dm +++ /dev/null @@ -1,78 +0,0 @@ -/obj/machinery/telepad - name = "telepad" - desc = "A bluespace telepad used for teleporting objects to and from a location." - icon = 'icons/obj/telescience.dmi' - icon_state = "pad-idle" - anchored = 1 - use_power = 1 - idle_power_usage = 2 - active_power_usage = 50 - var/efficiency - -/obj/machinery/telepad/New() - ..() - component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/telesci_pad(src) - component_parts += new /obj/item/bluespace_crystal/artificial(src) - component_parts += new /obj/item/bluespace_crystal/artificial(src) - component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - component_parts += new /obj/item/weapon/stock_parts/console_screen(src) - component_parts += new /obj/item/stack/cable_coil(src, 1) - RefreshParts() - -/obj/machinery/telepad/RefreshParts() - var/E - for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts) - E += C.rating - efficiency = E - -/obj/machinery/telepad/attackby(obj/item/I, mob/user) - if(default_deconstruction_screwdriver(user, "pad-idle-o", "pad-idle", I)) - return - - if(panel_open) - if(istype(I, /obj/item/device/multitool)) - var/obj/item/device/multitool/M = I - M.buffer = src - user << "You save the data in the [I.name]'s buffer." - - if(exchange_parts(user, I)) - return - - default_deconstruction_crowbar(I) - -/obj/machinery/telepad_cargo - name = "cargo telepad" - desc = "A telepad used by the Rapid Crate Sender." - icon = 'icons/obj/telescience.dmi' - icon_state = "pad-idle" - anchored = 1 - use_power = 1 - idle_power_usage = 2 - active_power_usage = 50 - var/stage = 0 - -/obj/machinery/telepad_cargo/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/wrench)) - playsound(src, 'sound/items/Ratchet.ogg', 50, 1) - if(anchored) - anchored = 0 - user << "The [src] can now be moved." - else if(!anchored) - anchored = 1 - user << "The [src] is now secured." - if(istype(W, /obj/item/weapon/screwdriver)) - if(stage == 0) - playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) - user << "You unscrew the telepad's tracking beacon." - stage = 1 - else if(stage == 1) - playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) - user << "You screw in the telepad's tracking beacon." - stage = 0 - if(istype(W, /obj/item/weapon/weldingtool) && stage == 1) - playsound(src, 'sound/items/Welder.ogg', 50, 1) - user << "You disassemble the telepad." - new /obj/item/stack/sheet/metal(get_turf(src)) - new /obj/item/stack/sheet/glass(get_turf(src)) - qdel(src) \ No newline at end of file diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index b64d0c27983..6e6c79f5772 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -3,7 +3,7 @@ desc = "Used to control a linked teleportation Hub and Station." icon_state = "teleport" circuit = "/obj/item/weapon/circuitboard/teleporter" - var/obj/item/device/sps/locked = null + var/obj/item/device/gps/locked = null var/regime_set = "Teleporter" var/id = null var/obj/machinery/teleport/station/power_station @@ -40,16 +40,16 @@ user << "\blue The teleporter can now lock on to Syndicate beacons!" else ui_interact(user) - else if(istype(I, /obj/item/device/sps)) - var/obj/item/device/sps/L = I + else if(istype(I, /obj/item/device/gps)) + var/obj/item/device/gps/L = I if(L.locked_location && !(stat & (NOPOWER|BROKEN))) user.before_take_item(L) L.loc = src locked = L - user << "You insert the SPS device into the [name]'s slot." + user << "You insert the GPS device into the [name]'s slot." src.attack_hand(user) else - user << "No useable data was found on te SPS device." + user << "No useable data was found on te GPS device." else ..() return diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm index b92d6086211..ba0a73466aa 100644 --- a/code/game/machinery/transformer.dm +++ b/code/game/machinery/transformer.dm @@ -5,10 +5,10 @@ icon_state = "separator-AO1" layer = MOB_LAYER+1 // Overhead anchored = 1 - density = 1 + density = 0 var/transform_dead = 0 var/transform_standing = 0 - var/cooldown_duration = 1200 // 2 minutes + var/cooldown_duration = 600 // 1 minute var/cooldown = 0 var/robot_cell_charge = 5000 diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm index 7bfab1eddec..fa7c83ff2b8 100644 --- a/code/game/machinery/turrets.dm +++ b/code/game/machinery/turrets.dm @@ -190,6 +190,13 @@ targeting_active = 1 target() targeting_active = 0 + + if(prob(15)) + if(prob(50)) + playsound(get_turf(src), 'sound/effects/turret/move1.wav', 60, 1) + else + playsound(get_turf(src), 'sound/effects/turret/move2.wav', 60, 1) + else if(!isPopping())//else, pop down if(!isDown()) popDown() @@ -229,6 +236,10 @@ else A = new /obj/item/projectile/energy/electrode( loc ) use_power(200) + if(src.lasers) + playsound(get_turf(src), 'sound/weapons/Laser.ogg', 60, 1) + else + playsound(get_turf(src), 'sound/weapons/Taser.ogg', 60, 1) A.current = T A.yo = U.y - T.y A.xo = U.x - T.x @@ -244,6 +255,7 @@ if ((!isPopping()) || src.popping==-1) invisibility = 0 popping = 1 + playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1) if (src.cover!=null) flick("popup", src.cover) src.cover.icon_state = "openTurretCover" @@ -253,6 +265,7 @@ /obj/machinery/turret/proc/popDown() if ((!isPopping()) || src.popping==1) popping = -1 + playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1) if (src.cover!=null) flick("popdown", src.cover) src.cover.icon_state = "turretCover" @@ -272,7 +285,7 @@ /obj/machinery/turret/attackby(obj/item/weapon/W, mob/user)//I can't believe no one added this before/N ..() - playsound(src.loc, 'sound/weapons/smash.ogg', 60, 1) + playsound(get_turf(src), 'sound/weapons/smash.ogg', 60, 1) src.spark_system.start() src.health -= W.force * 0.5 if (src.health <= 0) @@ -422,7 +435,7 @@ /obj/machinery/turret/attack_alien(mob/living/carbon/alien/humanoid/M as mob) if(!(stat & BROKEN)) - playsound(src.loc, 'sound/weapons/slash.ogg', 25, 1, -1) + playsound(get_turf(src), 'sound/weapons/slash.ogg', 25, 1, -1) visible_message("\red [] has slashed at []!", M, src) src.health -= 15 if (src.health <= 0) @@ -474,14 +487,15 @@ /obj/machinery/gun_turret //related to turrets but work way differentely because of being mounted on a moving ship. name = "machine gun turret" - desc = "Syndicate defense turret. It really packs a bunch." + desc = "Syndicate heavy defense turret. It really packs a bunch." density = 1 anchored = 1 var/state = 0 //Like stat on mobs, 0 is alive, 1 is damaged, 2 is dead - var/list/faction = list("syndicate") + var/faction = "syndicate" var/atom/cur_target = null var/scan_range = 9 //You will never see them coming var/health = 200 //Because it lacks a cover, and is mostly to keep people from touching the syndie shuttle. + var/bullet_type = /obj/item/projectile/bullet icon = 'icons/obj/turrets.dmi' icon_state = "syndieturret0" @@ -609,11 +623,27 @@ return if (targloc == curloc) return - playsound(src, 'sound/weapons/Gunshot.ogg', 50, 1) - var/obj/item/projectile/A = new /obj/item/projectile/bullet(curloc) + playsound(get_turf(src), 'sound/weapons/Gunshot3.ogg', 60, 1) + var/obj/item/projectile/A = new bullet_type(curloc) A.current = curloc A.yo = targloc.y - curloc.y A.xo = targloc.x - curloc.x spawn(0) A.process() return + + +/obj/machinery/gun_turret/interior + name = "machine gun turret (.45)" + desc = "Syndicate interior defense turret chambered for .45 rounds. Designed to down intruders without damaging the hull." + bullet_type = /obj/item/projectile/bullet/midbullet + +/obj/machinery/gun_turret/exterior + name = "machine gun turret (7.62)" + desc = "Syndicate exterior defense turret chambered for 7.62 rounds. Designed to down intruders with heavy calliber bullets." + bullet_type = /obj/item/projectile/bullet + +/obj/machinery/gun_turret/grenade + name = "mounted grenade launcher (40mm)" + desc = "Syndicate 40mm grenade launcher defense turret. If you've had this much time to look at it, you're probably already dead." + bullet_type = /obj/item/projectile/bullet/a40mm \ No newline at end of file diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 62856dead99..2c728b50b3c 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -915,26 +915,37 @@ product_slogans = "Dress for success!;Suited and booted!;It's show time!;Why leave style up to fate? Use AutoDrobe!" vend_delay = 15 vend_reply = "Thank you for using AutoDrobe!" - products = list(/obj/item/clothing/mask/fawkes = 1, /obj/item/clothing/suit/chickensuit = 1,/obj/item/clothing/head/chicken = 1, /obj/item/clothing/head/corgi = 1, /obj/item/clothing/suit/corgisuit = 1, /obj/item/clothing/under/gladiator = 1, + products = list(/obj/item/clothing/suit/chickensuit = 1,/obj/item/clothing/head/chicken = 1,/obj/item/clothing/under/gladiator = 1, /obj/item/clothing/head/helmet/gladiator = 1,/obj/item/clothing/under/gimmick/rank/captain/suit = 1,/obj/item/clothing/head/flatcap = 1, - /obj/item/clothing/glasses/gglasses = 1,/obj/item/clothing/shoes/jackboots = 1, + /obj/item/clothing/suit/storage/labcoat/mad = 1,/obj/item/clothing/glasses/gglasses = 1,/obj/item/clothing/shoes/jackboots = 1, /obj/item/clothing/under/schoolgirl = 1,/obj/item/clothing/head/kitty = 1,/obj/item/clothing/under/blackskirt = 1,/obj/item/clothing/head/beret = 1, - /obj/item/clothing/suit/wcoat = 1,/obj/item/clothing/under/suit_jacket = 1,/obj/item/clothing/head/that =1,/obj/item/clothing/head/cueball = 1, - /obj/item/clothing/under/scratch = 1,/obj/item/clothing/under/kilt = 1,/obj/item/clothing/head/beret = 1,/obj/item/clothing/suit/wcoat = 1, + /obj/item/clothing/tie/waistcoat = 1,/obj/item/clothing/under/suit_jacket = 1,/obj/item/clothing/head/that =1,/obj/item/clothing/under/kilt = 1,/obj/item/clothing/head/beret = 1,/obj/item/clothing/tie/waistcoat = 1, /obj/item/clothing/glasses/monocle =1,/obj/item/clothing/head/bowlerhat = 1,/obj/item/weapon/cane = 1,/obj/item/clothing/under/sl_suit = 1, /obj/item/clothing/mask/fakemoustache = 1,/obj/item/clothing/suit/bio_suit/plaguedoctorsuit = 1,/obj/item/clothing/head/plaguedoctorhat = 1,/obj/item/clothing/mask/gas/plaguedoctor = 1, /obj/item/clothing/under/owl = 1,/obj/item/clothing/mask/gas/owl_mask = 1,/obj/item/clothing/suit/apron = 1,/obj/item/clothing/under/waiter = 1, - /obj/item/clothing/under/pirate = 1,/obj/item/clothing/suit/pirate_black = 1,/obj/item/clothing/under/pirate_rags = 1,/obj/item/clothing/suit/pirate_brown = 1,/obj/item/clothing/head/pirate = 1,/obj/item/clothing/head/bandana = 1, + /obj/item/clothing/under/pirate = 1,/obj/item/clothing/suit/pirate_brown = 1,/obj/item/clothing/suit/pirate_black =1,/obj/item/clothing/under/pirate_rags =1,/obj/item/clothing/head/pirate = 1,/obj/item/clothing/head/bandana = 1, /obj/item/clothing/head/bandana = 1,/obj/item/clothing/under/soviet = 1,/obj/item/clothing/head/ushanka = 1,/obj/item/clothing/suit/imperium_monk = 1, /obj/item/clothing/mask/gas/cyborg = 1,/obj/item/clothing/suit/holidaypriest = 1,/obj/item/clothing/head/wizard/marisa/fake = 1, /obj/item/clothing/suit/wizrobe/marisa/fake = 1,/obj/item/clothing/under/sundress = 1,/obj/item/clothing/head/witchwig = 1,/obj/item/weapon/staff/broom = 1, /obj/item/clothing/suit/wizrobe/fake = 1,/obj/item/clothing/head/wizard/fake = 1,/obj/item/weapon/staff = 3,/obj/item/clothing/mask/gas/sexyclown = 1, /obj/item/clothing/under/sexyclown = 1,/obj/item/clothing/mask/gas/sexymime = 1,/obj/item/clothing/under/sexymime = 1,/obj/item/clothing/suit/apron/overalls = 1, - /obj/item/clothing/head/rabbitears =1) //Pretty much everything that had a chance to spawn. - contraband = list(/obj/item/clothing/suit/cardborg = 1,/obj/item/clothing/head/cardborg = 1,/obj/item/clothing/suit/judgerobe = 1,/obj/item/clothing/head/powdered_wig = 1,/obj/item/weapon/gun/magic/wand = 1) + /obj/item/clothing/head/rabbitears =1, /obj/item/clothing/head/sombrero = 1, /obj/item/clothing/suit/poncho = 1, + /obj/item/clothing/suit/poncho/green = 1, /obj/item/clothing/suit/poncho/red = 1, /obj/item/clothing/tie/blue = 1, /obj/item/clothing/tie/red = 1, /obj/item/clothing/tie/black = 1, /obj/item/clothing/tie/horrible = 1, + /obj/item/clothing/under/maid = 1, /obj/item/clothing/under/janimaid = 1) + contraband = list(/obj/item/clothing/suit/judgerobe = 1,/obj/item/clothing/head/powdered_wig = 1,/obj/item/weapon/gun/magic/wand = 1) premium = list(/obj/item/clothing/suit/hgpirate = 1, /obj/item/clothing/head/hgpiratecap = 1, /obj/item/clothing/head/helmet/roman = 1, /obj/item/clothing/head/helmet/roman/legionaire = 1, /obj/item/clothing/under/roman = 1, /obj/item/clothing/shoes/roman = 1) refill_canister = /obj/item/weapon/vending_refill/autodrobe +/obj/machinery/vending/autodrobe/New() + ..() + component_parts = list() + var/obj/item/weapon/circuitboard/vendor/V = new(null) + V.set_type(type) + component_parts += V + component_parts += new /obj/item/weapon/vending_refill/autodrobe(0) + component_parts += new /obj/item/weapon/vending_refill/autodrobe(0) + component_parts += new /obj/item/weapon/vending_refill/autodrobe(0) + /obj/machinery/vending/dinnerware name = "Dinnerware" desc = "A kitchen and restaurant equipment vendor" @@ -1038,7 +1049,7 @@ products = list(/obj/item/clothing/under/color/black = 10,/obj/item/clothing/under/color/blue = 10,/obj/item/clothing/under/color/green = 10,/obj/item/clothing/under/color/grey = 10,/obj/item/clothing/under/color/pink = 10,/obj/item/clothing/under/color/red = 10, /obj/item/clothing/under/color/white = 10, /obj/item/clothing/under/color/yellow = 10,/obj/item/clothing/under/color/lightblue = 10,/obj/item/clothing/under/color/aqua = 10,/obj/item/clothing/under/color/purple = 10,/obj/item/clothing/under/color/lightgreen = 10, /obj/item/clothing/under/color/lightblue = 10,/obj/item/clothing/under/color/lightbrown = 10,/obj/item/clothing/under/color/brown = 10,/obj/item/clothing/under/color/yellowgreen = 10,/obj/item/clothing/under/color/darkblue = 10,/obj/item/clothing/under/color/lightred = 10, /obj/item/clothing/under/color/darkred = 10) - contraband = list(/obj/item/clothing/under/syndicate/tacticool = 5,/obj/item/clothing/under/color/orange = 5,/obj/item/clothing/under/psyche = 5) + contraband = list(/obj/item/clothing/under/syndicate/tacticool = 5,/obj/item/clothing/under/color/orange = 5) premium = list(/obj/item/clothing/under/rainbow = 1) refill_canister = /obj/item/weapon/vending_refill/suitdispenser @@ -1047,8 +1058,8 @@ desc = "Wow, hatlord looked fancy, suitlord looked streamlined, and this is just normal. The guy who disigned these must be an idiot." icon_state = "shoes" product_ads = "Put your foot down!;One size fits all!;IM WALKING ON SUNSHINE!;No hobbits allowed.;NO PLEASE WILLY, DONT HURT ME- *BZZT*" - products = list(/obj/item/clothing/shoes/black = 10,/obj/item/clothing/shoes/brown = 10,/obj/item/clothing/shoes/blue = 10,/obj/item/clothing/shoes/green = 10,/obj/item/clothing/shoes/yellow = 10,/obj/item/clothing/shoes/purple = 10,/obj/item/clothing/shoes/red = 10,/obj/item/clothing/shoes/white = 10) - contraband = list(/obj/item/clothing/shoes/jackboots = 5,/obj/item/clothing/shoes/orange = 5) + products = list(/obj/item/clothing/shoes/black = 10,/obj/item/clothing/shoes/brown = 10,/obj/item/clothing/shoes/blue = 10,/obj/item/clothing/shoes/green = 10,/obj/item/clothing/shoes/yellow = 10,/obj/item/clothing/shoes/purple = 10,/obj/item/clothing/shoes/red = 10,/obj/item/clothing/shoes/white = 10,/obj/item/clothing/shoes/sandal=10) + contraband = list(/obj/item/clothing/shoes/orange = 5) premium = list(/obj/item/clothing/shoes/rainbow = 1) refill_canister = /obj/item/weapon/vending_refill/shoedispenser @@ -1069,4 +1080,42 @@ icon_state = "snack" products = list(/obj/item/weapon/reagent_containers/food/snacks/chips =6,/obj/item/weapon/reagent_containers/food/snacks/sosjerky = 6, /obj/item/weapon/reagent_containers/food/snacks/syndicake = 6, /obj/item/weapon/reagent_containers/food/snacks/cheesiehonkers = 6) - refill_canister = /obj/item/weapon/vending_refill/snack \ No newline at end of file + refill_canister = /obj/item/weapon/vending_refill/snack + +//This one's from NTstation +//don't forget to change the refill size if you change the machine's contents! +/obj/machinery/vending/clothing + name = "ClothesMate" //renamed to make the slogan rhyme + desc = "A vending machine for clothing." + icon_state = "clothes" + product_slogans = "Dress for success!;Prepare to look swagalicious!;Look at all this free swag!;Why leave style up to fate? Use the ClothesMate!" + vend_delay = 15 + vend_reply = "Thank you for using the ClothesMate!" + products = list(/obj/item/clothing/head/that=2,/obj/item/clothing/head/fedora=1,/obj/item/clothing/glasses/monocle=1, + /obj/item/clothing/under/suit_jacket/navy=2,/obj/item/clothing/under/kilt=1,/obj/item/clothing/under/overalls=1, + /obj/item/clothing/under/suit_jacket/really_black=2,/obj/item/clothing/under/pants/jeans=3,/obj/item/clothing/under/pants/classicjeans=2, + /obj/item/clothing/under/pants/camo = 1,/obj/item/clothing/under/pants/blackjeans=2,/obj/item/clothing/under/pants/khaki=2, + /obj/item/clothing/under/pants/white=2,/obj/item/clothing/under/pants/red=1,/obj/item/clothing/under/pants/black=2, + /obj/item/clothing/under/pants/tan=2,/obj/item/clothing/under/pants/blue=1,/obj/item/clothing/under/pants/track=1, + /obj/item/clothing/tie/scarf/red=1,/obj/item/clothing/tie/scarf/green=1,/obj/item/clothing/tie/scarf/darkblue=1, + /obj/item/clothing/tie/scarf/purple=1,/obj/item/clothing/tie/scarf/yellow=1,/obj/item/clothing/tie/scarf/orange=1, + /obj/item/clothing/tie/scarf/lightblue=1,/obj/item/clothing/tie/scarf/white=1,/obj/item/clothing/tie/scarf/black=1, + /obj/item/clothing/tie/scarf/zebra=1,/obj/item/clothing/tie/scarf/christmas=1,/obj/item/clothing/tie/stripedredscarf=1, + /obj/item/clothing/tie/stripedbluescarf=1,/obj/item/clothing/tie/stripedgreenscarf=1,/obj/item/clothing/tie/waistcoat=1, + /obj/item/clothing/under/sundress=2,/obj/item/clothing/under/stripeddress = 1, /obj/item/clothing/under/sailordress = 1, /obj/item/clothing/under/redeveninggown = 1, /obj/item/clothing/under/blacktango=1,/obj/item/clothing/suit/jacket=3, + /obj/item/clothing/glasses/regular=2,/obj/item/clothing/head/sombrero=1,/obj/item/clothing/suit/poncho=1, + /obj/item/clothing/suit/ianshirt=1,/obj/item/clothing/shoes/laceup=2,/obj/item/clothing/shoes/black=4, + /obj/item/clothing/shoes/sandal=1) + contraband = list(/obj/item/clothing/under/syndicate/tacticool=1,/obj/item/clothing/mask/balaclava=1,/obj/item/clothing/head/ushanka=1,/obj/item/clothing/under/soviet=1) + premium = list(/obj/item/clothing/under/suit_jacket/checkered=1,/obj/item/clothing/head/mailman=1,/obj/item/clothing/under/rank/mailman=1,/obj/item/clothing/suit/jacket/leather=1,/obj/item/clothing/under/pants/mustangjeans=1) + refill_canister = /obj/item/weapon/vending_refill/clothing + +/obj/machinery/vending/clothing/New() + ..() + component_parts = list() + var/obj/item/weapon/circuitboard/vendor/V = new(null) + V.set_type(type) + component_parts += V + component_parts += new /obj/item/weapon/vending_refill/clothing(0) + component_parts += new /obj/item/weapon/vending_refill/clothing(0) + component_parts += new /obj/item/weapon/vending_refill/clothing(0) \ No newline at end of file diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm index 3c894359db0..c72b2338cba 100644 --- a/code/game/machinery/washing_machine.dm +++ b/code/game/machinery/washing_machine.dm @@ -263,6 +263,9 @@ if ( istype(W,/obj/item/clothing/head/helmet ) ) user << "This item does not fit." return + if ( istype(W,/obj/item/clothing/gloves/furgloves ) ) + user << "This item does not fit." + return if(contents.len < 5) if ( state in list(1, 3) ) diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm index 32c150e23eb..cf3cd0022a6 100644 --- a/code/game/mecha/equipment/tools/tools.dm +++ b/code/game/mecha/equipment/tools/tools.dm @@ -732,7 +732,7 @@ name = "Energy Relay" desc = "Wirelessly drains energy from any available power channel in area. The performance index is quite low." icon_state = "tesla" - origin_tech = "magnets=4;syndicate=2" + origin_tech = "magnets=4;powerstorage=3" equip_cooldown = 10 energy_drain = 0 range = 0 diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index a2a5e5228c2..a4c8b5a527a 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -254,7 +254,7 @@ name = "LBX AC 10 \"Scattershot\"" icon_state = "mecha_scatter" equip_cooldown = 20 - projectile = /obj/item/projectile/bullet/midbullet12 + projectile = /obj/item/projectile/bullet/midbullet fire_sound = 'sound/weapons/Gunshot.ogg' projectiles = 40 projectile_energy_cost = 25 @@ -293,7 +293,7 @@ name = "Ultra AC 2" icon_state = "mecha_uac2" equip_cooldown = 10 - projectile = /obj/item/projectile/bullet/weakbullet + projectile = /obj/item/projectile/bullet/weakbullet3 fire_sound = 'sound/weapons/Gunshot.ogg' projectiles = 300 projectile_energy_cost = 20 diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 72d77cd5a60..454728f15bc 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -1,11 +1,7 @@ -///////////////////////////// -///// Part Fabricator /////// -///////////////////////////// - /obj/machinery/mecha_part_fabricator icon = 'icons/obj/robotics.dmi' icon_state = "fab-idle" - name = "Exosuit Fabricator" + name = "exosuit fabricator" desc = "Nothing is being built." density = 1 anchored = 1 @@ -18,367 +14,188 @@ var/time_coeff_tech = 1 var/resource_coeff_tech = 1 var/list/resources = list( - "metal"=0, - "glass"=0, - "gold"=0, - "silver"=0, - "diamond"=0, - "plasma"=0, - "uranium"=0, - "bananium"=0 - ) + "$metal"=0, + "$glass"=0, + "$bananium"=0, + "$diamond"=0, + "$gold"=0, + "$plasma"=0, + "$silver"=0, + "$uranium"=0 + ) var/res_max_amount = 200000 var/datum/research/files var/id var/sync = 0 var/part_set - var/obj/being_built + var/datum/design/being_built var/list/queue = list() var/processing_queue = 0 var/screen = "main" - var/opened = 0 var/temp - var/list/part_sets = list( //set names must be unique - "Robot"=list( - /obj/item/robot_parts/robot_suit, - /obj/item/robot_parts/chest, - /obj/item/robot_parts/head, - /obj/item/robot_parts/l_arm, - /obj/item/robot_parts/r_arm, - /obj/item/robot_parts/l_leg, - /obj/item/robot_parts/r_leg - ), - -"Robot Repair"=list( - /obj/item/robot_parts/robot_component/binary_communication_device, - /obj/item/robot_parts/robot_component/radio, - /obj/item/robot_parts/robot_component/actuator, - /obj/item/robot_parts/robot_component/diagnosis_unit, - /obj/item/robot_parts/robot_component/camera, - /obj/item/robot_parts/robot_component/armour - ), - "Ripley"=list( - /obj/item/mecha_parts/chassis/ripley, - /obj/item/mecha_parts/part/ripley_torso, - /obj/item/mecha_parts/part/ripley_left_arm, - /obj/item/mecha_parts/part/ripley_right_arm, - /obj/item/mecha_parts/part/ripley_left_leg, - /obj/item/mecha_parts/part/ripley_right_leg - ), - "Odysseus"=list( - /obj/item/mecha_parts/chassis/odysseus, - /obj/item/mecha_parts/part/odysseus_torso, - /obj/item/mecha_parts/part/odysseus_head, - /obj/item/mecha_parts/part/odysseus_left_arm, - /obj/item/mecha_parts/part/odysseus_right_arm, - /obj/item/mecha_parts/part/odysseus_left_leg, - /obj/item/mecha_parts/part/odysseus_right_leg - ), - - "Gygax"=list( - /obj/item/mecha_parts/chassis/gygax, - /obj/item/mecha_parts/part/gygax_torso, - /obj/item/mecha_parts/part/gygax_head, - /obj/item/mecha_parts/part/gygax_left_arm, - /obj/item/mecha_parts/part/gygax_right_arm, - /obj/item/mecha_parts/part/gygax_left_leg, - /obj/item/mecha_parts/part/gygax_right_leg, - /obj/item/mecha_parts/part/gygax_armour - ), - "Durand"=list( - /obj/item/mecha_parts/chassis/durand, - /obj/item/mecha_parts/part/durand_torso, - /obj/item/mecha_parts/part/durand_head, - /obj/item/mecha_parts/part/durand_left_arm, - /obj/item/mecha_parts/part/durand_right_arm, - /obj/item/mecha_parts/part/durand_left_leg, - /obj/item/mecha_parts/part/durand_right_leg, - /obj/item/mecha_parts/part/durand_armor - ), - "Phazon"=list( - /obj/item/mecha_parts/chassis/phazon, - /obj/item/mecha_parts/part/phazon_torso, - /obj/item/mecha_parts/part/phazon_head, - /obj/item/mecha_parts/part/phazon_left_arm, - /obj/item/mecha_parts/part/phazon_right_arm, - /obj/item/mecha_parts/part/phazon_left_leg, - /obj/item/mecha_parts/part/phazon_right_leg, - /obj/item/mecha_parts/part/phazon_armor - ), - "H.O.N.K"=list( - /obj/item/mecha_parts/chassis/honker, - /obj/item/mecha_parts/part/honker_torso, - /obj/item/mecha_parts/part/honker_head, - /obj/item/mecha_parts/part/honker_left_arm, - /obj/item/mecha_parts/part/honker_right_arm, - /obj/item/mecha_parts/part/honker_left_leg, - /obj/item/mecha_parts/part/honker_right_leg - ), - "Exosuit Equipment"=list( - /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp, - /obj/item/mecha_parts/mecha_equipment/tool/drill, - /obj/item/mecha_parts/mecha_equipment/tool/extinguisher, - /obj/item/mecha_parts/mecha_equipment/tool/cable_layer, - /obj/item/mecha_parts/mecha_equipment/tool/sleeper, - /obj/item/mecha_parts/mecha_equipment/tool/syringe_gun, - /obj/item/mecha_parts/chassis/firefighter, - ///obj/item/mecha_parts/mecha_equipment/repair_droid, - /obj/item/mecha_parts/mecha_equipment/generator, - ///obj/item/mecha_parts/mecha_equipment/jetpack, //TODO MECHA JETPACK SPRITE MISSING - /obj/item/mecha_parts/mecha_equipment/weapon/energy/taser, - /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg, - /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar, - /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar, - /obj/item/mecha_parts/mecha_equipment/weapon/honker - ), - - "Robotic Upgrade Modules" = list( - /obj/item/borg/upgrade/reset, - /obj/item/borg/upgrade/rename, - /obj/item/borg/upgrade/restart, - /obj/item/borg/upgrade/vtec, - /obj/item/borg/upgrade/tasercooler, - /obj/item/borg/upgrade/jetpack - ), - - "Space Pod" = list( - /obj/item/pod_parts/core - ), - - "Misc"=list(/obj/item/mecha_parts/mecha_tracking) - ) - - - + var/list/part_sets = list( + "Cyborg", + "Cyborg Repair", + "Ripley", + "Firefighter", + "Odysseus", + "Gygax", + "Durand", + "H.O.N.K", + "Phazon", + "Exosuit Equipment", + "Cyborg Upgrade Modules", + "Misc" + ) /obj/machinery/mecha_part_fabricator/New() ..() component_parts = list() - component_parts += new /obj/item/weapon/circuitboard/mechfab(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) - component_parts += new /obj/item/weapon/stock_parts/manipulator(src) - component_parts += new /obj/item/weapon/stock_parts/micro_laser(src) - component_parts += new /obj/item/weapon/stock_parts/console_screen(src) + component_parts += new /obj/item/weapon/circuitboard/mechfab(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/matter_bin(null) + component_parts += new /obj/item/weapon/stock_parts/manipulator(null) + component_parts += new /obj/item/weapon/stock_parts/micro_laser(null) + component_parts += new /obj/item/weapon/stock_parts/console_screen(null) RefreshParts() - - // part_sets["Cyborg Upgrade Modules"] = typesof(/obj/item/borg/upgrade/) - /obj/item/borg/upgrade/ // Eh. This does it dymaically, but to support having the items referenced otherwhere in the code but not being constructable, going to do it manaully. - - for(var/part_set in part_sets) - convert_part_set(part_set) files = new /datum/research(src) //Setup the research data holder. - /* - if(!id) - for(var/obj/machinery/r_n_d/server/centcom/S in world) - S.initialize() - break - */ - return /obj/machinery/mecha_part_fabricator/RefreshParts() var/T = 0 + + //maximum stocking amount (max 412000) for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts) T += M.rating - res_max_amount = (187500+(T * 37500)) - T = 0 + res_max_amount = (187000+(T * 37500)) + + //ressources adjustment coefficient (1 -> 0.88 -> 0.75) + T = -1 for(var/obj/item/weapon/stock_parts/micro_laser/Ma in component_parts) T += Ma.rating - T -= 1 - var/diff - diff = round(initial(resource_coeff) - (initial(resource_coeff)*(T))/8,0.01) - if(resource_coeff!=diff) - resource_coeff = diff - T = 0 + resource_coeff = round(initial(resource_coeff) - (initial(resource_coeff)*(T))/8,0.01) + + //building time adjustment coefficient (1 -> 0.8 -> 0.6) + T = -1 for(var/obj/item/weapon/stock_parts/manipulator/Ml in component_parts) T += Ml.rating - T -= 1 - diff = round(initial(time_coeff) - (initial(time_coeff)*(T))/5,0.01) - if(time_coeff!=diff) - time_coeff = diff + time_coeff = round(initial(time_coeff) - (initial(time_coeff)*(T))/5,0.01) -/obj/machinery/mecha_part_fabricator/Destroy() - for(var/atom/A in src) - del A - ..() - return - -/obj/machinery/mecha_part_fabricator/proc/operation_allowed(mob/M) - if(isrobot(M) || isAI(M)) - return 1 - if(!istype(req_access) || !req_access.len) - return 1 - else if(istype(M, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = M - for(var/ID in list(H.get_active_hand(), H.wear_id, H.belt)) - if(src.check_access(ID)) - return 1 - M << "You don't have required permissions to use [src]" - return 0 +/obj/machinery/mecha_part_fabricator/check_access(obj/item/weapon/card/id/I) + if(istype(I, /obj/item/device/pda)) + var/obj/item/device/pda/pda = I + I = pda.id + if(!istype(I) || !I.access) //not ID or no access + return 0 + for(var/req in req_access) + if(!(req in I.access)) //doesn't have this access + return 0 + return 1 /obj/machinery/mecha_part_fabricator/proc/emag() - sleep() switch(emagged) if(0) emagged = 0.5 - src.visible_message("\icon[src] [src] beeps: \"DB error \[Code 0x00F1\]\"") + visible_message("\icon[src] \The [src] beeps: \"DB error \[Code 0x00F1\]\"") sleep(10) - src.visible_message("\icon[src] [src] beeps: \"Attempting auto-repair\"") + visible_message("\icon[src] \The [src] beeps: \"Attempting auto-repair\"") sleep(15) - src.visible_message("\icon[src] [src] beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"") + visible_message("\icon[src] \The [src] beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"") sleep(30) - src.visible_message("\icon[src] [src] beeps: \"User DB truncated. Please contact your Nanotrasen system operator for future assistance.\"") + visible_message("\icon[src] \The [src] beeps: \"User DB truncated. Please contact your Nanotrasen system operator for future assistance.\"") req_access = null emagged = 1 if(0.5) - src.visible_message("\icon[src] [src] beeps: \"DB not responding \[Code 0x0003\]...\"") + visible_message("\icon[src] \The [src] beeps: \"DB not responding \[Code 0x0003\]...\"") if(1) - src.visible_message("\icon[src] [src] beeps: \"No records in User DB\"") - return - -/obj/machinery/mecha_part_fabricator/proc/convert_part_set(set_name as text) - var/list/parts = part_sets[set_name] - if(istype(parts, /list)) - for(var/i=1;i<=parts.len;i++) - var/path = parts[i] - var/part = new path(src) - if(part) - parts[i] = part - //debug below - if(!istype(parts[i],/obj/item)) return 0 - return - - -/obj/machinery/mecha_part_fabricator/proc/add_part_set(set_name as text,parts=null) - if(set_name in part_sets)//attempt to create duplicate set - return 0 - if(isnull(parts)) - part_sets[set_name] = list() - else - part_sets[set_name] = parts - convert_part_set(set_name) - return 1 - -/obj/machinery/mecha_part_fabricator/proc/add_part_to_set(set_name as text,part) - if(!part) return 0 - src.add_part_set(set_name)//if no "set_name" set exists, create - var/list/part_set = part_sets[set_name] - var/atom/apart - if(ispath(part)) - apart = new part(src) - else - apart = part - if(!istype(apart)) return 0 - for(var/obj/O in part_set) - if(O.type == apart.type) - del apart - return 0 - part_set[++part_set.len] = apart - return 1 - -/obj/machinery/mecha_part_fabricator/proc/remove_part_set(set_name as text) - for(var/i=1,i<=part_sets.len,i++) - if(part_sets[i]==set_name) - part_sets.Cut(i,++i) + visible_message("\icon[src] \The [src] beeps: \"No records in User DB\"") return /obj/machinery/mecha_part_fabricator/proc/output_parts_list(set_name) var/output = "" - var/list/part_set = listgetindex(part_sets, set_name) - if(istype(part_set)) - for(var/obj/item/part in part_set) - var/resources_available = check_resources(part) - output += "
[output_part_info(part)]
\[[resources_available?"Build | ":null]Add to queue\]\[?\]
" + for(var/datum/design/D in files.known_designs) + if(D.build_type & MECHFAB) + if(!(set_name in D.category)) + continue + var/resources_available = check_resources(D) + output += "
[output_part_info(D)]
\[[resources_available?"Build | ":null]Add to queue\]\[?\]
" return output -/obj/machinery/mecha_part_fabricator/proc/output_part_info(var/obj/item/part) - var/output = "[part.name] (Cost: [output_part_cost(part)]) [get_construction_time_w_coeff(part)/10]sec" +/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D) + var/output = "[initial(D.name)] (Cost: [output_part_cost(D)]) [get_construction_time_w_coeff(D)/10] seconds" return output -/obj/machinery/mecha_part_fabricator/proc/output_part_cost(var/obj/item/part) +/obj/machinery/mecha_part_fabricator/proc/output_part_cost(datum/design/D) var/i = 0 var/output - if(part.vars.Find("construction_time") && part.vars.Find("construction_cost"))//The most efficient way to go about this. Not all objects have these vars, but if they don't then they CANNOT be made by the mech fab. Doing it this way reduces a major amount of typecasting and switches, while cutting down maintenece for them as well -Sieve - for(var/c in part:construction_cost)//The check should ensure that anything without the var doesn't make it to this point - if(c in resources) - output += "[i?" | ":null][get_resource_cost_w_coeff(part,c)] [c]" - i++ - return output - else - return 0 + for(var/c in D.materials) + if(c in resources) + output += "[i?" | ":null][get_resource_cost_w_coeff(D,c)] [material2name(c)]" + i++ + return output /obj/machinery/mecha_part_fabricator/proc/output_available_resources() var/output for(var/resource in resources) var/amount = min(res_max_amount, resources[resource]) - output += "[resource]: [amount] cm³" + output += "[material2name(resource)]: [amount] cm³" if(amount>0) - output += " - Remove \[1\] | \[10\] | \[All\]" + output += " - Remove \[1\] | \[10\] | \[All\]" output += "
" return output -/obj/machinery/mecha_part_fabricator/proc/remove_resources(var/obj/item/part) -//Be SURE to add any new equipment to this switch, but don't be suprised if it spits out children objects - if(part.vars.Find("construction_time") && part.vars.Find("construction_cost")) - for(var/resource in part:construction_cost) - if(resource in src.resources) - src.resources[resource] -= get_resource_cost_w_coeff(part,resource) - else - return +/obj/machinery/mecha_part_fabricator/proc/remove_resources(datum/design/D) + for(var/resource in D.materials) + if(resource in resources) + resources[resource] -= get_resource_cost_w_coeff(D,resource) -/obj/machinery/mecha_part_fabricator/proc/check_resources(var/obj/item/part) -// if(istype(part, /obj/item/robot_parts) || istype(part, /obj/item/mecha_parts) || istype(part,/obj/item/borg/upgrade)) -//Be SURE to add any new equipment to this switch, but don't be suprised if it spits out children objects - if(part.vars.Find("construction_time") && part.vars.Find("construction_cost")) - for(var/resource in part:construction_cost) - if(resource in src.resources) - if(src.resources[resource] < get_resource_cost_w_coeff(part,resource)) - return 0 - return 1 - else - return 0 +/obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D) + for(var/R in D.materials) + if(R in resources) + if(resources[R] < get_resource_cost_w_coeff(D, R)) + return 0 + else + return 0 + return 1 -/obj/machinery/mecha_part_fabricator/proc/build_part(var/obj/item/part) - if(!part) return +/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D) + being_built = D + desc = "It's building \a [initial(D.name)]." + remove_resources(D) + overlays += "fab-active" + use_power = 2 + updateUsrDialog() + sleep(get_construction_time_w_coeff(D)) + use_power = 1 + overlays -= "fab-active" + desc = initial(desc) - // critical exploit prevention, do not remove unless you replace it -walter0o - if( !(locate(part, src.contents)) || !(part.vars.Find("construction_time")) || !(part.vars.Find("construction_cost")) ) // these 3 are the current requirements for an object being buildable by the mech_fabricator - return + var/obj/item/I = new D.build_path + I.loc = get_step(src,SOUTH) + I.m_amt = get_resource_cost_w_coeff(D,"$metal") + I.g_amt = get_resource_cost_w_coeff(D,"$glass") + visible_message("\icon[src] \The [src] beeps, \"\The [I] is complete.\"") + being_built = null - src.being_built = new part.type(src) - src.desc = "It's building [src.being_built]." - src.remove_resources(part) - src.overlays += "fab-active" - src.use_power = 2 - src.updateUsrDialog() - sleep(get_construction_time_w_coeff(part)) - src.use_power = 1 - src.overlays -= "fab-active" - src.desc = initial(src.desc) - if(being_built) - src.being_built.Move(get_step(src,SOUTH)) - src.visible_message("\icon[src] [src] beeps, \"The following has been completed: [src.being_built] is built\".") - src.being_built = null - src.updateUsrDialog() + updateUsrDialog() return 1 /obj/machinery/mecha_part_fabricator/proc/update_queue_on_page() - send_byjax(usr,"mecha_fabricator.browser","queue",src.list_queue()) + send_byjax(usr,"mecha_fabricator.browser","queue",list_queue()) return /obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(set_name) if(set_name in part_sets) - var/list/part_set = part_sets[set_name] - if(islist(part_set)) - for(var/obj/item/part in part_set) - add_to_queue(part) - return + for(var/datum/design/D in files.known_designs) + if(D.build_type & MECHFAB) + if(set_name in D.category) + add_to_queue(D) -/obj/machinery/mecha_part_fabricator/proc/add_to_queue(part) +/obj/machinery/mecha_part_fabricator/proc/add_to_queue(D) if(!istype(queue)) queue = list() - if(part) - queue[++queue.len] = part + if(D) + queue[++queue.len] = D return queue.len /obj/machinery/mecha_part_fabricator/proc/remove_from_queue(index) @@ -388,30 +205,26 @@ return 1 /obj/machinery/mecha_part_fabricator/proc/process_queue() - var/obj/item/part = listgetindex(src.queue, 1) - if(!part) + var/datum/design/D = queue[1] + if(!D) remove_from_queue(1) - if(src.queue.len) + if(queue.len) return process_queue() else return - if(!(part.vars.Find("construction_time")) || !(part.vars.Find("construction_cost")))//If it shouldn't be printed - remove_from_queue(1)//Take it out of the quene - return process_queue()//Then reprocess it temp = null - while(part) + while(D) if(stat&(NOPOWER|BROKEN)) return 0 - if(!check_resources(part)) - src.visible_message("\icon[src] [src] beeps, \"Not enough resources. Queue processing stopped\".") - temp = {"Not enough resources to build next part.
+ if(!check_resources(D)) + visible_message("\icon[src] \The [src] beeps, \"Not enough resources. Queue processing stopped.\"") + temp = {"Not enough resources to build next part.
Try again | Return"} return 0 remove_from_queue(1) - build_part(part) - part = listgetindex(src.queue, 1) - src.visible_message("\icon[src] [src] beeps, \"Queue processing finished successfully\".") - return 1 + build_part(D) + D = listgetindex(queue, 1) + visible_message("\icon[src] \The [src] beeps, \"Queue processing finished successfully.\"") /obj/machinery/mecha_part_fabricator/proc/list_queue() var/output = "Queue contains:" @@ -419,67 +232,45 @@ output += "
Nothing" else output += "
    " - for(var/i=1;i<=queue.len;i++) - var/obj/item/part = listgetindex(src.queue, i) - if(istype(part)) - if(part.vars.Find("construction_time") && part.vars.Find("construction_cost")) - output += "[part.name] - [i>1?"":null] [i↓":null] Remove" - else//Prevents junk items from even appearing in the list, and they will be silently removed when the fab processes - remove_from_queue(i)//Trash it - return list_queue()//Rebuild it + var/i = 0 + for(var/datum/design/D in queue) + i++ + var/obj/part = D.build_path + output += "[initial(part.name)] - [i>1?"":null] [i↓":null] Remove" + output += "
" output += "\[Process queue | Clear queue\]" return output -/obj/machinery/mecha_part_fabricator/proc/convert_designs() - if(!files) return - var/i = 0 - for(var/datum/design/D in files.known_designs) - if(D.build_type&16) - if(D.category in part_sets)//Checks if it's a valid category - if(add_part_to_set(D.category, text2path(D.build_path)))//Adds it to said category - i++ - else - if(add_part_to_set("Misc", text2path(D.build_path)))//If in doubt, chunk it into the Misc - i++ - return i - /obj/machinery/mecha_part_fabricator/proc/update_tech() - if(!files) return + if(!files) + return var/output for(var/datum/tech/T in files.known_tech) if(T && T.level > 1) var/diff - switch(T.id) //bad, bad formulas + switch(T.id) if("materials") - var/pmat = 0//Calculations to make up for the fact that these parts and tech modify the same thing - for(var/obj/item/weapon/stock_parts/micro_laser/Ml in component_parts) - pmat += Ml.rating - if(pmat >= 1) - pmat -= 1//So the equations don't have to be reworked, upgrading a single part from T1 to T2 is == to 1 tech level - diff = round(initial(resource_coeff_tech) - (initial(resource_coeff_tech)*(T.level+pmat))/30,0.01) - if(resource_coeff_tech > diff) + //one materials level is 1/32, so that max level is 0.75 coefficient + diff = round(initial(resource_coeff_tech) - (initial(resource_coeff_tech)*(T.level-1))/32,0.01) + if(resource_coeff_tech>diff) resource_coeff_tech = diff - output += "Production efficiency increased.
" + output+="Production efficiency increased.
" if("programming") - var/ptime = 0 - for(var/obj/item/weapon/stock_parts/manipulator/Ma in component_parts) - ptime += Ma.rating - if(ptime >= 2) - ptime -= 2 - diff = round(initial(time_coeff_tech) - (initial(time_coeff_tech)*(T.level+ptime))/25,0.1) - if(time_coeff_tech > diff) + //one materials level is 1/40, so that max level is 0.8 coefficient + diff = round(initial(time_coeff_tech) - (initial(time_coeff_tech)*(T.level-1))/40,0.1) + if(time_coeff_tech>diff) time_coeff_tech = diff - output += "Production routines updated.
" + output+="Production routines updated.
" return output -/obj/machinery/mecha_part_fabricator/proc/sync(silent=null) - if(!silent) - temp = "Updating local R&D database..." - src.updateUsrDialog() - sleep(30) //only sleep if called by user - for(var/obj/machinery/computer/rdconsole/RDC in get_area(src)) +/obj/machinery/mecha_part_fabricator/proc/sync() + temp = "Updating local R&D database..." + updateUsrDialog() + sleep(30) //only sleep if called by user + + for(var/obj/machinery/computer/rdconsole/RDC in area_contents(get_area(src))) if(!RDC.sync) continue for(var/datum/tech/T in RDC.files.known_tech) @@ -487,48 +278,43 @@ for(var/datum/design/D in RDC.files.known_designs) files.AddDesign2Known(D) files.RefreshResearch() - var/i = src.convert_designs() - var/tech_output = update_tech() - if(!silent) - temp = "Processed [i] equipment designs.
" - temp += tech_output - temp += "Return" - src.updateUsrDialog() - if(i || tech_output) - src.visible_message("\icon[src] [src] beeps, \"Succesfully synchronized with R&D server. New data processed.\"") + temp = "Processed equipment designs.
" + //check if the tech coefficients have changed + temp += update_tech() + temp += "Return" + + updateUsrDialog() + visible_message("\icon[src] \The [src] beeps, \"Successfully synchronized with R&D server.\"") + return + + temp = "Unable to connect to local R&D Database.
Please check your connections and try again.
Return" + updateUsrDialog() return -/obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(var/obj/item/part as obj,var/resource as text, var/roundto=1) - if(part.vars.Find("construction_time") && part.vars.Find("construction_cost")) - if (resource=="iron" && !("iron" in part:construction_cost)) - resource="metal" - return round(part:construction_cost[resource]*resource_coeff*resource_coeff_tech, roundto) - else - return 0 +/obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(datum/design/D, resource, roundto = 1) + return round(D.materials[resource]*resource_coeff*resource_coeff_tech, roundto) -/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(var/obj/item/part as obj, var/roundto=1) -//Be SURE to add any new equipment to this switch, but don't be suprised if it spits out children objects - if(part.vars.Find("construction_time") && part.vars.Find("construction_cost")) - return round(part:construction_time*time_coeff*time_coeff_tech, roundto) - else - return 0 +/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(datum/design/D, roundto = 1) //aran + return round(initial(D.construction_time)*time_coeff*time_coeff_tech, roundto) +/obj/machinery/mecha_part_fabricator/attack_hand(mob/user) + if(!(..())) + return interact(user) -/obj/machinery/mecha_part_fabricator/attack_hand(mob/user as mob) +/obj/machinery/mecha_part_fabricator/interact(mob/user as mob) var/dat, left_part if (..()) return - if(!operation_allowed(user)) - return user.set_machine(src) var/turf/exit = get_step(src,SOUTH) if(exit.density) - src.visible_message("\icon[src] [src] beeps, \"Error! Part outlet is obstructed\".") + visible_message("\icon[src] \The [src] beeps, \"Error! Part outlet is obstructed.\"") return if(temp) left_part = temp - else if(src.being_built) - left_part = {"Building [src.being_built.name].
+ else if(being_built) + var/obj/I = being_built.build_path + left_part = {"Building [initial(I.name)].
Please wait until completion...
"} else switch(screen) @@ -536,13 +322,13 @@ left_part = output_available_resources()+"
" left_part += "Sync with R&D servers
" for(var/part_set in part_sets) - left_part += "[part_set] - \[Add all parts to queue\]
" + left_part += "
[part_set] - \[Add all parts to queue\]
" if("parts") left_part += output_parts_list(part_set) left_part += "
Return" dat = {" - [src.name] + [name]