diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..7e9a359
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,8 @@
+# These are supported funding model platforms
+
+github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
+patreon: linuxgurugamer
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
+custom: # Replace with a single custom sponsorship URL
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f94dd14
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+obj/
+bin/
+*.user
+*.suo
+.vs/
+*~
+*.dll
diff --git a/ChangeLog.txt b/ChangeLog.txt
new file mode 100644
index 0000000..b78dfa4
--- /dev/null
+++ b/ChangeLog.txt
@@ -0,0 +1,186 @@
+ChangeLog
+
+1.9.20.5
+
+ Thanks to github user @averageksp for this:
+ Add German Translation for ScienceAlert
+
+1.9.20.4
+ Thanks to github user @ch3zych3z for this:
+ Added RU localization
+
+1.9.20.3
+ Thanks to github user @frankieorabona for this:
+ Updated Italian translation
+
+1.9.10.2
+ Fixed path for loading files (broken by new launcher)
+
+1.9.10.1
+ Fixed small memory leak caused by not releasing callback from GameEvents
+
+1.9.10
+ Thanks to github user @peterhaneve for this:
+ Optimize profile saving (reduce persistent file size), saves space and speeds up loading and saving
+
+1.9.9.3
+ Added AssemblyFileVersion
+ Updated version file for 1.12
+
+1.9.9.2
+ Changed fix to properly add a default key in the ProfileManager
+
+1.9.9.1
+ Thanks to github user @kfsone for pointing out this error:
+ added missing ! in ScienceAlertProfileManager.cs to void a null ref exception
+
+1.9.9
+ Disabled some unused code
+ Thanks to github user @frankieorabona for this:
+ Italian Localization
+
+1.9.8.9
+ Added check to "ScienceAlertProfileManager.OnSave" check that a game is loaded before trying to save data
+
+1.9.8.8
+ Replaced sheet-38 with original sheet-38 (animation was sharper)
+ Changed the loading of the sheets from the database to toolbarController.LoadImageFromFile
+
+1.9.8.7
+ Fixed Collect all to be visible even when only one science container on vessel
+ Thanks to @Fitiales for a spanish translation
+ a single Kerbal doesn't have a "collect all" action.
+ Added support for the DMagic experiments
+ Added support for DMModuleScienceAnimateGeneric
+ Added check for old version of DMModuleScienceAnimateGeneric (disables if less than 0.23)
+ Thanks to githb user @Fitiales:
+ Added spanish translation
+
+1.9.8.6
+ Fixed initialization of variables in DraggableWindow (two Awake() methods were conflicting)
+
+1.9.8.5
+ Moved initialization of variables into Awake
+
+1.9.8.4
+ Moved the Localization directory & file into the release directory
+
+1.9.8.3
+ Some localization changes
+
+1.9.8.2
+ Replaced embedded resource images with files
+ Removed 120 lines related to embedded resource images
+ Found a static GUISkin which was causing the options window to be double width
+ Commented out a line in Settings which was setting the background to null
+ Restored the missing controls to close the window, lock the window, etc
+
+1.9.8.1
+ Thanks to @Gordon_Dry for this:
+ Simplification of zzz_fix_biomeMask_situationMask_0.cfg
+ Sanity fix for RP-0 (RP-1)
+ Update zzz_fix_biomeMask_situationMask_0.cfg
+
+ See
+ https://forum.kerbalspaceprogram.com/index.php?/topic/175772-15-*
+ and following posts. A simplification of the patch.
+
+1.9.8
+ Updated for KSP 1.8
+
+1.9.7.1
+ Fixed "Deploy All" allowing an eva when eva's aren't allowed
+
+1.9.7
+ Added Install Checker
+ Updated AssemblyVersion
+
+1.9.6.2
+ Fixed Collect All button to be visible whenever any science container has spare capacity
+ (note that most science containers seem to have unlimited capacity)
+
+1.9.6.1
+ Added button to mapview
+
+1.9.6
+ Fixed the Collect All so it now works with science containers which have a gui available in the PAW
+ Added check so that if no science containers are available, the button will be greyed out
+ Now doesn't show the Collect All if no data is available to be collected
+
+1.9.5.4
+ Replaced ugly GOTO code
+ Added more checks for null in StorageCache.cs in RemoveMagicTransmitter()""
+ vessel.rootPart.Modules == null || vessel.Parts == null)
+
+1.9.5.2
+ Fixed saving of profiles
+ Fixed loading of profiles
+ Some optimizations by reducing duplicate calls
+ Following due to changes in KSP
+ Changed the OnLoad in the ScienceAlertProfileManager to calling a CoRoutine so it can wait until the scene is ready
+ Changed the OnVesselChange in the ScienceAlertProfileManager to calling a CoRoutine so it can wait until the OnLoad is complete
+
+1.9.5.1
+ Fixed issue where tourists could EVA
+ Updated .version file
+
+1.9.5
+ Fixed bug where coming out of timewarp to get science would lock the maneuver node
+
+1.9.4.4
+ Fixed download link in .version file
+ Moved ModuleManager configs into new folder called MM_Configs
+ Added contributed file from forum user @Gordon Dry to fix issues where biomeMask and situationMask are 0
+
+1.9.4.3
+ Version bump for 1.5 rebuild
+
+1.9.4.2
+ Thanks to github user @dariasc for this:
+ Change SurfaceSampleObserver requirements: Changed to go inline with the current status.
+ https://wiki.kerbalspaceprogram.com/wiki/Research_and_Development#Levels
+
+1.9.4.1
+ Following from 4x4cheesecake:
+ Science Alert now works along Kerbalism
+ Stored experiments are detected in all loaded vessels
+ Removed unnecessary line from AssemblyVersion.tt: <#@ assembly name="EnvDTE" #>
+
+1.9.4
+ Thanks to github & forum user @jefftimlin for this fix:
+ The BiomeFilter class attempted to generate a clean biome texture for the purposes of more accurate biome detection,
+ however it's expensive and complicated. Completely removed all of the complex code from this class to avoid the threading
+ issue entirely, and just made it use the ScienceUtil.GetExperimentBiome function, which seems to work well.
+ It makes the code faster, simpler, and safer.
+ Fixed an array index out of bounds problem in RequiresCrew.cs, which I found while debugging, which would intermittently
+ produce errors in the logs.
+ Added Collect All button to collect all science into any/all containers
+
+
+1.9.3
+ Added two colors to the buttons:
+ Yellow if the experiment needs to be reset before rerunning it
+ Red if the experiment cannot be reset
+
+1.9.2.3
+ Official release
+
+ Fixed nullref when going from flight to spacecenter
+ New icons for stock toolbar
+ Removed log spam for animation
+ Replaced foreach with for int on lists
+ Added a "Deploy All" button
+
+
+1.9.2.2
+ Deleted about 1150 lines of unneeded code related to the Toolbar
+ Added exclusion list for experiments and manufacturers
+
+1.9.2.1
+ fixed the missed repopulating a list after a revert??
+
+1.9.2
+ Adoption by LGG
+ Added support for ToolbarController
+ Added support for the ClickThrough Blocker
+ Removed old code used for the Blizzy Toolbar
diff --git a/GameData/ScienceAlert/LICENSE.txt b/GameData/ScienceAlert/LICENSE.txt
new file mode 100644
index 0000000..94a0453
--- /dev/null
+++ b/GameData/ScienceAlert/LICENSE.txt
@@ -0,0 +1,621 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 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 General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is 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. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ 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.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ 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 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. Use with the GNU Affero General Public License.
+
+ 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 Affero 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 special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 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 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 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
diff --git a/GameData/ScienceAlert/Localization/de-de.cfg b/GameData/ScienceAlert/Localization/de-de.cfg
new file mode 100644
index 0000000..c3b699f
--- /dev/null
+++ b/GameData/ScienceAlert/Localization/de-de.cfg
@@ -0,0 +1,78 @@
+Localization
+{
+ de-de
+ {
+ #ScienceAlert_title = Verfügbare Experiemente
+ #ScienceAlert_HaveScanData = Daten nicht gefunden
+ #ScienceAlert_Available = Keine Experiemente verfügbar
+ #ScienceAlert_DeployAll = Alle ausfahren
+ #ScienceAlert_DeployexEVA = Alle ausfahren, außer EVA
+ #ScienceAlert_CollectAll = Alles einsammeln
+ #ScienceAlert_Nocontainers = Alles einsammeln (keine Wissenschafts Behälter verfügbar)
+
+ // OptionUI
+ #ScienceAlert_Optitle = ScienceAlarm Optionen
+
+ #ScienceAlert_label1 = Globale Zeitraffer Einstellungen
+ #ScienceAlert_label2 = Globaler Alarm Ton
+ #ScienceAlert_label3 = Weitere Optionen
+ #ScienceAlert_label4 = UI-Einstellungen
+ #ScienceAlert_label5 = Globale Animationen anmachen
+ #ScienceAlert_label6 = Fenster Kapazität
+ #ScienceAlert_label7 = Weniger
+ #ScienceAlert_label8 = Mehr
+ #ScienceAlert_label9 = Optionen für die Integration von Drittanbietern
+ #ScienceAlert_label10 = Einstellungen für bemannte Raumfahrzeuge
+ #ScienceAlert_label11 = Profile: <<1>>
+ #ScienceAlert_label12 = Alarmgrenze
+ #ScienceAlert_label13 = Alarmgrenze: <<1>>
+ #ScienceAlert_label14 = (deaktiviert)
+ #ScienceAlert_label15 = Wissenschaftsmenge
+ #ScienceAlert_label16 = Kein Profil aktiv
+ #ScienceAlert_label17 = Wählen Sie ein Profil zum Laden
+ #ScienceAlert_label18 = Keine Profile gespeichert
+ #ScienceAlert_label19 = '<<1>>' Speichern?
+ #ScienceAlert_label20 = Profil '<<1>>' existiert bereits!
+
+ #ScienceAlert_button1 = Ununtersucht
+ #ScienceAlert_button2 = Nicht maximal
+ #ScienceAlert_button3 = < 50% gesammelt
+ #ScienceAlert_button4 = < 90% gesammelt
+ #ScienceAlert_button5 = Nach Experiment
+ #ScienceAlert_button6 = Global ein
+ #ScienceAlert_button7 = Global aus
+ #ScienceAlert_button8 = Immer
+ #ScienceAlert_button9 = Nie
+ #ScienceAlert_button10 = Abbruch
+ #ScienceAlert_button11 = SPEICHERN
+ #ScienceAlert_button12 = ABBRUCH
+ #ScienceAlert_button13 = Überschreiben
+ #ScienceAlert_button14 = UMBENNEN
+ #ScienceAlert_button15 = Bestätigen
+
+ #ScienceAlert_toggle1 = Berichtswert anzeigen
+ #ScienceAlert_toggle2 = Biome in der Experimentliste anzeigen
+ #ScienceAlert_toggle3 = EVA-Bericht zuerst auflisten
+ #ScienceAlert_toggle4 = SCANsat-Integration aktivieren
+ #ScienceAlert_toggle5 = Oberflächenprobe im Raumschiff verfolgen
+ #ScienceAlert_toggle6 = Aktiviert
+ #ScienceAlert_toggle7 = Animation bei Entdeckung
+ #ScienceAlert_toggle8 = Ton bei Entdeckung
+ #ScienceAlert_toggle9 = Zeitraffer bei Entdeckung stoppen
+ #ScienceAlert_toggle10 = Filtermethode
+
+ #ScienceAlert_Msg1title = SCANsat nicht gefunden
+ #ScienceAlert_Msg1 = SCANsat wurde nicht gefunden. Du musst SCANsat installieren, um diese Funktion zu nutzen.
+ #ScienceAlert_Msg1_button1 = Okay
+
+ #ScienceAlert_Msg2title = '<<1>>' umbenennen in:
+ #ScienceAlert_Msg2 = '<<1>>' existiert bereits. Überschreiben?
+ #ScienceAlert_Msg2title2 = Zielprofil umbenennen
+ #ScienceAlert_Msg2_button1 = Ja
+ #ScienceAlert_Msg2_button2 = Nein
+
+ #ScienceAlert_Msg3 = Bist du sicher, dass du '<<1>>' löschen möchtest?
+ #ScienceAlert_Msg3_2 = '<<1>>' laden?\nNicht gespeicherte Einstellungen gehen verloren.
+ #ScienceAlert_Msg3title = Wissenschafts-Alarm Popup öffnen
+ }
+}
diff --git a/GameData/ScienceAlert/Localization/en-us.cfg b/GameData/ScienceAlert/Localization/en-us.cfg
new file mode 100644
index 0000000..5f86e8b
--- /dev/null
+++ b/GameData/ScienceAlert/Localization/en-us.cfg
@@ -0,0 +1,78 @@
+Localization
+{
+ en-us
+ {
+ #ScienceAlert_title = Available Experiments
+ #ScienceAlert_HaveScanData = Data not found
+ #ScienceAlert_Available = no experiments available
+ #ScienceAlert_DeployAll = Deploy All
+ #ScienceAlert_DeployexEVA = Deploy All except EVA
+ #ScienceAlert_CollectAll = Collect All
+ #ScienceAlert_Nocontainers = Collect All (no science containers available)
+
+ //OptionUI
+ #ScienceAlert_Optitle = ScienceAlert Options
+
+ #ScienceAlert_label1 = Global Warp Settings
+ #ScienceAlert_label2 = Global Alert Sound
+ #ScienceAlert_label3 = Additional Options
+ #ScienceAlert_label4 = User Interface Settings
+ #ScienceAlert_label5 = Globally Enable Animation
+ #ScienceAlert_label6 = Window Opacity
+ #ScienceAlert_label7 = Less
+ #ScienceAlert_label8 = More
+ #ScienceAlert_label9 = Third-party Integration Options
+ #ScienceAlert_label10 = Crewed Vessel Settings
+ #ScienceAlert_label11 = Profile: <<1>>
+ #ScienceAlert_label12 = Alert Threshold
+ #ScienceAlert_label13 = Alert Threshold: <<1>>
+ #ScienceAlert_label14 = (disabled)
+ #ScienceAlert_label15 = Science Amount
+ #ScienceAlert_label16 = No profile active
+ #ScienceAlert_label17 = Select a profile to load
+ #ScienceAlert_label18 = No profiles saved
+ #ScienceAlert_label19 = SAVE '<<1>>'?
+ #ScienceAlert_label20 = Profile '<<1>>' already exists!
+
+ #ScienceAlert_button1 = Unresearched
+ #ScienceAlert_button2 = Not maxed
+ #ScienceAlert_button3 = < 50% collected
+ #ScienceAlert_button4 = < 90% collected
+ #ScienceAlert_button5 = By Experiment
+ #ScienceAlert_button6 = Globally on
+ #ScienceAlert_button7 = Globally off
+ #ScienceAlert_button8 = Always
+ #ScienceAlert_button9 = Never
+ #ScienceAlert_button10 = Cancel
+ #ScienceAlert_button11 = SAVE
+ #ScienceAlert_button12 = CANCEL
+ #ScienceAlert_button13 = Overwrite
+ #ScienceAlert_button14 = RENAME
+ #ScienceAlert_button15 = Confirm
+
+ #ScienceAlert_toggle1 = Display Report Value
+ #ScienceAlert_toggle2 = Display Biome in Experiment List
+ #ScienceAlert_toggle3 = List EVA Report first
+ #ScienceAlert_toggle4 = Enable SCANsat integration
+ #ScienceAlert_toggle5 = Track surface sample in vessel
+ #ScienceAlert_toggle6 = Enabled
+ #ScienceAlert_toggle7 = Animation on discovery
+ #ScienceAlert_toggle8 = Sound on discovery
+ #ScienceAlert_toggle9 = Stop warp on discovery
+ #ScienceAlert_toggle10 = Filter Method
+
+ #ScienceAlert_Msg1title = SCANsat Not Found
+ #ScienceAlert_Msg1 = SCANsat was not found. You must install SCANsat to use this feature.
+ #ScienceAlert_Msg1_button1 = Okay
+
+ #ScienceAlert_Msg2title = Rename '<<1>>' to:
+ #ScienceAlert_Msg2 = '<<1>>' already exists. Overwrite?
+ #ScienceAlert_Msg2title2 = Rename Target Profile
+ #ScienceAlert_Msg2_button1 = Yes
+ #ScienceAlert_Msg2_button2 = No
+
+ #ScienceAlert_Msg3 = Are you sure you want to\ndelete '<<1>>'?
+ #ScienceAlert_Msg3_2 = Load '<<1>>'?\nUnsaved settings will be lost.
+ #ScienceAlert_Msg3title = Science Alert Open Popup
+ }
+}
diff --git a/GameData/ScienceAlert/Localization/es-es.cfg b/GameData/ScienceAlert/Localization/es-es.cfg
new file mode 100644
index 0000000..fe77220
--- /dev/null
+++ b/GameData/ScienceAlert/Localization/es-es.cfg
@@ -0,0 +1,78 @@
+Localization
+{
+ es-es
+ {
+ #ScienceAlert_title = Experimentos Disponibles
+ #ScienceAlert_HaveScanData = Datos no encontrados
+ #ScienceAlert_Available = no hay experimentos disponibles
+ #ScienceAlert_DeployAll = Desplegar todo
+ #ScienceAlert_DeployexEVA = Desplegar todo excepto AEV
+ #ScienceAlert_CollectAll = Recoger Todo
+ #ScienceAlert_Nocontainers = Recoger Todo (no hay contenedores de ciencias disponibles)
+
+ //OptionUI
+ #ScienceAlert_Optitle = Opciones de ScienceAlert
+
+ #ScienceAlert_label1 = Configuración global de Deformación
+ #ScienceAlert_label2 = Sonido de alerta global
+ #ScienceAlert_label3 = Opciones adicionales
+ #ScienceAlert_label4 = Configuraciones de interfaz de usuario
+ #ScienceAlert_label5 = Habilitar globalmente animación
+ #ScienceAlert_label6 = Opacidad de ventana
+ #ScienceAlert_label7 = Menos
+ #ScienceAlert_label8 = Más
+ #ScienceAlert_label9 = Opciones de integración de terceros
+ #ScienceAlert_label10 = Configuración de la nave con tripulación
+ #ScienceAlert_label11 = Perfil: <<1>>
+ #ScienceAlert_label12 = Umbral de alerta
+ #ScienceAlert_label13 = Umbral de alerta: <<1>>
+ #ScienceAlert_label14 = (deshabilitado)
+ #ScienceAlert_label15 = Cantidad de ciencia
+ #ScienceAlert_label16 = Ningún perfil activo
+ #ScienceAlert_label17 = Seleccione un perfil para cargar
+ #ScienceAlert_label18 = No hay perfiles guardados
+ #ScienceAlert_label19 = SALVAR '<<1>>'?
+ #ScienceAlert_label20 = ¡El perfil '<<1>>' ya existe!
+
+ #ScienceAlert_button1 = No investigado
+ #ScienceAlert_button2 = No maximizado
+ #ScienceAlert_button3 = < 50% recogido
+ #ScienceAlert_button4 = < 90% recogido
+ #ScienceAlert_button5 = Por Experimento
+ #ScienceAlert_button6 = Globalmente encendido
+ #ScienceAlert_button7 = Globalmente apagado
+ #ScienceAlert_button8 = Siempre
+ #ScienceAlert_button9 = Nunca
+ #ScienceAlert_button10 = Cancelar
+ #ScienceAlert_button11 = SALVAR
+ #ScienceAlert_button12 = CANCELAR
+ #ScienceAlert_button13 = Sobrescribir
+ #ScienceAlert_button14 = RENOMBRAR
+ #ScienceAlert_button15 = Confirmar
+
+ #ScienceAlert_toggle1 = Mostrar valor del informe
+ #ScienceAlert_toggle2 = Mostrar bioma en la lista de experimentos
+ #ScienceAlert_toggle3 = Listar el Informe AEV primero
+ #ScienceAlert_toggle4 = Habilitar la integración SCANsat
+ #ScienceAlert_toggle5 = Seguir la muestra de superficie en la nave
+ #ScienceAlert_toggle6 = Habilitado
+ #ScienceAlert_toggle7 = Animación al descubrir
+ #ScienceAlert_toggle8 = Sonido al descubrir
+ #ScienceAlert_toggle9 = Detener la deformación al descubrir
+ #ScienceAlert_toggle10 = Método de filtro
+
+ #ScienceAlert_Msg1title = SCANsat no encontrado
+ #ScienceAlert_Msg1 = SCANsat no se encontró. Debe instalar SCANsat para usar esta función.
+ #ScienceAlert_Msg1_button1 = OK
+
+ #ScienceAlert_Msg2title = Renombrar '<<1>>' a:
+ #ScienceAlert_Msg2 = '<<1>>' ya existe. ¿Sobrescribir?
+ #ScienceAlert_Msg2title2 = Renombrar perfil de destino
+ #ScienceAlert_Msg2_button1 = Sí
+ #ScienceAlert_Msg2_button2 = No
+
+ #ScienceAlert_Msg3 = ¿Estás seguro de que quieres\neliminar '<<1>>'?
+ #ScienceAlert_Msg3_2 = ¿Cargar '<<1>>'?\nLa configuración no guardada se perderá.
+ #ScienceAlert_Msg3title = Ventana emergente de alerta de ciencia
+ }
+}
diff --git a/GameData/ScienceAlert/Localization/it-it.cfg b/GameData/ScienceAlert/Localization/it-it.cfg
new file mode 100644
index 0000000..158432b
--- /dev/null
+++ b/GameData/ScienceAlert/Localization/it-it.cfg
@@ -0,0 +1,78 @@
+Localization
+{
+ it-it
+ {
+ #ScienceAlert_title = Esperimenti Disponibili
+ #ScienceAlert_HaveScanData = Dati non trovati
+ #ScienceAlert_Available = nessun esperimento disponibile
+ #ScienceAlert_DeployAll = Distribuisci tutto
+ #ScienceAlert_DeployexEVA = Distribuisci tutto tranne EVA
+ #ScienceAlert_CollectAll = Raccogli tutto
+ #ScienceAlert_Nocontainers = Raccogli tutto (nessun contenitore scientifico disponibile)
+
+ //OptionUI
+ #ScienceAlert_Optitle = Opzioni ScienceAlert
+
+ #ScienceAlert_label1 = Global Warp Settings
+ #ScienceAlert_label2 = Global Alert Sound
+ #ScienceAlert_label3 = Opzioni Aggiuntive
+ #ScienceAlert_label4 = Impostazioni Interfaccia UTente
+ #ScienceAlert_label5 = Abilita Animazione Globalmente
+ #ScienceAlert_label6 = Opacità FInestra
+ #ScienceAlert_label7 = Meno
+ #ScienceAlert_label8 = Più
+ #ScienceAlert_label9 = Opzioni di integrazione di terze parti
+ #ScienceAlert_label10 = Impostazioni Veicolo con Equipaggio
+ #ScienceAlert_label11 = Profilo: <<1>>
+ #ScienceAlert_label12 = Soglia di Allarme
+ #ScienceAlert_label13 = Soglia di Allarme: <<1>>
+ #ScienceAlert_label14 = (disabilitato)
+ #ScienceAlert_label15 = Quantità di Scienza
+ #ScienceAlert_label16 = Nessun profilo attivo
+ #ScienceAlert_label17 = Selezionare un profilo da caricare
+ #ScienceAlert_label18 = Nessun profilo salvato
+ #ScienceAlert_label19 = SALVA '<<1>>'?
+ #ScienceAlert_label20 = Il profilo '<<1>>' esiste già!
+
+ #ScienceAlert_button1 = Non ricercato
+ #ScienceAlert_button2 = Not maxed
+ #ScienceAlert_button3 = < 50% raccolta
+ #ScienceAlert_button4 = < 90% raccolta
+ #ScienceAlert_button5 = Per Esperimento
+ #ScienceAlert_button6 = Globalmente on
+ #ScienceAlert_button7 = Globalmente off
+ #ScienceAlert_button8 = Sempre
+ #ScienceAlert_button9 = Mai
+ #ScienceAlert_button10 = Annulla
+ #ScienceAlert_button11 = SALVA
+ #ScienceAlert_button12 = ANNULLA
+ #ScienceAlert_button13 = Sovrascrivi
+ #ScienceAlert_button14 = RINOMINA
+ #ScienceAlert_button15 = Conferma
+
+ #ScienceAlert_toggle1 = Mostra Valore Rapporto
+ #ScienceAlert_toggle2 = Visualizza Bioma nella Lista Esperimenti
+ #ScienceAlert_toggle3 = Elenca Prima Rapporto EVA
+ #ScienceAlert_toggle4 = Abilita l'integrazione di SCANsat
+ #ScienceAlert_toggle5 = Traccia campione di superficie sul veicolo
+ #ScienceAlert_toggle6 = Abilitato
+ #ScienceAlert_toggle7 = Animazione sulla scoperta
+ #ScienceAlert_toggle8 = Suono alla scoperta
+ #ScienceAlert_toggle9 = Ferma Accellerazione Temp. alla scoperta
+ #ScienceAlert_toggle10 = Metodo del filtro
+
+ #ScienceAlert_Msg1title = SCANsat Non Trovato
+ #ScienceAlert_Msg1 = SCANsat non è stato trovato. È necessario installare SCANsat per utilizzare questa funzione.
+ #ScienceAlert_Msg1_button1 = Okay
+
+ #ScienceAlert_Msg2title = Rinomina '<<1>>' in:
+ #ScienceAlert_Msg2 = '<<1>>' esiste già. Vuoi sovrascriverlo?
+ #ScienceAlert_Msg2title2 = Rinomina Profilo Obiettivo
+ #ScienceAlert_Msg2_button1 = Sì
+ #ScienceAlert_Msg2_button2 = No
+
+ #ScienceAlert_Msg3 = Sei sicuro di voler\neliminare '<<1>>'?
+ #ScienceAlert_Msg3_2 = Carica '<<1>>'?\nLE impostazioni non salvate saranno perse.
+ #ScienceAlert_Msg3title = Finestra pop-up di avviso scientifico
+ }
+}
diff --git a/GameData/ScienceAlert/Localization/ru-ru.cfg b/GameData/ScienceAlert/Localization/ru-ru.cfg
new file mode 100644
index 0000000..6ca5c1e
--- /dev/null
+++ b/GameData/ScienceAlert/Localization/ru-ru.cfg
@@ -0,0 +1,78 @@
+Localization
+{
+ ru-ru
+ {
+ #ScienceAlert_title = Доступные эксперименты
+ #ScienceAlert_HaveScanData = Данные не найдены
+ #ScienceAlert_Available = нет доступных экспериментов
+ #ScienceAlert_DeployAll = Провести все
+ #ScienceAlert_DeployexEVA = Провести все, кроме внекорабельной деятельности
+ #ScienceAlert_CollectAll = Собрать все
+ #ScienceAlert_Nocontainers = Собрать все (нет доступных контейнеров для экспериментов)
+
+ //OptionUI
+ #ScienceAlert_Optitle = Настройки ScienceAlert
+
+ #ScienceAlert_label1 = Глобальные настройки ускорения времени
+ #ScienceAlert_label2 = Глобальные настройки звуков уведомлений
+ #ScienceAlert_label3 = Дополнительные настройки
+ #ScienceAlert_label4 = Настройки интерфейса
+ #ScienceAlert_label5 = Глобально включить анимацию
+ #ScienceAlert_label6 = Прозрачность окон
+ #ScienceAlert_label7 = Меньше
+ #ScienceAlert_label8 = Больше
+ #ScienceAlert_label9 = Настройки интеграции с другими модами
+ #ScienceAlert_label10 = Настройки корабля с экипажем
+ #ScienceAlert_label11 = Профиль: <<1>>
+ #ScienceAlert_label12 = Порог уведомления
+ #ScienceAlert_label13 = Порог уведомления: <<1>>
+ #ScienceAlert_label14 = (отключено)
+ #ScienceAlert_label15 = Количество очков науки
+ #ScienceAlert_label16 = Нет активного профиля
+ #ScienceAlert_label17 = Выберите профиль для загрузки
+ #ScienceAlert_label18 = Ни один профиль не сохранен
+ #ScienceAlert_label19 = Сохранить '<<1>>'?
+ #ScienceAlert_label20 = Профиль '<<1>>' уже существует!
+
+ #ScienceAlert_button1 = Не исследовано
+ #ScienceAlert_button2 = Не получено максимального значения
+ #ScienceAlert_button3 = < 50% собрано
+ #ScienceAlert_button4 = < 90% собрано
+ #ScienceAlert_button5 = By Experiment
+ #ScienceAlert_button6 = Глобально включено
+ #ScienceAlert_button7 = Глобально выключено
+ #ScienceAlert_button8 = Всегда
+ #ScienceAlert_button9 = Никогда
+ #ScienceAlert_button10 = Отменить
+ #ScienceAlert_button11 = Сохранить
+ #ScienceAlert_button12 = Отменить
+ #ScienceAlert_button13 = Перезаписать
+ #ScienceAlert_button14 = Переименовать
+ #ScienceAlert_button15 = Подтвердить
+
+ #ScienceAlert_toggle1 = Показывать отчет
+ #ScienceAlert_toggle2 = Показывать биом в списке экспериментов
+ #ScienceAlert_toggle3 = Отображать отчет о внекорабельной деятельности первым
+ #ScienceAlert_toggle4 = Включить интеграцию с SCANsat
+ #ScienceAlert_toggle5 = Отслеживать образец грунта внутри корабля
+ #ScienceAlert_toggle6 = Включено
+ #ScienceAlert_toggle7 = Анимация при возможности провести эксперимент
+ #ScienceAlert_toggle8 = Звук при возможности провести эксперимент
+ #ScienceAlert_toggle9 = Выключить ускорение времени при возможности провести эксперимент
+ #ScienceAlert_toggle10 = Метод фильтрации
+
+ #ScienceAlert_Msg1title = SCANsat не обнаружен
+ #ScienceAlert_Msg1 = SCANsat не обнаружен. Чтобы использовать это, Вы должны установить SCANsat.
+ #ScienceAlert_Msg1_button1 = Понятно
+
+ #ScienceAlert_Msg2title = Переименоваьт '<<1>>' в:
+ #ScienceAlert_Msg2 = '<<1>>' уже существует. Перезаписать?
+ #ScienceAlert_Msg2title2 = Переименовать профиль?
+ #ScienceAlert_Msg2_button1 = Да
+ #ScienceAlert_Msg2_button2 = Нет
+
+ #ScienceAlert_Msg3 = Вы уверены, что хотите\nудалить '<<1>>'?
+ #ScienceAlert_Msg3_2 = Загрузить '<<1>>'?\nНесохраненные данные будут потеряны.
+ #ScienceAlert_Msg3title = Всплывающее окно Science Alert
+ }
+}
diff --git a/GameData/ScienceAlert/MM_Configs/ExcludedExperiments.cfg b/GameData/ScienceAlert/MM_Configs/ExcludedExperiments.cfg
new file mode 100644
index 0000000..26a26bd
--- /dev/null
+++ b/GameData/ScienceAlert/MM_Configs/ExcludedExperiments.cfg
@@ -0,0 +1,47 @@
+KEI_EXCLUDED_EXPERIMENTS
+{
+ experiment = SEP_SolarwindSpectrum
+ experiment = SEP_CCIDscan
+ experiment = error
+ experiment = waitWhat
+
+ experiment = hullcampicture
+
+ // Following from the WildBlueIndustries mod
+ experiment = WBISpaceResearch
+ experiment = WBISpaceAdaptionStudy
+ experiment = WBIPowerToolsEvaluation
+ experiment = WBIConstructionTechniques
+ experiment = WBICrystalGrowth
+ experiment = WBIIceCreamResearch
+ experiment = WBITemperatureStudy
+ experiment = WBIThermalStudy
+ experiment = WBIGooStudy
+ experiment = WBICryogenicResourceStudy
+ experiment = WBILongTermCryogenicMiniStudy
+ experiment = WBIMESS
+ experiment = WBICryogenicStudy
+ experiment = WBILongTermCryogenicStudy
+ experiment = WBICryogenicRadiationStudy
+ experiment = WBISurfaceConstructionStudy
+ experiment = WBIKNUTS
+ experiment = WBIBRE
+ experiment = WBISAME
+ experiment = WBICoreSampleAnalysis
+ experiment = WBIBiomeAnalysis
+ experiment = WBISoilAnalysis
+ experiment = WBIMetallurgyAnalysis
+ experiment = WBIChemicalAnalysis
+ experiment = WBIExtractionAnalysis
+
+ experiment = GravioliumStudy
+ experiment = wbiSaucerResearchExperiment
+
+
+ // Nehemia Engineering Orbital Science
+ experiment = NE_KEES_ODC
+ experiment = NE_KEES_POSA1
+ experiment = NE_KEES_POSA2
+ experiment = NE_KEES_PPMD
+ experiment = NE_KEES_TEST
+}
diff --git a/GameData/ScienceAlert/MM_Configs/ExcludedManufacturers.cfg b/GameData/ScienceAlert/MM_Configs/ExcludedManufacturers.cfg
new file mode 100644
index 0000000..736ab9e
--- /dev/null
+++ b/GameData/ScienceAlert/MM_Configs/ExcludedManufacturers.cfg
@@ -0,0 +1,4 @@
+KEI_EXCLUDED_MANUFACTURERS
+{
+ manufacturer = Station Science Directorate
+}
diff --git a/Textures/btnBackground.png b/GameData/ScienceAlert/PluginData/Textures/btnBackground.png
similarity index 100%
rename from Textures/btnBackground.png
rename to GameData/ScienceAlert/PluginData/Textures/btnBackground.png
diff --git a/Textures/btnClose.png b/GameData/ScienceAlert/PluginData/Textures/btnClose.png
similarity index 100%
rename from Textures/btnClose.png
rename to GameData/ScienceAlert/PluginData/Textures/btnClose.png
diff --git a/Textures/btnDelete.png b/GameData/ScienceAlert/PluginData/Textures/btnDelete.png
similarity index 100%
rename from Textures/btnDelete.png
rename to GameData/ScienceAlert/PluginData/Textures/btnDelete.png
diff --git a/Textures/btnExpand.png b/GameData/ScienceAlert/PluginData/Textures/btnExpand.png
similarity index 100%
rename from Textures/btnExpand.png
rename to GameData/ScienceAlert/PluginData/Textures/btnExpand.png
diff --git a/Textures/btnLock.png b/GameData/ScienceAlert/PluginData/Textures/btnLock.png
similarity index 100%
rename from Textures/btnLock.png
rename to GameData/ScienceAlert/PluginData/Textures/btnLock.png
diff --git a/Textures/btnOpen.png b/GameData/ScienceAlert/PluginData/Textures/btnOpen.png
similarity index 100%
rename from Textures/btnOpen.png
rename to GameData/ScienceAlert/PluginData/Textures/btnOpen.png
diff --git a/Textures/btnRename.png b/GameData/ScienceAlert/PluginData/Textures/btnRename.png
similarity index 100%
rename from Textures/btnRename.png
rename to GameData/ScienceAlert/PluginData/Textures/btnRename.png
diff --git a/Textures/btnSave.png b/GameData/ScienceAlert/PluginData/Textures/btnSave.png
similarity index 100%
rename from Textures/btnSave.png
rename to GameData/ScienceAlert/PluginData/Textures/btnSave.png
diff --git a/Textures/btnUnlock.png b/GameData/ScienceAlert/PluginData/Textures/btnUnlock.png
similarity index 100%
rename from Textures/btnUnlock.png
rename to GameData/ScienceAlert/PluginData/Textures/btnUnlock.png
diff --git a/GameData/ScienceAlert/PluginData/Textures/flask-38.png b/GameData/ScienceAlert/PluginData/Textures/flask-38.png
new file mode 100644
index 0000000..5bcad7a
Binary files /dev/null and b/GameData/ScienceAlert/PluginData/Textures/flask-38.png differ
diff --git a/GameData/ScienceAlert/PluginData/Textures/flask.png b/GameData/ScienceAlert/PluginData/Textures/flask.png
new file mode 100644
index 0000000..2058c08
Binary files /dev/null and b/GameData/ScienceAlert/PluginData/Textures/flask.png differ
diff --git a/GameData/ScienceAlert/PluginData/Textures/flask_256.png b/GameData/ScienceAlert/PluginData/Textures/flask_256.png
new file mode 100644
index 0000000..2d97c9f
Binary files /dev/null and b/GameData/ScienceAlert/PluginData/Textures/flask_256.png differ
diff --git a/GameData/ScienceAlert/PluginData/Textures/flask_64.png b/GameData/ScienceAlert/PluginData/Textures/flask_64.png
new file mode 100644
index 0000000..d5920d1
Binary files /dev/null and b/GameData/ScienceAlert/PluginData/Textures/flask_64.png differ
diff --git a/GameData/ScienceAlert/PluginData/Textures/sheet-38-unused.png b/GameData/ScienceAlert/PluginData/Textures/sheet-38-unused.png
new file mode 100644
index 0000000..d272a90
Binary files /dev/null and b/GameData/ScienceAlert/PluginData/Textures/sheet-38-unused.png differ
diff --git a/GameData/ScienceAlert/PluginData/Textures/sheet-38.png b/GameData/ScienceAlert/PluginData/Textures/sheet-38.png
new file mode 100644
index 0000000..77c4f58
Binary files /dev/null and b/GameData/ScienceAlert/PluginData/Textures/sheet-38.png differ
diff --git a/Textures/sheet.png b/GameData/ScienceAlert/PluginData/Textures/sheet.png
similarity index 100%
rename from Textures/sheet.png
rename to GameData/ScienceAlert/PluginData/Textures/sheet.png
diff --git a/GameData/ScienceAlert/PluginData/profiles.cfg b/GameData/ScienceAlert/PluginData/profiles.cfg
new file mode 100644
index 0000000..66312ba
--- /dev/null
+++ b/GameData/ScienceAlert/PluginData/profiles.cfg
@@ -0,0 +1,1221 @@
+Stored_Profiles
+{
+ PROFILE
+ {
+ name = default
+ modified = False
+ scienceThreshold = 0
+ NE_KEES_TEST
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KEES_PPMD
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KEES_ODC
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KEES_POSA1
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KEES_POSA2
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KeminiTEST
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KeminiD5
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KeminiD8
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KeminiMSC3
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KeminiD10
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KeminiD7
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_ADUM
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_SpiU
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_Test
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_FLEX
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_CFI
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_CCF
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_CFE
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_MEE1
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_MEE2
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_MIS1
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_MIS2
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_MIS3
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_CVB
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_PACE
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ crewReport
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ evaReport
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ mysteryGoo
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ surfaceSample
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ mobileMaterialsLab
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ temperatureScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ barometerScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ seismicScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ gravityScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ atmosphereAnalysis
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ asteroidSample
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ infraredTelescope
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ recovery
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ FASAmysteryGoo
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ FASAlaserSurfaceSample
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ GeminiVesselReport
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ MercuryVesselReport
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ magScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ rpwsScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ scopeScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmImagingPlatform
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmSIGINT
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmReconScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmNAlbedoScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmXRayDiffract
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmlaserblastscan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmSolarParticles
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmSoilMoisture
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmAsteroidScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmRadiometerScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmseismicHammer
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmbathymetryscan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmbiodrillscan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ AnomalyScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ TargetScanning
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ GeigerCounter
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ ApolloStatusReport
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ LEMvesselReport
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ LEMlandingReport
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ ALSEPenvironmentScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ ALSEPsurfaceScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ ALSEPreflectorExp
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ }
+ PROFILE
+ {
+ name = test
+ modified = False
+ scienceThreshold = 0
+ NE_KEES_TEST
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KEES_PPMD
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KEES_ODC
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KEES_POSA1
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KEES_POSA2
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KeminiTEST
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KeminiD5
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KeminiD8
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KeminiMSC3
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KeminiD10
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_KeminiD7
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_ADUM
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_SpiU
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_Test
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_FLEX
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_CFI
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_CCF
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_CFE
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_MEE1
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_MEE2
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_MIS1
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_MIS2
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_MIS3
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_CVB
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ NE_PACE
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ crewReport
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ evaReport
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ mysteryGoo
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ surfaceSample
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ mobileMaterialsLab
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ temperatureScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ barometerScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ seismicScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ gravityScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ atmosphereAnalysis
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ asteroidSample
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ infraredTelescope
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ recovery
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ FASAmysteryGoo
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ FASAlaserSurfaceSample
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ GeminiVesselReport
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ MercuryVesselReport
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ magScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ rpwsScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ scopeScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmImagingPlatform
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmSIGINT
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmReconScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmNAlbedoScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmXRayDiffract
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmlaserblastscan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmSolarParticles
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmSoilMoisture
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmAsteroidScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmRadiometerScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmseismicHammer
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmbathymetryscan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ dmbiodrillscan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ AnomalyScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ TargetScanning
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ GeigerCounter
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ ApolloStatusReport
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ LEMvesselReport
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ LEMlandingReport
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ ALSEPenvironmentScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ ALSEPsurfaceScan
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = False
+ Filter = Unresearched
+ IsDefault = False
+ }
+ ALSEPreflectorExp
+ {
+ Enabled = True
+ SoundOnDiscovery = True
+ AnimationOnDiscovery = True
+ StopWarpOnDiscovery = True
+ Filter = Unresearched
+ IsDefault = False
+ }
+ }
+}
diff --git a/GameData/ScienceAlert/PluginData/settings.cfg b/GameData/ScienceAlert/PluginData/settings.cfg
new file mode 100644
index 0000000..8320f0e
--- /dev/null
+++ b/GameData/ScienceAlert/PluginData/settings.cfg
@@ -0,0 +1,63 @@
+DebugMode = False
+TimeWarpCheckThreshold = 5
+WindowOpacity = 255
+EvaReportOnTop = True
+ScanInterfaceType = None
+ToolbarInterfaceType = BlizzyToolbar
+additional
+{
+ config
+ {
+ OptionsWindow
+ {
+ WindowX = 1239
+ WindowY = 122
+ Draggable = True
+ Visible = False
+ }
+ ExperimentWindow
+ {
+ WindowX = 813
+ WindowY = 95
+ Draggable = True
+ Visible = False
+ }
+ DebugWindow
+ {
+ WindowX = 840
+ WindowY = 525
+ Draggable = True
+ Visible = False
+ }
+ }
+}
+General
+{
+ GlobalWarp = ByExperiment
+ SoundNotification = ByExperiment
+ EvaAtmospherePressureWarnThreshold = 0.00035
+ EvaAtmosphereVelocityWarnThreshold = 30
+}
+UserInterface
+{
+ ShowReportValue = True
+ DisplayCurrentBiome = False
+ FlaskAnimationEnabled = True
+ StarFlaskFrameRate = 24
+}
+CrewedVesselSettings
+{
+ CheckSurfaceSampleNotEva = False
+}
+LogSettings
+{
+ LogMask = 0
+ // Bit index = message type
+ // Bit 0 = None
+ // Bit 1 = Normal
+ // Bit 2 = Debug
+ // Bit 3 = Verbose
+ // Bit 4 = Performance
+ // Bit 5 = Warning
+ // Bit 6 = Error
+}
diff --git a/GameData/ScienceAlert/Plugins/ScienceAlert.pdb b/GameData/ScienceAlert/Plugins/ScienceAlert.pdb
new file mode 100644
index 0000000..ef19a44
Binary files /dev/null and b/GameData/ScienceAlert/Plugins/ScienceAlert.pdb differ
diff --git a/GameData/ScienceAlert/README.md b/GameData/ScienceAlert/README.md
new file mode 100644
index 0000000..bdc94a6
--- /dev/null
+++ b/GameData/ScienceAlert/README.md
@@ -0,0 +1,11 @@
+# ScienceAlert Updated
+
+This is a minor updated version of the Kerbal Space Program mod ScienceAlert (see original here: https://github.com/DennyTX/ScienceAlert) to fix a few bugs.
+
+
+TODO
+
+Significant FPS drop
+
+
+I just got this, and started a new game. When I go on EVA and get an EVA report, then hit keep, it doesnt show it for review on my kerbal or when I get back to my capsule. Transmitting data does not seem to work even when having an external antenna.
\ No newline at end of file
diff --git a/GameData/ScienceAlert/ScienceAlert.version b/GameData/ScienceAlert/ScienceAlert.version
new file mode 100644
index 0000000..45c2002
--- /dev/null
+++ b/GameData/ScienceAlert/ScienceAlert.version
@@ -0,0 +1,30 @@
+{
+ "NAME": "ScienceAlert",
+ "URL": "https://raw.githubusercontent.com/linuxgurugamer/ScienceAlert/refs/heads/master/ScienceAlert.version",
+ "DOWNLOAD": "https://spacedock.info/mod/1886/ScienceAlert%20ReAlerted",
+ "GITHUB": {
+ "USERNAME": "linuxgurugamer",
+ "REPOSITORY": "ScienceAlert"
+ },
+ "VERSION": {
+ "MAJOR": 1,
+ "MINOR": 9,
+ "PATCH": 20,
+ "BUILD": 5
+ },
+ "KSP_VERSION": {
+ "MAJOR": 1,
+ "MINOR": 12,
+ "PATCH": 5
+ },
+ "KSP_VERSION_MIN": {
+ "MAJOR": 1,
+ "MINOR": 9,
+ "PATCH": 0
+ },
+ "KSP_VERSION_MAX": {
+ "MAJOR": 1,
+ "MINOR": 12,
+ "PATCH": 99
+ }
+}
diff --git a/GameData/ScienceAlert/ScienceAlert.version.1-12-3 b/GameData/ScienceAlert/ScienceAlert.version.1-12-3
new file mode 100644
index 0000000..9a45381
--- /dev/null
+++ b/GameData/ScienceAlert/ScienceAlert.version.1-12-3
@@ -0,0 +1,25 @@
+{
+ "NAME": "ScienceAlert",
+ "URL": "http://ksp.spacetux.net/avc/ScienceAlert",
+ "DOWNLOAD": "https://spacedock.info/mod/1886/ScienceAlert%20ReAlerted",
+ "GITHUB": {
+ "USERNAME": "linuxgurugamer",
+ "REPOSITORY": "ScienceAlert"
+ },
+ "VERSION": {
+ "MAJOR": 1,
+ "MINOR": 9,
+ "PATCH": 10,
+ "BUILD": 1
+ },
+ "KSP_VERSION": {
+ "MAJOR": 1,
+ "MINOR": 12,
+ "PATCH": 3
+ },
+ "KSP_VERSION_MIN": {
+ "MAJOR": 1,
+ "MINOR": 9,
+ "PATCH": 0
+ }
+}
diff --git a/GameData/ScienceAlert/sounds/bubbles.wav b/GameData/ScienceAlert/sounds/bubbles.wav
new file mode 100644
index 0000000..1db0c67
Binary files /dev/null and b/GameData/ScienceAlert/sounds/bubbles.wav differ
diff --git a/GameData/ScienceAlert/sounds/click1.wav b/GameData/ScienceAlert/sounds/click1.wav
new file mode 100644
index 0000000..8046128
Binary files /dev/null and b/GameData/ScienceAlert/sounds/click1.wav differ
diff --git a/GameData/ScienceAlert/sounds/click2.wav b/GameData/ScienceAlert/sounds/click2.wav
new file mode 100644
index 0000000..332d4f2
Binary files /dev/null and b/GameData/ScienceAlert/sounds/click2.wav differ
diff --git a/GameData/ScienceAlert/sounds/error.wav b/GameData/ScienceAlert/sounds/error.wav
new file mode 100644
index 0000000..4720816
Binary files /dev/null and b/GameData/ScienceAlert/sounds/error.wav differ
diff --git a/Instructions.txt b/Instructions.txt
new file mode 100644
index 0000000..cd6dee0
--- /dev/null
+++ b/Instructions.txt
@@ -0,0 +1,133 @@
+These scripts are based on the following directory layout:
+
+modmaindir
+ |-> GameData
+ |-> ModDir
+ |-> Plugins
+ |-> Sourcedir
+
+The GameData should contain all files needed for a release
+
+Overview and Dependencies
+
+ Dependencies
+ These instructions are based on using Microsoft Visual Studio 2017.
+
+ The 7Zip packaging program is required for the final packaging,
+ available here: http://www.7-zip.org/
+
+ The JQ program is required to parse the JSON version file, available
+ here: https://stedolan.github.io/jq/download/
+
+ Overview
+
+ Part of the process involves adding a file, AssemblyVersion.tt, to the
+ codebase. This file is called a "Text Template", and is used to create
+ the AssemblyVersion value which is then stored in the final DLL
+
+ There are two batch files, deploy.bat and buildRelease.bat. The
+ "deploy.bat" used to copy the DLL to the GameData directory, and
+ then to copy the complete release to a test install. The
+ "buildRelease.bat" is used to create the final zip file for release
+
+While the packaging program can be changed to an alternative (with appropriate
+changes to the "buildRelease.bat" file, the JQ program is required and not
+replacable.
+
+The assumption is also made that the mod is downloaded and ready to be worked
+on.
+
+
+
+Instructions
+
+Create the GameData folder if it doesn't exist
+
+ If it doesn't exist, then copy the latest release of the mod into the GameData folder
+
+Find the .version file (if it exists) and copy it to the top level directory
+
+
+You can either copy the AssemblyVersion.tt to the main mod folder, or
+create a new TextTemplate in the project (using MS Studio) and do a copy/paste
+operation. If you copy it over, you will need to add the file to the project
+in the IDE
+
+Edit the AssemblyVersion.tt file, update the following line:
+
+ string versionfile = @"CompletePathTo.version";
+
+Replace the "CompletePathTo.version" with the path to the .version file.
+
+Remove or comment out the following line from the file AssemblyInfo.cs (usually
+located in the "Properties" folder inside your C# project):
+
+ [assembly: AssemblyVersion("1.0.0.0")]
+
+
+Add the following to the Pre-build event command line. This line is based on
+using Visual Studio 2017, installed on the X drive:
+
+
+ set textTemplatingPath="%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community\Common7\IDE\texttransform.exe"
+
+ %textTemplatingPath% "$(ProjectDir)AssemblyVersion.tt"
+
+
+Copy the two files, "deploy.bat" and "buildRelease.bat" to the main mod folder
+
+You need to update the deploy.bat and the buildRelease.bat with the following values:
+
+
+H to point to your test KSP install: set H=R:\KSP_1.3.1_dev
+GAMEDIR to the name of the mod folder: set GAMEDIR=xxxxx
+GAMEDATA to point to the GameData folder: GAMEDATA="GameData"
+VERSIONFILE to the name of the .version file: VERSIONFILE=%GAMEDIR%.version
+
+In most cases, the VERSIONFILE is built from the GAMEDIR, but some mods use a
+different name
+
+For the buildRelease.bat, you have to update the following as well:
+
+If existing, LICENSE to the license file: set LICENSE=License.txt
+If existing, README to the Readme file: README=ReadMe.md
+Set RELEASEDIR to where you want the zip file: RELEASEDIR=d:\Users\jbb\release
+
+If you want to use a different program than 7z, change it in the next line.
+If you do, you will have to change the options to the zip program at the end
+of the file:
+
+set ZIP="c:\Program Files\7-zip\7z.exe"
+
+
+
+In the MS VS IDE, right-click on the Solution in the Solution Explorer, and
+select "Add -> New Solution Folder", give the folder a name "SolutionItems"
+
+Right-click on the SolutionItems folder, and select "Add -> Existing item...",
+add the two files just copied and the .version file
+
+
+
+Add the following to the Post-build event command line, replace the "xxxxx"
+with the complete path to the top level directory of the mod:
+
+
+ start /D xxxxx /WAIT deploy.bat $(TargetDir) $(TargetFileName)
+
+ if $(ConfigurationName) == Release (
+
+ start /D xxxxx /WAIT buildRelease.bat $(TargetDir) $(TargetFileName)
+
+ )
+
+Make sure the .version file has the correct values.
+
+Now, set the Visual Studio configuration to Debug, and do a test compile.
+
+If all is correct, it will compile the code, copy the DLL to the destination
+folder, and then copy the complete release to your test KSP installation
+
+Finally, change the VS config to "Release" and rebuild the mod. This time it
+will add the step to pack up the entire release and leave it in the RELEASEDIR
+
diff --git a/README.md b/README.md
index 5a865b5..bdc94a6 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,11 @@
-# ScienceAlert
-When is is it time for science?
+# ScienceAlert Updated
+
+This is a minor updated version of the Kerbal Space Program mod ScienceAlert (see original here: https://github.com/DennyTX/ScienceAlert) to fix a few bugs.
+
+
+TODO
+
+Significant FPS drop
+
+
+I just got this, and started a new game. When I go on EVA and get an EVA report, then hit keep, it doesnt show it for review on my kerbal or when I get back to my capsule. Transmitting data does not seem to work even when having an external antenna.
\ No newline at end of file
diff --git a/ReeperCommon/AudioPlayer.cs b/ReeperCommon/AudioPlayer.cs
deleted file mode 100644
index 8604a92..0000000
--- a/ReeperCommon/AudioPlayer.cs
+++ /dev/null
@@ -1,140 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using UnityEngine;
-
-namespace ReeperCommon
-{
- internal class AudioPlayer : MonoBehaviour
- {
- private static AudioPlayer _instance;
- private readonly Dictionary sounds = new Dictionary();
- private AudioSource source;
-
- public static AudioPlayer Audio
- {
- get
- {
- if (_instance != null) return _instance;
- GameObject gameObject = new GameObject("Reeper.AudioPlayer", typeof(AudioSource));
- gameObject.AddComponent().SetSource(gameObject);
- return _instance;
- }
- }
-
- public int Count => sounds.Count;
-
- private void Awake()
- {
- if (_instance == null)
- {
- _instance = this;
- }
- }
-
- private void OnDestroy()
- {
- if (_instance == this)
- {
- _instance = null;
- }
- }
-
- public void SetSource(GameObject src, bool b2d = true)
- {
- source = src.GetComponent() ?? src.AddComponent();
- }
-
- public int LoadSoundsFrom(string dir, bool b2D = true)
- {
- int counter = 0;
- if (System.IO.Path.IsPathRooted(dir) && System.IO.Directory.Exists(dir))
- {
- dir = System.IO.Path.GetFullPath(dir).Replace('\\', '/');
- dir = ConfigUtil.GetRelativeToGameData(dir);
- }
- else
- {
- dir = dir.TrimStart('\\', '/');
- if (!System.IO.Directory.Exists(System.IO.Path.Combine(System.IO.Path.GetFullPath(KSPUtil.ApplicationRootPath + "GameData"), dir)))
- {
- string text = System.IO.Path.Combine(ConfigUtil.GetDllDirectoryPath(), dir);
- if (!System.IO.Directory.Exists(text))
- {
- Log.Debug("[ScienceAlert]:AudioPlayer: Couldn't find '{0}'", dir);
- return 0;
- }
- dir = ConfigUtil.GetRelativeToGameData(text).Replace('\\', '/');
- }
- else
- {
- dir = dir.Replace('\\', '/');
- }
- }
- GameDatabase.Instance.databaseAudio.ForEach(delegate(AudioClip ac)
- {
- string text2 = ac.name;
- int num = text2.LastIndexOf('/');
- if (num >= 0)
- {
- text2 = text2.Substring(0, num);
- }
- if (!string.Equals(text2, dir)) return;
- if (sounds.ContainsKey(ac.name))return;
- sounds.Add(ac.name, new PlayableSound(ac));
- counter++;
- });
- if (counter == 0)
- {
- Log.Warning("AudioPlayer: Didn't load any sounds from directory '{0}'", dir);
- }
- return counter;
- }
-
- public bool PlayThenDelay(string name, float delay = 1f)
- {
- return Play(name, 1f, delay);
- }
-
- public bool PlayUI(string name, float delay = 0f)
- {
- return Play(name, GameSettings.UI_VOLUME, delay);
- }
-
- public bool Play(string name, float volume = 1f, float delay = 0f)
- {
- PlayableSound playableSound = null;
- if (sounds.ContainsKey(name))
- {
- playableSound = sounds[name];
- }
- else
- {
- string text = sounds.Keys.ToList().SingleOrDefault((string k) => string.Equals(PlayableSound.GetShortName(k), name));
- if (!string.IsNullOrEmpty(text) && sounds.ContainsKey(text))
- {
- playableSound = sounds[text];
- }
- }
- if (playableSound == null)
- {
- return false;
- }
- if (!(Time.realtimeSinceStartup - playableSound.nextPlayableTime > 0f)) return false;
- if (source == null)
- {
- SetSource(gameObject);
- }
- try
- {
- source.PlayOneShot(playableSound.clip, Mathf.Clamp(volume, 0f, 1f));
- playableSound.nextPlayableTime = Time.realtimeSinceStartup + delay;
- bool result = true;
- return result;
- }
- catch (System.Exception)
- {
- return false;
- }
- }
- }
-}
diff --git a/ReeperCommon/ConfigNodeTypeHandler.cs b/ReeperCommon/ConfigNodeTypeHandler.cs
deleted file mode 100644
index e3d5535..0000000
--- a/ReeperCommon/ConfigNodeTypeHandler.cs
+++ /dev/null
@@ -1,127 +0,0 @@
-using UnityEngine;
-
-namespace ReeperCommon
-{
- [System.AttributeUsage(System.AttributeTargets.Property | System.AttributeTargets.Field | System.AttributeTargets.Event)]
- internal class DoNotSerialize : System.Attribute
- {}
-
- internal interface IConfigNodeTypeFormatter
- {
- string Serialize(object obj);
-
- object Deserialize(object obj, string value);
- }
-
- internal interface IReeperSerializable
- {
- void OnSerialize(ConfigNode node);
-
- void OnDeserialize(ConfigNode node);
- }
-
- internal class ConfigNodeTypeHandler
- {
- internal class Vector2Formatter : IConfigNodeTypeFormatter
- {
- public string Serialize(object obj)
- {
- return KSPUtil.WriteVector((Vector2)obj);
- }
-
- public object Deserialize(object obj, string value)
- {
- Vector2 vector = (Vector2)obj;
- vector = KSPUtil.ParseVector2(value);
- return vector;
- }
- }
-
- private System.Collections.Generic.Dictionary handlers = new System.Collections.Generic.Dictionary();
-
- internal ConfigNodeTypeHandler()
- {
- AddFormatter(typeof(Vector2), typeof(Vector2Formatter));
- }
-
- internal void AddFormatter(System.Type targetType, IConfigNodeTypeFormatter impl)
- {
- if (handlers.ContainsKey(targetType))
- {
- handlers[targetType] = impl;
- return;
- }
- handlers.Add(targetType, impl);
- }
-
- internal void AddFormatter(System.Type targetType, System.Type formatter)
- {
- try
- {
- if (!typeof(IConfigNodeTypeFormatter).IsAssignableFrom(formatter)) return;
- IConfigNodeTypeFormatter value = (IConfigNodeTypeFormatter)System.Activator.CreateInstance(formatter);
- if (handlers.ContainsKey(targetType))
- handlers[targetType] = value;
- else
- handlers.Add(targetType, value);
- }
- catch (System.Exception ex)
- {
- Log.Debug("[ScienceAlert]:ConfigNodeTypeHandler.AddFormatter: Exception while attempting to add handler for type '{0}' (of type {1}): {2}", targetType.FullName, formatter.FullName, ex);
- }
- }
-
- internal string Serialize(ref T obj)
- {
- System.Type typeFromHandle = typeof(T);
- if (handlers.ContainsKey(typeFromHandle))
- {
- IConfigNodeTypeFormatter configNodeTypeFormatter = handlers[typeFromHandle];
- return configNodeTypeFormatter.Serialize(obj);
- }
- if (typeFromHandle.IsEnum)
- {
- return obj.ToString();
- }
- return obj.ToString();
- }
-
- internal bool Deserialize(ref T obj, string value)
- {
- if (!handlers.ContainsKey(typeof(T)))
- {
- bool result;
- if (typeof(T).IsEnum)
- {
- try
- {
- obj = (T)System.Enum.Parse(typeof(T), value, true);
- return true;
- }
- catch (System.Exception)
- {
- return false;
- }
- }
- try
- {
- obj = ConfigUtil.ParseThrowable(value);
- result = true;
- }
- catch (System.Exception)
- {
- result = false;
- }
- return result;
- }
-
- object obj2 = handlers[typeof(T)].Deserialize(obj, value);
- if (obj2 != null)
- {
- obj = (T)obj2;
- return true;
- }
- return false;
- }
- }
-}
diff --git a/ReeperCommon/ConfigUtil.cs b/ReeperCommon/ConfigUtil.cs
deleted file mode 100644
index 4733322..0000000
--- a/ReeperCommon/ConfigUtil.cs
+++ /dev/null
@@ -1,215 +0,0 @@
-using System;
-using System.Reflection;
-using UnityEngine;
-
-namespace ReeperCommon
-{
- public static class ConfigUtil
- {
- public static T ParseEnum(this ConfigNode node, string valueName, T defaultValue)
- {
- try
- {
- string value = node.GetValue(valueName);
- T result;
- if (string.IsNullOrEmpty(value))
- {
- result = defaultValue;
- return result;
- }
- Enum.GetValues(typeof(T));
- result = (T)Enum.Parse(typeof(T), value, true);
- return result;
- }
- catch (Exception ex)
- {
- Log.Debug("[ScienceAlert]:Settings: Failed to parse value '{0}' from ConfigNode, resulted in an exception {1}", valueName, ex);
- }
- return defaultValue;
- }
-
- public static string Parse(this ConfigNode node, string valueName, string defaultValue = "")
- {
- try
- {
- string result;
- if (!node.HasValue(valueName))
- {
- result = defaultValue;
- return result;
- }
- result = node.GetValue(valueName);
- return result;
- }
- catch (Exception ex)
- {
- Log.Debug("[ScienceAlert]:Settings: Failed to parse string value '{0}' from ConfigNode, resulted in an exception {1}", valueName, ex);
- }
- return defaultValue;
- }
-
- public static T Parse(string value)
- {
- return Parse(value, default(T));
- }
-
- public static T Parse(string value, T defaultValue)
- {
- try
- {
- MethodInfo method = typeof(T).GetMethod("TryParse", new[]
- {
- typeof(string),
- typeof(T).MakeByRefType()
- });
- if (method == null)
- {
- Log.Debug("[ScienceAlert]:Failed to locate TryParse in {0}", typeof(T).FullName);
- }
- else
- {
- object[] array = {
- value,
- default(T)
- };
- T result;
- if ((bool)method.Invoke(null, array))
- {
- result = (T)array[1];
- return result;
- }
- result = defaultValue;
- return result;
- }
- }
- catch (Exception)
- {
- T result = defaultValue;
- return result;
- }
- return defaultValue;
- }
-
- public static T ParseThrowable(string value)
- {
- T result;
- try
- {
- MethodInfo method = typeof(T).GetMethod("TryParse", new[]
- {
- typeof(string),
- typeof(T).MakeByRefType()
- });
- if (method == null)
- {
- throw new Exception("TryParse method not found");
- }
- object[] array = {
- value,
- default(T)
- };
- if (!(bool)method.Invoke(null, array))
- {
- throw new Exception("TryParse invoke reports failure");
- }
- result = (T)array[1];
- }
- catch (Exception ex)
- {
- Log.Debug("[ScienceAlert]:ConfigUtil.Parse<{0}>: Failed to parse from value '{1}': {2}", typeof(T).FullName, value, ex);
- throw;
- }
- return result;
- }
-
- public static T Parse(this ConfigNode node, string valueName, T defaultValue)
- {
- try
- {
- T result;
- if (!node.HasValue(valueName))
- {
- result = defaultValue;
- return result;
- }
- string value = node.GetValue(valueName);
- result = Parse(value, defaultValue);
- return result;
- }
- catch (Exception ex)
- {
- Log.Debug("[ScienceAlert]:ConfigUtil.Parse<{0}>: Exception while parsing a value named {1}: {2}", typeof(T).FullName, valueName, ex);
- }
- return defaultValue;
- }
-
- public static string ReadString(this ConfigNode node, string valueName, string defaultValue = "")
- {
- if (node == null || !node.HasValue(valueName))
- {
- return defaultValue;
- }
- return node.GetValue(valueName);
- }
-
- public static void Set(this ConfigNode node, string valueName, string value)
- {
- if (node.HasValue(valueName))
- {
- node.SetValue(valueName, value);
- return;
- }
- node.AddValue(valueName, value);
- }
-
- public static void Set(this ConfigNode node, string valueName, T value)
- {
- node.Set(valueName, value.ToString());
- }
-
- public static string GetDllDirectoryPath()
- {
- return System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
- }
-
- public static string GetRelativeToGameData(string path)
- {
- if (!path.Contains("GameData"))
- {
- Log.Debug(
- $"GetRelativeToGameData: Given path '{path}' does not reside in GameData. The plugin does not appear to be installed correctly.");
- throw new FormatException($"GetRelativeToGameData: path '{path}' does not contain 'GameData'");
- }
- int num = path.IndexOf("GameData");
- string text = "";
- if (path.Length > num + "GameData".Length + 1)
- {
- text = path.Substring(num + "GameData".Length + 1);
- }
- return text;
- }
-
- public static Rect ReadRect(this ConfigNode node, string name, Rect defaultValue = default(Rect))
- {
- if (node.HasValue(name))
- {
- try
- {
- Vector4 vector = KSPUtil.ParseVector4(node.GetValue(name));
- return new Rect(vector.x, vector.y, vector.z, vector.w);
- }
- catch (Exception ex)
- {
- Log.Debug("[ScienceAlert]:ConfigUtil.ReadRect: exception while reading value '{0}': {1}", name, ex);
- }
- return defaultValue;
- }
- return defaultValue;
- }
-
- public static Vector4 AsVector(this Rect rect)
- {
- return new Vector4(rect.x, rect.y, rect.width, rect.height);
- }
- }
-}
diff --git a/ReeperCommon/DraggableWindow.cs b/ReeperCommon/DraggableWindow.cs
deleted file mode 100644
index 32e7056..0000000
--- a/ReeperCommon/DraggableWindow.cs
+++ /dev/null
@@ -1,315 +0,0 @@
-using UnityEngine;
-
-namespace ReeperCommon
-{
- public delegate void WindowClosedDelegate();
- public delegate void WindowDelegate(bool tf);
-
- public abstract class DraggableWindow : MonoBehaviour
- {
- protected Rect windowRect = default(Rect);
- protected Rect lastRect = default(Rect);
- private GUISkin skin;
- private int winId = Random.Range(2444, 2147483647);
- private static Vector2 offset = new Vector2(4f, 4f);
- private static GUIStyle buttonStyle;
- private bool draggable = true;
- private bool visible = true;
- private static Texture2D hoverBackground;
- private static GUISkin defaultSkin;
- public event WindowDelegate OnVisibilityChange = delegate{};
-
- public event WindowDelegate OnDraggabilityChange = delegate{};
-
- public event WindowClosedDelegate OnClosed = delegate{};
-
- public bool Draggable
- {
- get
- {
- return draggable;
- }
- protected set
- {
- if (draggable != value)
- {
- OnDraggabilityChange(value);
- }
- draggable = value;
- }
- }
-
- public bool ShrinkHeightToFit
- {
- get;
- set;
- }
-
- public bool Visible
- {
- get
- {
- return visible;
- }
- set
- {
- if (value != visible)
- {
- OnVisibilityChange(value);
- }
- visible = value;
- if (gameObject.activeInHierarchy != visible && !visible)
- {
- OnClosed();
- }
- gameObject.SetActive(visible);
- }
- }
-
- public int WindowID
- {
- get
- {
- return winId;
- }
- private set
- {
- winId = value;
- }
- }
-
- public string Title
- {
- get;
- set;
- }
-
- public GUISkin Skin
- {
- get
- {
- return skin ?? DefaultSkin;
- }
- set
- {
- skin = value ?? DefaultSkin;
- }
- }
-
- public Rect WindowRect
- {
- get
- {
- return lastRect;
- }
- }
-
- public bool ClampToScreen
- {
- get;
- set;
- }
-
- public static Texture2D LockTexture
- {
- get;
- set;
- }
-
- public static Texture2D UnlockTexture
- {
- get;
- set;
- }
-
- public static Texture2D CloseTexture
- {
- get;
- set;
- }
-
- public static Texture2D ButtonHoverBackground
- {
- get
- {
- return hoverBackground ?? ResourceUtil.GenerateRandom(16, 16);
- }
- set
- {
- hoverBackground = value;
- if (buttonStyle != null)
- {
- buttonStyle.hover.background = value;
- }
- }
- }
-
- public static string ButtonSound
- {
- get;
- set;
- }
-
- public static GUISkin DefaultSkin
- {
- get
- {
- return defaultSkin ?? HighLogic.Skin;
- }
- set
- {
- defaultSkin = value;
- }
- }
-
- protected void Awake()
- {
- if (buttonStyle == null)
- {
- buttonStyle = new GUIStyle(GUIStyle.none);
- if (hoverBackground != null)
- {
- buttonStyle.hover.background = hoverBackground;
- }
- }
- Draggable = true;
- Visible = true;
- ClampToScreen = true;
- Title = "Draggable Window";
- windowRect = Setup();
- lastRect = new Rect(windowRect);
- GameEvents.onHideUI.Add(OnHideUI);
- GameEvents.onShowUI.Add(OnShowUI);
- Log.Debug("ALERT:DraggableWindow {0} Awake", Title);
- }
-
- private void Start()
- {
- Log.Debug("ALERT:DraggableWindow {0} Start", Title);
- }
-
- protected virtual void OnDestroy()
- {
- Log.Debug("ALERT:DraggableWindow.OnDestroy");
- GameEvents.onHideUI.Remove(OnHideUI);
- GameEvents.onShowUI.Remove(OnShowUI);
- }
-
- protected void OnEnable()
- {
- OnVisibilityChange(true);
- }
-
- protected void OnDisable()
- {
- OnVisibilityChange(false);
- }
-
- public void Show(bool tf)
- {
- Visible = tf;
- }
-
- protected void Update()
- {
- if (ShrinkHeightToFit)
- {
- windowRect.height = 1f;
- }
- }
-
- protected void OnGUI()
- {
- GUI.skin = Skin;
- windowRect = GUILayout.Window(winId, windowRect, _InternalDraw, Title);
- if (ClampToScreen)
- windowRect = KSPUtil.ClampRectToScreen(windowRect);
- }
-
- private void _InternalDraw(int winid)
- {
- DrawUI();
- lastRect.x = windowRect.x;
- lastRect.y = windowRect.y;
- GUILayout.BeginArea(new Rect(0f, offset.y, lastRect.width, lastRect.height));
- lastRect = new Rect(windowRect);
- GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(false));
- GUILayout.FlexibleSpace();
- if (LockTexture != null && UnlockTexture != null)
- {
- if (GUILayout.Button(Draggable ? UnlockTexture : LockTexture, buttonStyle))
- {
- Draggable = !Draggable;
- if (!string.IsNullOrEmpty(ButtonSound))
- {
- AudioPlayer.Audio.PlayUI(ButtonSound);
- }
- Log.Debug("ALERT:DraggableWindow {0}", Draggable ? "unlocked" : "locked");
- }
- if (CloseTexture != null)
- {
- GUILayout.Space(offset.x * 0.5f);
- }
- }
- if (CloseTexture != null && GUILayout.Button(CloseTexture, buttonStyle))
- {
- if (!string.IsNullOrEmpty(ButtonSound))
- {
- AudioPlayer.Audio.PlayUI(ButtonSound);
- }
- OnCloseClick();
- }
- GUILayout.Space(offset.x);
- GUILayout.EndHorizontal();
- GUILayout.EndArea();
- if (Draggable)
- {
- GUI.DragWindow();
- }
- }
-
- protected abstract Rect Setup();
-
- protected abstract void DrawUI();
-
- protected abstract void OnCloseClick();
-
- private void OnHideUI()
- {
- gameObject.SetActive(false);
- }
-
- private void OnShowUI()
- {
- gameObject.SetActive(Visible);
- }
-
- public void SaveInto(ConfigNode node)
- {
- if (node != null)
- {
- node.Set("WindowX", windowRect.x);
- node.Set("WindowY", windowRect.y);
- node.Set("Draggable", Draggable);
- node.Set("Visible", Visible);
- Log.Debug("ALERT:DraggableWindow.SaveInto: Saved window {0} as ConfigNode {1}", Title, node.ToString());
- return;
- }
- Log.Warning("GuiUtil.DraggableWindow: Can't save into null ConfigNode");
- }
-
- public bool LoadFrom(ConfigNode node)
- {
- if (node != null)
- {
- windowRect.x = node.Parse("WindowX", (float)Screen.width * 0.5f - windowRect.width * 0.5f);
- windowRect.y = node.Parse("WindowY", (float)Screen.height * 0.5f - windowRect.height * 0.5f);
- Draggable = node.Parse("Draggable", true);
- Visible = node.Parse("Visible", false);
- return node.HasValue("WindowX") && node.HasValue("WindowY");
- }
- Log.Warning("GuiUtil.DraggableWindow: Can't load from null ConfigNode");
- return false;
- }
- }
-}
diff --git a/ReeperCommon/Log.cs b/ReeperCommon/Log.cs
deleted file mode 100644
index 580032d..0000000
--- a/ReeperCommon/Log.cs
+++ /dev/null
@@ -1,141 +0,0 @@
-namespace ReeperCommon
-{
- internal class Log
- {
- [System.Flags]
- internal enum LogMask
- {
- Normal = 1,
- Debug = 2,
- Verbose = 4,
- Performance = 8,
- Warning = 16,
- Error = 32,
- None = 0,
- All = -1
- }
-
- internal static LogMask Level = LogMask.Normal | LogMask.Warning | LogMask.Error;
-
- internal static string _AssemblyName => System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
-
- internal string _ClassName => GetType().Name;
-
- private static string FormatMessage(string msg)
- {
- return $"{_AssemblyName}, {msg}";
- }
-
- private static bool ShouldLog(LogMask messageType)
- {
- return (Level & messageType) != LogMask.None;
- }
-
- internal static void Write(string message, LogMask level)
- {
- if (ShouldLog(level))
- {
- string message2 = FormatMessage(message);
- if ((level & LogMask.Error) != LogMask.None)
- {
- UnityEngine.Debug.LogError(message2);
- return;
- }
- if ((level & LogMask.Warning) != LogMask.None)
- {
- UnityEngine.Debug.LogWarning(message2);
- return;
- }
- if ((level & LogMask.Normal) != LogMask.None)
- {
- UnityEngine.Debug.Log(message2);
- return;
- }
- if ((level & LogMask.Performance) != LogMask.None)
- {
- UnityEngine.Debug.Log(FormatMessage($"[PERF] {message}"));
- return;
- }
- UnityEngine.Debug.Log(message2);
- }
- }
-
- internal static void Write(string message, LogMask level, params object[] strParams)
- {
- if (ShouldLog(level))
- {
- Write(string.Format(message, strParams), level);
- }
- }
-
- internal static void SaveInto(ConfigNode parentNode)
- {
- ConfigNode configNode = parentNode.AddNode(new ConfigNode("LogSettings"));
- configNode.AddValue("LogMask", (int)Level);
- string[] names = System.Enum.GetNames(typeof(LogMask));
- System.Array values = System.Enum.GetValues(typeof(LogMask));
- configNode.AddValue("// Bit index", "message type");
- for (int i = 0; i < names.Length - 1; i++)
- {
- configNode.AddValue($"// Bit {i}", values.GetValue(i));
- }
- Debug("[ScienceAlert].SaveInto = {0}", configNode.ToString());
- }
-
- internal static void LoadFrom(ConfigNode parentNode)
- {
- if (parentNode == null || !parentNode.HasNode("LogSettings"))
- {
- Warning("[ScienceAlert] failed, did not find LogSettings in: {0}", parentNode != null ? parentNode.ToString() : "");
- return;
- }
- ConfigNode node = parentNode.GetNode("LogSettings");
- try
- {
- if (!node.HasValue("LogMask"))
- {
- throw new System.Exception("[ScienceAlert]:No LogMask value in ConfigNode");
- }
- string value = node.GetValue("LogMask");
- int num = 0;
- if (int.TryParse(value, out num))
- {
- if (num == 0)
- {
- Warning("[ScienceAlert]: Log disabled");
- }
- Level = (LogMask)num;
- Debug("[ScienceAlert]:Loaded LogMask = {0} from ConfigNode", Level.ToString());
- }
- else
- {
- Debug("[ScienceAlert]: LogMask value '{0}' cannot be converted to LogMask", value);
- }
- }
- catch (System.Exception ex)
- {
- Warning("[ScienceAlert] failed with exception: {0}", ex);
- }
- }
-
- internal static void Debug(string message, params object[] strParams)
- {
- Write(message, LogMask.Debug, strParams);
- }
-
- internal static void Normal(string message, params object[] strParams)
- {
- Write(message, LogMask.Normal, strParams);
- }
-
- internal static void Warning(string message, params object[] strParams)
- {
- Write(message, LogMask.Warning, strParams);
- }
-
- internal static void Error(string message, params object[] strParams)
- {
- Write(message, LogMask.Error, strParams);
- }
- }
-}
diff --git a/ReeperCommon/PlayableSound.cs b/ReeperCommon/PlayableSound.cs
deleted file mode 100644
index 5777dad..0000000
--- a/ReeperCommon/PlayableSound.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using UnityEngine;
-
-namespace ReeperCommon
-{
- internal class PlayableSound
- {
- public AudioClip clip;
-
- public string shortName = "";
-
- public float nextPlayableTime;
-
- internal PlayableSound(AudioClip aclip)
- {
- clip = aclip;
- nextPlayableTime = 0f;
- shortName = GetShortName(aclip.name);
- }
-
- public static string GetShortName(string name)
- {
- if (name.Contains("/"))
- {
- int num = name.LastIndexOf('/');
- if (num >= 0)
- {
- return name.Substring(num + 1);
- }
- }
- return name;
- }
- }
-}
diff --git a/ReeperCommon/ReeperConfigNodeExtensions.cs b/ReeperCommon/ReeperConfigNodeExtensions.cs
deleted file mode 100644
index bc57bcf..0000000
--- a/ReeperCommon/ReeperConfigNodeExtensions.cs
+++ /dev/null
@@ -1,255 +0,0 @@
-using System;
-using System.Linq;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-
-namespace ReeperCommon
-{
- [System.AttributeUsage(System.AttributeTargets.Property | System.AttributeTargets.Field)]
- internal class Subsection : System.Attribute
- {
- private string sectionName = "Subsection";
-
- public string Section => sectionName;
-
- public Subsection(string name)
- {
- sectionName = name;
- if (string.IsNullOrEmpty(name))
- {
- sectionName = "Subsection";
- }
- }
- }
-
- public static class ReeperConfigNodeExtensions
- {
- internal static ConfigNode CreateConfigFromObjectEx(this object obj, ConfigNodeTypeHandler typeFormatter = null)
- {
- ConfigNode result;
- try
- {
- ConfigNode configNode = new ConfigNode(obj.GetType().Name);
- typeFormatter = typeFormatter ?? new ConfigNodeTypeHandler();
- FieldInfo[] objectFields = GetObjectFields(obj);
- FieldInfo[] array = objectFields;
- for (int i = 0; i < array.Length; i++)
- {
- FieldInfo fieldInfo = array[i];
- object[] customAttributes = fieldInfo.GetCustomAttributes(false);
- object value = fieldInfo.GetValue(obj);
- if (value != null)
- {
- if (typeof(ConfigNode).IsAssignableFrom(fieldInfo.FieldType))
- {
- ConfigNode configNode2 = new ConfigNode(fieldInfo.Name);
- ConfigNode configNode3 = ((ConfigNode)Convert.ChangeType(value, typeof(ConfigNode))).CreateCopy();
- if (string.IsNullOrEmpty(configNode3.name))
- configNode3.name = "ConfigNode";
- configNode2.ClearData();
- Subsection subsection = customAttributes.SingleOrDefault(attr => attr is Subsection) as Subsection;
- if (subsection == null)
- configNode2.AddNode(configNode3);
- else
- configNode2.AddNode(subsection.Section).AddNode(configNode3);
- configNode.AddNode(configNode2);
- }
- else
- {
- MethodInfo method = typeFormatter.GetType().GetMethod("Serialize", BindingFlags.Instance | BindingFlags.NonPublic);
- if (method == null)
- {
- Log.Debug("[ScienceAlert]:CreateConfigFromObjectEx: Serialize method not found");
- }
- MethodInfo methodInfo = method.MakeGenericMethod(fieldInfo.FieldType);
- string value2 = methodInfo.Invoke(typeFormatter, new[]
- {
- value
- }) as string;
- if (string.IsNullOrEmpty(value2))
- {
- Log.Warning("ConfigUtil.CreateConfigFromObjectEx: null or empty return value for serialized type {0}", fieldInfo.FieldType.Name);
- }
- WriteValue(configNode, fieldInfo.Name, value2, customAttributes);
- }
- }
- else
- {
- Log.Warning("Could not get value for " + fieldInfo.Name);
- }
- }
- PropertyInfo[] objectProperties = GetObjectProperties(obj);
- PropertyInfo[] array2 = objectProperties;
- for (int j = 0; j < array2.Length; j++)
- {
- PropertyInfo propertyInfo = array2[j];
- object obj2 = propertyInfo.GetGetMethod(true).Invoke(obj, null);
- object[] customAttributes2 = propertyInfo.GetCustomAttributes(true);
- MethodInfo method2 = typeFormatter.GetType().GetMethod("Serialize", BindingFlags.Instance | BindingFlags.NonPublic);
- if (method2 == null)
- {
- Log.Debug("[ScienceAlert]:CreateConfigFromObjectEx: Serialize method not found");
- }
- else
- {
- MethodInfo methodInfo2 = method2.MakeGenericMethod(propertyInfo.PropertyType);
- string value3 = methodInfo2.Invoke(typeFormatter, new[]
- {
- obj2
- }) as string;
- if (string.IsNullOrEmpty(value3))
- {
- Log.Warning("ConfigUtil.CreateConfigFromObjectEx: null or empty return value for serialized type {0}", propertyInfo.PropertyType.Name);
- }
- WriteValue(configNode, propertyInfo.Name, value3, customAttributes2);
- }
- }
- if (obj is IReeperSerializable)
- {
- ((IReeperSerializable)obj).OnSerialize(configNode);
- }
- result = configNode;
- }
- catch (Exception ex)
- {
- Log.Debug("[ScienceAlert]:ConfigUtil.CreateConfigFromObjectEx: Exception {0}", ex);
- result = null;
- }
- return result;
- }
-
- internal static bool CreateObjectFromConfigEx(this ConfigNode node, object obj, ConfigNodeTypeHandler typeFormatter = null)
- {
- bool flag = true;
- typeFormatter = typeFormatter ?? new ConfigNodeTypeHandler();
- FieldInfo[] objectFields = GetObjectFields(obj);
- PropertyInfo[] objectProperties = GetObjectProperties(obj);
- Log.Debug("ALERT:CreateObjectFromConfig: Found {0} fields and {1} properties", objectFields.Length, objectProperties.Length);
- FieldInfo[] array = objectFields;
- for (int i = 0; i < array.Length; i++)
- {
- FieldInfo fieldInfo = array[i];
- try
- {
- object[] customAttributes = fieldInfo.GetCustomAttributes(true);
- if (typeof(ConfigNode).IsAssignableFrom(fieldInfo.FieldType))
- {
- if (node.HasNode(fieldInfo.Name))
- {
- Convert.ChangeType(fieldInfo.GetValue(obj) ?? new ConfigNode(), typeof(ConfigNode));
- ConfigNode node2 = node.GetNode(fieldInfo.Name);
- Subsection subsection = customAttributes.SingleOrDefault(attr => attr is Subsection) as Subsection;
- if (subsection != null)
- {
- if (node2.HasNode(subsection.Section))
- {
- node2 = node2.GetNode(subsection.Section);
- }
- }
- if (node2.CountNodes == 1)
- {
- ConfigNode value = node2.nodes[0];
- fieldInfo.SetValue(obj, value);
- }
- }
- }
- else
- {
- string text = ReadValue(node, fieldInfo.Name, fieldInfo.GetCustomAttributes(true));
- if (!string.IsNullOrEmpty(text))
- {
- MethodInfo method = typeFormatter.GetType().GetMethod("Deserialize", BindingFlags.Instance | BindingFlags.NonPublic);
- MethodInfo methodInfo = method.MakeGenericMethod(fieldInfo.FieldType);
- if (!(bool)methodInfo.Invoke(typeFormatter, new[]
- {
- fieldInfo.GetValue(obj),
- text
- }))
- {
- flag = false;
- }
- }
- }
- }
- catch (Exception ex)
- {
- Log.Debug("[ScienceAlert]:Exception while deserializing field '{0}': {1}", fieldInfo.Name, ex);
- flag = false;
- }
- }
- PropertyInfo[] array2 = objectProperties;
- for (int j = 0; j < array2.Length; j++)
- {
- PropertyInfo propertyInfo = array2[j];
- try
- {
- string text2 = ReadValue(node, propertyInfo.Name, propertyInfo.GetCustomAttributes(true));
- if (!string.IsNullOrEmpty(text2))
- {
- MethodInfo method2 = typeFormatter.GetType().GetMethod("Deserialize", BindingFlags.Instance | BindingFlags.NonPublic);
- MethodInfo methodInfo2 = method2.MakeGenericMethod(propertyInfo.PropertyType);
- object obj2 = Convert.ChangeType(propertyInfo.GetGetMethod(true).Invoke(obj, null), propertyInfo.PropertyType);
- object[] array3 = { obj2, text2 };
- if (!(bool)methodInfo2.Invoke(typeFormatter, array3))
- flag = false;
- else
- propertyInfo.SetValue(obj, array3[0], BindingFlags.Instance | BindingFlags.SetProperty, null, null, null);
- }
- }
- catch (Exception ex2)
- {
- Log.Debug("[ScienceAlert]:Exception while deserializing property '{0}': {1}", propertyInfo.Name, ex2);
- flag = false;
- }
- }
- if (obj is IReeperSerializable)
- ((IReeperSerializable)obj).OnDeserialize(node);
- return flag && objectFields.Count() > 0 || obj is IReeperSerializable;
- }
-
- private static FieldInfo[] GetObjectFields(object obj)
- {
- return (from fi in obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy)
- where !fi.GetCustomAttributes(false).Any(attr => attr is CompilerGeneratedAttribute || attr is NonSerializedAttribute || attr is DoNotSerialize)
- select fi).ToArray();
- }
-
- private static PropertyInfo[] GetObjectProperties(object obj)
- {
- return obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy).Where(delegate(PropertyInfo pi)
- {
- if (pi.GetGetMethod(true) != null && pi.GetSetMethod(true) != null)
- return !pi.GetCustomAttributes(true).Any(attr => attr is DoNotSerialize || attr is NonSerializedAttribute);
- return false;
- }).ToArray();
- }
-
- private static void WriteValue(ConfigNode node, string valueName, string value, object[] attrs)
- {
- if (attrs == null) attrs = new object[0];
- Subsection subsection = attrs.SingleOrDefault(attr => attr is Subsection) as Subsection;
- if (subsection != null)
- {
- if (node.HasNode(subsection.Section))
- node = node.GetNode(subsection.Section);
- else
- node = node.AddNode(subsection.Section);
- }
- attrs.ToList().ForEach(delegate{});
- node.AddValue(valueName, value);
- }
-
- private static string ReadValue(ConfigNode node, string valueName, object[] attrs)
- {
- if (attrs == null)
- attrs = new object[0];
- Subsection subsection = attrs.SingleOrDefault(attr => attr is Subsection) as Subsection;
- if (subsection != null)
- {
- if (node.HasNode(subsection.Section))
- node = node.GetNode(subsection.Section);
- }
- return node.ReadString(valueName);
- }
- }
-}
diff --git a/ReeperCommon/ResourceUtil.cs b/ReeperCommon/ResourceUtil.cs
deleted file mode 100644
index 7069f78..0000000
--- a/ReeperCommon/ResourceUtil.cs
+++ /dev/null
@@ -1,259 +0,0 @@
-using System.IO;
-using UnityEngine;
-
-namespace ReeperCommon
-{
- public static class ResourceUtil
- {
- public static bool SaveToDisk(this Texture2D texture, string pathInGameData)
- {
- System.Collections.Generic.List list = new System.Collections.Generic.List
- {
- TextureFormat.Alpha8,
- TextureFormat.RGB24,
- TextureFormat.RGBA32,
- TextureFormat.ARGB32
- };
- if (!list.Contains(texture.format))
- {
- return texture.CreateReadable().SaveToDisk(pathInGameData);
- }
- if (pathInGameData.StartsWith("/"))
- {
- pathInGameData = pathInGameData.Substring(1);
- }
- pathInGameData = "/GameData/" + pathInGameData;
- if (!pathInGameData.EndsWith(".png"))
- {
- pathInGameData += ".png";
- }
- bool result;
- try
- {
- FileStream output = new FileStream(KSPUtil.ApplicationRootPath + pathInGameData, FileMode.OpenOrCreate, FileAccess.Write);
- BinaryWriter binaryWriter = new BinaryWriter(output);
- binaryWriter.Write(texture.EncodeToPNG());
- result = true;
- }
- catch (System.Exception)
- {
- result = false;
- }
- return result;
- }
-
- public static Texture2D as2D(this Texture tex)
- {
- return tex as Texture2D;
- }
-
- public static Texture2D GetEmbeddedTexture(string resource, bool compress = false, bool mip = false)
- {
- Stream embeddedContentsStream = GetEmbeddedContentsStream(resource);
- if (embeddedContentsStream == null)
- {
- Log.Debug("[ScienceAlert]:Failed to locate embedded texture '{0}'", resource);
- return null;
- }
- byte[] array = new byte[16384];
- MemoryStream memoryStream = new MemoryStream();
- int count;
- while ((count = embeddedContentsStream.Read(array, 0, array.Length)) > 0)
- {
- memoryStream.Write(array, 0, count);
- }
- Texture2D texture2D = new Texture2D(1, 1, compress ? TextureFormat.DXT5 : TextureFormat.ARGB32, mip);
- if (texture2D.LoadImage(memoryStream.ToArray()))
- {
- return texture2D;
- }
- return null;
- }
-
- public static bool GetEmbeddedContents(string resource, System.Reflection.Assembly assembly, out string contents)
- {
- contents = string.Empty;
- try
- {
- Stream embeddedContentsStream = GetEmbeddedContentsStream(resource, assembly);
- if (embeddedContentsStream != null)
- {
- StreamReader streamReader = new StreamReader(embeddedContentsStream);
- if (streamReader != null)
- {
- contents = streamReader.ReadToEnd();
- return contents.Length > 0;
- }
- }
- }
- catch (System.Exception ex)
- {
- Log.Debug("[ScienceAlert]:GetEmbeddedContents: {0}", ex);
- }
- return false;
- }
-
- public static bool GetEmbeddedContents(string resource, out string contents)
- {
- return GetEmbeddedContents(resource, System.Reflection.Assembly.GetExecutingAssembly(), out contents);
- }
-
- public static byte[] GetEmbeddedContentsBytes(string resource, System.Reflection.Assembly assembly)
- {
- Stream embeddedContentsStream = GetEmbeddedContentsStream(resource, assembly);
- if (embeddedContentsStream != null && embeddedContentsStream.Length > 0L)
- {
- byte[] array = new byte[embeddedContentsStream.Length];
- MemoryStream memoryStream = new MemoryStream();
- int count;
- while ((count = embeddedContentsStream.Read(array, 0, array.Length)) > 0)
- {
- memoryStream.Write(array, 0, count);
- }
- return array;
- }
- return null;
- }
-
- public static Stream GetEmbeddedContentsStream(string resource, System.Reflection.Assembly assembly)
- {
- return assembly.GetManifestResourceStream(resource);
- }
-
- public static Stream GetEmbeddedContentsStream(string resource)
- {
- return GetEmbeddedContentsStream(resource, System.Reflection.Assembly.GetExecutingAssembly());
- }
-
- public static Texture2D LocateTexture(string textureName, bool relativeToGameData = false)
- {
- if (string.IsNullOrEmpty(textureName))
- {
- return null;
- }
- byte[] embeddedContentsBytes = GetEmbeddedContentsBytes(textureName, System.Reflection.Assembly.GetExecutingAssembly());
- Texture2D texture2D;
- if (embeddedContentsBytes != null)
- {
- texture2D = new Texture2D(1, 1, TextureFormat.ARGB32, false);
- if (texture2D.LoadImage(embeddedContentsBytes))
- {
- return texture2D;
- }
- }
- string text = Path.GetFileNameWithoutExtension(textureName);
- string text2 = Path.GetDirectoryName(textureName);
- if (text.StartsWith("/") || text.StartsWith("\\"))
- {
- text = text.Substring(1);
- }
- if (text2.EndsWith("/") || text2.EndsWith("\\"))
- {
- text2 = text2.Substring(1);
- }
- if (relativeToGameData)
- {
- textureName = text2 + "/" + text;
- }
- else
- {
- textureName = ConfigUtil.GetRelativeToGameData(ConfigUtil.GetDllDirectoryPath()) + text2 + "/" + text;
- }
- texture2D = GameDatabase.Instance.GetTexture(textureName, false);
- if (texture2D == null)
- {
- Log.Debug("[ScienceAlert]:Failed to find texture '{0}'", textureName);
- }
- return texture2D;
- }
-
- public static void FlipTexture(Texture2D tex, bool horizontal, bool vertical)
- {
- Color32[] pixels = tex.GetPixels32();
- Color32[] array = new Color32[pixels.Length];
- for (int i = 0; i < tex.height; i++)
- {
- for (int j = 0; j < tex.width; j++)
- {
- int num = (vertical ? tex.height - i - 1 : i) * tex.width + (horizontal ? tex.width - j - 1 : j);
- array[i * tex.width + j] = pixels[num];
- }
- }
- tex.SetPixels32(array);
- tex.Apply();
- }
-
- public static Texture2D CreateReadable(this Texture2D original)
- {
- if (original.width == 0 || original.height == 0)
- {
- throw new System.Exception("CreateReadable: Original has zero width or height or both");
- }
- Texture2D texture2D = new Texture2D(original.width, original.height);
- RenderTexture temporary = RenderTexture.GetTemporary(original.width, original.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB, 1);
- Graphics.Blit(original, temporary);
- RenderTexture.active = temporary;
- texture2D.ReadPixels(new Rect(0f, 0f, (float)texture2D.width, (float)texture2D.height), 0, 0);
- RenderTexture.active = null;
- RenderTexture.ReleaseTemporary(temporary);
- return texture2D;
- }
-
- public static Texture2D Cutout(this Texture2D source, Rect src, bool rectIsInUV = false)
- {
- Rect src2 = new Rect(src);
- if (rectIsInUV)
- {
- src2.x *= (float)source.width;
- src2.width *= (float)source.width;
- src2.y *= (float)source.height;
- src2.height *= (float)source.height;
- }
- return Cutout_Internal(source, src2);
- }
-
- public static Texture2D Cutout(this Renderer renderer, Rect uv)
- {
- return ((Texture2D)renderer.sharedMaterial.mainTexture).Cutout(uv, true);
- }
-
- private static Texture2D Cutout_Internal(Texture2D source, Rect src, bool secondAttempt = false)
- {
- Texture2D texture2D = new Texture2D(Mathf.FloorToInt(src.width), Mathf.FloorToInt(src.height), TextureFormat.ARGB32, false);
- Texture2D result;
- try
- {
- Color[] pixels = source.GetPixels(Mathf.FloorToInt(src.x), Mathf.FloorToInt(src.y), Mathf.FloorToInt(src.width), Mathf.FloorToInt(src.height));
- texture2D.SetPixels(pixels);
- texture2D.Apply();
- result = texture2D;
- }
- catch (System.Exception)
- {
- result = secondAttempt ? null : Cutout_Internal(source.CreateReadable(), src, true);
- }
- return result;
- }
-
- public static void GenerateRandom(this Texture2D tex)
- {
- Color32[] pixels = tex.GetPixels32();
- for (int i = 0; i < tex.height; i++)
- {
- for (int j = 0; j < tex.width; j++)
- {
- pixels[i * tex.width + j] = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f));
- }
- }
- tex.SetPixels32(pixels);
- tex.Apply();
- }
-
- public static Texture2D GenerateRandom(int w, int h)
- {
- Texture2D texture2D = new Texture2D(w, h, TextureFormat.ARGB32, false);
- texture2D.GenerateRandom();
- return texture2D;
- }
- }
-}
diff --git a/ScienceAlert.Experiments/BiomeFilter.cs b/ScienceAlert.Experiments/BiomeFilter.cs
deleted file mode 100644
index 3926925..0000000
--- a/ScienceAlert.Experiments/BiomeFilter.cs
+++ /dev/null
@@ -1,186 +0,0 @@
-using System;
-using ReeperCommon;
-using UnityEngine;
-
-namespace ScienceAlert.Experiments
-{
- public class BiomeFilter : MonoBehaviour
- {
- private const int HALF_SEARCH_DIMENSIONS = 2; // box around the point on the biome map to
-
- private CelestialBody current; // which CelestialBody we've got a cached biome map texture for
- private Texture2D projectedMap; // this is the cleaned biome map of the current CelestialBody
- private System.Collections.IEnumerator projector; // this coroutine constructs the projectedMap from current CelestialBody
- private const float COLOR_THRESHOLD = 0.005f; // Maximum color difference for two colors to be considered the same
-
- void Start()
- {
- GameEvents.onDominantBodyChange.Add(OnDominantBodyChanged);
- GameEvents.onVesselChange.Add(OnVesselChanged);
- ReprojectBiomeMap(FlightGlobals.currentMainBody);
- }
-
- void OnDestroy()
- {
- GameEvents.onVesselChange.Remove(OnVesselChanged);
- GameEvents.onDominantBodyChange.Remove(OnDominantBodyChanged);
- }
-
- public void Update()
- {
- if (projector != null)
- projector.MoveNext();
- }
-
- public bool GetCurrentBiome(out string biome)
- {
- biome = "N/A";
-
- if (FlightGlobals.ActiveVessel == null) return false;
-
- string possibleBiome = string.Empty;
-
- if (GetBiome(FlightGlobals.ActiveVessel.latitude * Mathf.Deg2Rad, FlightGlobals.ActiveVessel.longitude * Mathf.Deg2Rad, out possibleBiome))
- {
- // the biome we got is most likely good
- biome = possibleBiome;
- return true;
- }
- // the biome we got is not very accurate (e.g. polar ice caps in middle of kerbin grasslands and
- // such, due to the way the biome map is filtered).
- biome = possibleBiome;
- return false;
- }
-
- public bool GetBiome(double latRad, double lonRad, out string biome)
- {
- biome = string.Empty;
- var vessel = FlightGlobals.ActiveVessel;
-
- if (vessel == null || vessel.mainBody.BiomeMap == null || vessel.mainBody.BiomeMap.MapName == null)
- return true;
-
- if (!string.IsNullOrEmpty(vessel.landedAt))
- {
- biome = Vessel.GetLandedAtString(vessel.landedAt);
- return true;
- }
-
- var possibleBiome = vessel.mainBody.BiomeMap.GetAtt(latRad, lonRad);
-
- if (!IsBusy)
- {
- if (!VerifyBiomeResult(latRad, lonRad, possibleBiome)) return false;
- biome = possibleBiome.name;
- return true;
- }
-
- biome = possibleBiome.name;
- return true;
- }
-
- private bool Similar(Color first, Color second)
- {
- return Mathf.Abs(first.r - second.r) < COLOR_THRESHOLD && Mathf.Abs(first.g - second.g) < COLOR_THRESHOLD && Mathf.Abs(first.b - second.b) < COLOR_THRESHOLD;
- }
-
- private bool VerifyBiomeResult(double lat, double lon, CBAttributeMapSO.MapAttribute target)
- {
- if (projectedMap == null) return true; // we'll have to assume it's accurate since we can't prove otherwise
- if (target == null || target.mapColor == null) return true; // this shouldn't happen
-
- lon -= Mathf.PI * 0.5f;
- if (lon < 0d) lon += Mathf.PI * 2d;
- lon %= Mathf.PI * 2d;
-
- int x_center = (int)Math.Round(projectedMap.width * (float)(lon / (Mathf.PI * 2)), 0);
- int y_center = (int)Math.Round(projectedMap.height * ((float)(lat / Mathf.PI) + 0.5f), 0);
-
- for (int y = y_center - HALF_SEARCH_DIMENSIONS; y < y_center + HALF_SEARCH_DIMENSIONS; ++y)
- for (int x = x_center - HALF_SEARCH_DIMENSIONS; x < x_center + HALF_SEARCH_DIMENSIONS; ++x)
- {
- Color c = projectedMap.GetPixel(x, y);
- if (Similar(c, target.mapColor))
- return true; // we have a match, no need to look further
- }
- return false;
- }
-
- private void ReprojectBiomeMap(CelestialBody newBody)
- {
- projector = ReprojectMap(newBody);
- }
-
- private System.Collections.IEnumerator ReprojectMap(CelestialBody newBody)
- {
- if (current == newBody)
- {
- projector = null;
- yield break;
- }
-
- if (newBody == null)
- {
- projector = null;
- current = null;
- yield break;
- }
-
- current = null;
-
- if (newBody.BiomeMap == null || newBody.BiomeMap.MapName == null)
- {
- projectedMap = null;
- projector = null;
- yield break;
- }
-
- Texture2D projection = new Texture2D(newBody.BiomeMap.Width, newBody.BiomeMap.Height, TextureFormat.ARGB32, false);
- projection.filterMode = FilterMode.Point;
-
- yield return null;
-
- float timer = Time.realtimeSinceStartup;
- Color32[] pixels = projection.GetPixels32();
-
- for (int y = 0; y < projection.height; ++y)
- {
- for (int x = 0; x < projection.width; ++x)
- {
- // convert x and y into uv coordinates
- float u = (float)x / projection.width;
- float v = (float)y / projection.height;
-
- // convert uv coordinates into latitude and longitude
- double lat = Math.PI * v - Math.PI * 0.5;
- double lon = 2d * Math.PI * u + Math.PI * 0.5;
-
- // set biome color in our clean texture
- pixels[y * projection.width + x] = (Color32)newBody.BiomeMap.GetAtt(lat, lon).mapColor;
- }
-
- if (y % 5 == 0)
- yield return null;
- }
-
- projection.SetPixels32(pixels);
- projection.Apply();
-
- current = newBody;
- projectedMap = projection;
- projector = null; // we're finished!
- }
-
- private void OnDominantBodyChanged(GameEvents.FromToAction bodies)
- {
- ReprojectBiomeMap(bodies.to);
- }
-
- private void OnVesselChanged(Vessel v)
- {
- ReprojectBiomeMap(v.mainBody);
- }
-
- public bool IsBusy => projector != null;
- }
-}
\ No newline at end of file
diff --git a/ScienceAlert.ProfileData/ExperimentSettings.cs b/ScienceAlert.ProfileData/ExperimentSettings.cs
deleted file mode 100644
index ef75680..0000000
--- a/ScienceAlert.ProfileData/ExperimentSettings.cs
+++ /dev/null
@@ -1,148 +0,0 @@
-using ReeperCommon;
-
-namespace ScienceAlert.ProfileData
-{
- public class ExperimentSettings
- {
- public enum FilterMethod
- {
- Unresearched,
- NotMaxed,
- LessThanFiftyPercent,
- LessThanNinetyPercent
- }
-
- private bool _enabled = true;
- private bool _soundOnDiscovery = true;
- private bool _animationOnDiscovery = true;
- private bool _stopWarpOnDiscovery;
- private FilterMethod _filter;
- public bool IsDefault;
- public event Callback OnChanged = delegate{};
-
- public bool Enabled
- {
- get
- {
- return _enabled;
- }
- set
- {
- if (value == _enabled) return;
- _enabled = value;
- OnChanged();
- }
- }
-
- public bool SoundOnDiscovery
- {
- get
- {
- return _soundOnDiscovery;
- }
- set
- {
- if (_soundOnDiscovery != value)
- {
- _soundOnDiscovery = value;
- OnChanged();
- }
- }
- }
-
- public bool AnimationOnDiscovery
- {
- get
- {
- return _animationOnDiscovery;
- }
- set
- {
- if (value != _animationOnDiscovery)
- {
- _animationOnDiscovery = value;
- OnChanged();
- }
- }
- }
-
- public bool StopWarpOnDiscovery
- {
- get
- {
- return _stopWarpOnDiscovery;
- }
- set
- {
- if (value != _stopWarpOnDiscovery)
- {
- _stopWarpOnDiscovery = value;
- OnChanged();
- }
- }
- }
-
- public FilterMethod Filter
- {
- get
- {
- return _filter;
- }
- set
- {
- if (value != _filter)
- {
- _filter = value;
- OnChanged();
- }
- }
- }
-
- public ExperimentSettings()
- {
- }
-
- public ExperimentSettings(ExperimentSettings other)
- {
- Enabled = other.Enabled;
- SoundOnDiscovery = other.SoundOnDiscovery;
- AnimationOnDiscovery = other.AnimationOnDiscovery;
- StopWarpOnDiscovery = other.StopWarpOnDiscovery;
- Filter = other.Filter;
- IsDefault = other.IsDefault;
- }
-
- public void OnLoad(ConfigNode node)
- {
- Enabled = node.Parse("Enabled", true);
- SoundOnDiscovery = node.Parse("SoundOnDiscovery", true);
- AnimationOnDiscovery = node.Parse("AnimationOnDiscovery", true);
- StopWarpOnDiscovery = node.Parse("StopWarpOnDiscovery", false);
- string value = node.GetValue("Filter");
- if (string.IsNullOrEmpty(value))
- {
- Log.Debug("[ScienceAlert]:Settings: invalid experiment filter");
- value = System.Enum.GetValues(typeof(FilterMethod)).GetValue(0).ToString();
- }
- Filter = (FilterMethod)System.Enum.Parse(typeof(FilterMethod), value);
- IsDefault = node.Parse("IsDefault", false);
- }
-
- public void OnSave(ConfigNode node)
- {
- node.AddValue("Enabled", Enabled);
- node.AddValue("SoundOnDiscovery", SoundOnDiscovery);
- node.AddValue("AnimationOnDiscovery", AnimationOnDiscovery);
- node.AddValue("StopWarpOnDiscovery", StopWarpOnDiscovery);
- node.AddValue("Filter", Filter);
- node.AddValue("IsDefault", IsDefault);
- }
-
- public override string ToString()
- {
- ConfigNode configNode = new ConfigNode();
- OnSave(configNode);
- return configNode.ToString();
- }
- }
-}
diff --git a/ScienceAlert.ProfileData/Profile.cs b/ScienceAlert.ProfileData/Profile.cs
deleted file mode 100644
index dafcee0..0000000
--- a/ScienceAlert.ProfileData/Profile.cs
+++ /dev/null
@@ -1,170 +0,0 @@
-using System.Collections.Generic;
-using ReeperCommon;
-
-namespace ScienceAlert.ProfileData
-{
- internal class Profile
- {
- [Persistent(isPersistant = true)]
- public string name = string.Empty;
-
- [Persistent]
- public bool modified;
-
- [Persistent]
- public float scienceThreshold;
-
- [System.NonSerialized]
- public Dictionary settings;
-
- public ExperimentSettings this[string expid]
- {
- get
- {
- if (settings.ContainsKey(expid))
- {
- return settings[expid];
- }
- settings[expid] = new ExperimentSettings();
- return settings[expid];
- }
- private set
- {
- settings.Add(expid.ToLower(), value);
- }
- }
-
- public string DisplayName
- {
- get
- {
- if (modified)
- {
- return "*" + name + "*";
- }
- return name;
- }
- }
-
- public float ScienceThreshold
- {
- get
- {
- return scienceThreshold;
- }
- set
- {
- if (value != scienceThreshold)
- {
- modified = true;
- }
- scienceThreshold = value;
- }
- }
-
- public Profile(ConfigNode node)
- {
- Setup();
- OnLoad(node);
- RegisterEvents();
- }
-
- public Profile(string name)
- {
- Log.Debug("VERB ALERT:Creating profile '{0}' with default values", name);
- this.name = name;
- Setup();
- RegisterEvents();
- }
-
- public Profile(Profile other)
- {
- Dictionary.KeyCollection keys = other.settings.Keys;
- settings = new Dictionary();
- foreach (string current in keys)
- {
- settings.Add(current, new ExperimentSettings(other.settings[current]));
- }
- name = string.Copy(other.name);
- modified = other.modified;
- scienceThreshold = other.scienceThreshold;
- RegisterEvents();
- }
-
- private void Setup()
- {
- settings = new Dictionary();
- try
- {
- List experimentIDs = ResearchAndDevelopment.GetExperimentIDs();
- foreach (string current in experimentIDs)
- {
- settings.Add(current, new ExperimentSettings());
- }
- }
- catch (System.Exception ex)
- {
- Log.Debug("[ScienceAlert]:Profile '{1}' constructor exception: {0}", ex, string.IsNullOrEmpty(name) ? "(unnamed)" : name);
- }
- }
-
- public void OnSave(ConfigNode node)
- {
- ConfigNode.CreateConfigFromObject(this, 0, node);
- foreach (KeyValuePair current in settings)
- {
- current.Value.OnSave(node.AddNode(new ConfigNode(current.Key)));
- }
- Log.Debug("ALERT:Profile: OnSave config: {0}", node.ToString());
- }
-
- public void OnLoad(ConfigNode node)
- {
- Log.Debug("ALERT:Loading profile...");
- ConfigNode.LoadObjectFromConfig(this, node);
- if (string.IsNullOrEmpty(name))
- {
- name = "nameless." + System.Guid.NewGuid();
- }
- else
- {
- Log.Debug("ALERT:Profile name is '{0}'", name);
- }
- string[] array = node.nodes.DistinctNames();
- for (int i = 0; i < array.Length; i++)
- {
- string text = array[i];
- ConfigNode node2 = node.GetNode(text);
- if (!settings.ContainsKey(text))
- {
- settings.Add(text, new ExperimentSettings());
- }
- settings[text].OnLoad(node2);
- }
- }
-
- public Profile Clone()
- {
- return new Profile(this);
- }
-
- public static Profile MakeDefault()
- {
- return new Profile("default");
- }
-
- private void SettingChanged()
- {
- Log.Debug("ALERT:Profile '{0}' was modified!", name);
- modified = true;
- }
-
- private void RegisterEvents()
- {
- foreach (KeyValuePair current in settings)
- {
- current.Value.OnChanged += SettingChanged;
- }
- }
- }
-}
diff --git a/ScienceAlert.Toolbar/BlizzyInterface.cs b/ScienceAlert.Toolbar/BlizzyInterface.cs
deleted file mode 100644
index d4a4392..0000000
--- a/ScienceAlert.Toolbar/BlizzyInterface.cs
+++ /dev/null
@@ -1,392 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using UnityEngine;
-using ReeperCommon;
-
-namespace ScienceAlert.Toolbar
-{
- class BlizzyInterface : MonoBehaviour, IToolbar
- {
- private const string NormalFlaskTexture = "ScienceAlert/textures/flask";
- private List StarFlaskTextures = new List();
- private float FrameRate = 24f;
- private int FrameCount = 100;
- private int CurrentFrame = 0;
-
- IButton button;
- IEnumerator animation;
-
- public event ToolbarClickHandler OnClick;
-
- void Start()
- {
- SliceAtlasTexture();
- button = ToolbarManager.Instance.add("ScienceAlert", "PopupOpen");
- button.Text = "Science Alert";
- button.ToolTip = "Left-click to view alert experiments; Right-click for settings";
- button.TexturePath = NormalFlaskTexture;
- button.OnClick += ce => {
- OnClick(new ClickInfo { button = ce.MouseButton, used = false });
- };
- FrameRate = Settings.Instance.StarFlaskFrameRate;
- }
-
- private void SliceAtlasTexture()
- {
- Func GetFrame = delegate (int frame, int desiredLen)
- {
- string str = frame.ToString();
- while (str.Length < desiredLen)
- str = "0" + str;
- return str;
- };
-
- // load textures
- try
- {
- if (!GameDatabase.Instance.ExistsTexture(NormalFlaskTexture))
- {
- // load normal flask texture
- Log.Debug("Loading normal flask texture");
-
- Texture2D nflask = ResourceUtil.GetEmbeddedTexture("Textures.flask.png", true);
- if (nflask == null)
- {
- Log.Error("Failed to create normal flask texture!");
- }
- else
- {
- GameDatabase.TextureInfo ti = new GameDatabase.TextureInfo(null, nflask, false, true, true);
- ti.name = NormalFlaskTexture;
- GameDatabase.Instance.databaseTexture.Add(ti);
- Log.Debug("Created normal flask texture {0}", ti.name);
- }
-
- Texture2D sheet = ResourceUtil.GetEmbeddedTexture("Textures.sheet.png");
- if (sheet == null)
- {
- Log.Error("Failed to create sprite sheet texture!");
- }
- else
- {
- var rt = RenderTexture.GetTemporary(sheet.width, sheet.height);
- var oldRt = RenderTexture.active;
- int invertHeight = ((FrameCount - 1) / (sheet.width / 24)) * 24;
-
- Graphics.Blit(sheet, rt);
- RenderTexture.active = rt;
-
- for (int i = 0; i < FrameCount; ++i)
- {
- StarFlaskTextures.Add(NormalFlaskTexture + GetFrame(i + 1, 4));
- Texture2D sliced = new Texture2D(24, 24, TextureFormat.ARGB32, false);
-
- sliced.ReadPixels(new Rect((i % (sheet.width / 24)) * 24, /*invertHeight -*/ (i / (sheet.width / 24)) * 24, 24, 24), 0, 0);
- sliced.Apply();
-
- GameDatabase.TextureInfo ti = new GameDatabase.TextureInfo(null, sliced, false, false, false);
- ti.name = StarFlaskTextures.Last();
-
- GameDatabase.Instance.databaseTexture.Add(ti);
- Log.Debug("Added sheet texture {0}", ti.name);
- }
-
- RenderTexture.active = oldRt;
- RenderTexture.ReleaseTemporary(rt);
- }
- Log.Debug("Finished loading sprite sheet textures.");
- }
- else
- { // textures already loaded
- for (int i = 0; i < FrameCount; ++i)
- StarFlaskTextures.Add(NormalFlaskTexture + GetFrame(i + 1, 4));
- }
- }
- catch (Exception e)
- {
- Log.Error("Failed to load textures: {0}", e);
- }
- }
-
- ///
- /// Normal cleanup
- ///
- void OnDestroy()
- {
- //Log.Verbose("Destroying BlizzyInterface");
- button.Destroy();
- }
-
- ///
- /// Begins playing the "star flask" animation, used when a new
- /// experiment has become available.
- ///
- public void PlayAnimation()
- {
- if (animation == null) animation = DoAnimation();
- }
-
- ///
- /// Stops playing animation (but leaves the current frame state)
- ///
- public void StopAnimation()
- {
- animation = null;
- }
-
- ///
- /// Switch to normal flask texture
- ///
- public void SetUnlit()
- {
- animation = null;
- button.TexturePath = NormalFlaskTexture;
- }
-
- public void SetLit()
- {
- animation = null;
- button.TexturePath = StarFlaskTextures[0];
- }
-
- public IDrawable Drawable
- {
- get
- {
- return button.Drawable;
- }
-
- set
- {
- button.Drawable = value;
- }
- }
-
- public bool Important
- {
- get
- {
- return button.Important;
- }
-
- set
- {
- button.Important = value;
- }
- }
-
- public bool IsAnimating => animation != null;
-
- public bool IsLit => animation == null && button.TexturePath != NormalFlaskTexture;
-
- public bool IsNormal => !IsAnimating && !IsLit;
-
- void Update()
- {
- if (animation != null) animation.MoveNext();
- }
-
- ///
- /// Is called by Update whenever animation exists to
- /// update animation frame.
- ///
- /// Note: I didn't make this into an actual coroutine
- /// because StopCoroutine seems to sometimes throw
- /// exceptions
- ///
- ///
- IEnumerator DoAnimation()
- {
- float elapsed = 0f;
- while (true)
- {
- while (elapsed < 1f / FrameRate)
- {
- elapsed += Time.deltaTime;
- yield return new WaitForSeconds(1f / FrameRate);
- }
- elapsed -= 1f / FrameRate;
- CurrentFrame = (CurrentFrame + 1) % FrameCount;
- button.TexturePath = StarFlaskTextures[CurrentFrame];
- }
- }
- }
-}
-
-
-
-//using System;
-//using System.Collections;
-//using System.Collections.Generic;
-//using System.Linq;
-//using ReeperCommon;
-//using UnityEngine;
-
-//namespace ScienceAlert.Toolbar
-//{
-// internal class BlizzyInterface : MonoBehaviour, IToolbar
-// {
-// private readonly List StarFlaskTextures = new List();
-// private float FrameRate = 24f;
-// private int FrameCount = 100;
-// private int CurrentFrame;
-// private IButton button;
-// private IEnumerator animation;
-// public event ToolbarClickHandler OnClick;
-
-// public IDrawable Drawable
-// {
-// get
-// {
-// return button.Drawable;
-// }
-// set
-// {
-// button.Drawable = value;
-// }
-// }
-
-// public bool Important
-// {
-// get
-// {
-// return button.Important;
-// }
-// set
-// {
-// button.Important = value;
-// }
-// }
-
-// public bool IsAnimating => animation != null;
-
-// public bool IsLit => animation == null && button.TexturePath != "ScienceAlert/textures/flask";
-
-// public bool IsNormal => !IsAnimating && !IsLit;
-
-// private void Start()
-// {
-// SliceAtlasTexture();
-// button = ToolbarManager.Instance.add("ScienceAlert", "PopupOpen");
-// button.Text = "Science Alert";
-// button.ToolTip = "Left-click to view alert experiments; Right-click for settings";
-// button.OnClick += delegate(ClickEvent ce)
-// {
-// OnClick(new ClickInfo{button = ce.MouseButton,used = false});
-// };
-// FrameRate = Settings.Instance.StarFlaskFrameRate;
-// }
-
-// private void SliceAtlasTexture()
-// {
-// Func func = delegate(int frame, int desiredLen)
-// {
-// string text = frame.ToString();
-// while (text.Length < desiredLen)
-// {
-// text = "0" + text;
-// }
-// return text;
-// };
-// try
-// {
-// if (!GameDatabase.Instance.ExistsTexture("ScienceAlert/textures/flask"))
-// {
-// Texture2D embeddedTexture = ResourceUtil.GetEmbeddedTexture("Textures.flask.png", true);
-// GameDatabase.TextureInfo textureInfo = new GameDatabase.TextureInfo(null, embeddedTexture, false, true, true);
-// GameDatabase.Instance.databaseTexture.Add(textureInfo);
-// Texture2D embeddedTexture2 = ResourceUtil.GetEmbeddedTexture("Textures.sheet.png");
-// RenderTexture temporary = RenderTexture.GetTemporary(embeddedTexture2.width, embeddedTexture2.height);
-// RenderTexture active = RenderTexture.active;
-// Graphics.Blit(embeddedTexture2, temporary);
-// RenderTexture.active = temporary;
-// for (var i = 0; i < FrameCount; i++)
-// {
-// StarFlaskTextures.Add("ScienceAlert/textures/flask" + func(i + 1, 4));
-// Texture2D texture2D = new Texture2D(24, 24, TextureFormat.ARGB32, false);
-// texture2D.ReadPixels(new Rect(i % (embeddedTexture2.width / 24) * 24, i / (embeddedTexture2.width / 24) * 24, 24f, 24f), 0, 0);
-// texture2D.Apply();
-// GameDatabase.TextureInfo textureInfo2 =
-// new GameDatabase.TextureInfo(null, texture2D, false, false, false)
-// {
-// name = StarFlaskTextures.Last()
-// };
-// GameDatabase.Instance.databaseTexture.Add(textureInfo2);
-// }
-// RenderTexture.active = active;
-// RenderTexture.ReleaseTemporary(temporary);
-// }
-// else
-// {
-// for (int j = 0; j < FrameCount; j++)
-// {
-// StarFlaskTextures.Add("ScienceAlert/textures/flask" + func(j + 1, 4));
-// }
-// }
-// }
-// catch (Exception ex)
-// {
-// Log.Debug("[ScienceAlert]:Failed to load textures: {0}", ex);
-// }
-// }
-
-// private void OnDestroy()
-// {
-// Log.Debug("VERB ALERT:Destroying BlizzyInterface");
-// button.Destroy();
-// }
-
-// public void PlayAnimation()
-// {
-// if (animation == null)
-// {
-// animation = DoAnimation();
-// }
-// }
-
-// public void StopAnimation()
-// {
-// animation = null;
-// }
-
-// public void SetUnlit()
-// {
-// animation = null;
-// }
-
-// public void SetLit()
-// {
-// animation = null;
-// button.TexturePath = StarFlaskTextures[0];
-// }
-
-// private void Update()
-// {
-// if (animation != null)
-// {
-// animation.MoveNext();
-// }
-// }
-
-// private IEnumerator DoAnimation()
-// {
-// float num = 0f;
-// while (true)
-// {
-// if (num >= 1f / FrameRate)
-// {
-// num -= 1f / FrameRate;
-// CurrentFrame = (CurrentFrame + 1) % FrameCount;
-// button.TexturePath = StarFlaskTextures[CurrentFrame];
-// }
-// else
-// {
-// num += Time.deltaTime;
-// yield return new WaitForSeconds(1f / FrameRate);
-// }
-// }
-// }
-// }
-//}
diff --git a/ScienceAlert.Toolbar/ClickInfo.cs b/ScienceAlert.Toolbar/ClickInfo.cs
deleted file mode 100644
index da46763..0000000
--- a/ScienceAlert.Toolbar/ClickInfo.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-namespace ScienceAlert.Toolbar
-{
- public class ClickInfo
- {
- public int button;
- public bool used;
-
- public bool Unused => !used;
-
- public ClickInfo()
- {
- button = 0;
- used = false;
- }
-
- public void Consume()
- {
- used = true;
- }
- }
-}
diff --git a/ScienceAlert.Toolbar/IToolbar.cs b/ScienceAlert.Toolbar/IToolbar.cs
deleted file mode 100644
index 6cd68db..0000000
--- a/ScienceAlert.Toolbar/IToolbar.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-namespace ScienceAlert.Toolbar
-{
- public delegate void ToolbarClickHandler(ClickInfo click);
-
- public interface IToolbar
- {
- event ToolbarClickHandler OnClick;
-
- IDrawable Drawable {get;set;}
-
- bool Important {get;set;}
-
- bool IsAnimating {get;}
-
- bool IsNormal {get;}
-
- bool IsLit {get;}
-
- void PlayAnimation();
-
- void StopAnimation();
-
- void SetUnlit();
-
- void SetLit();
- }
-}
diff --git a/ScienceAlert.Toolbar/ToolbarManager.cs b/ScienceAlert.Toolbar/ToolbarManager.cs
deleted file mode 100644
index b375ded..0000000
--- a/ScienceAlert.Toolbar/ToolbarManager.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-namespace ScienceAlert.Toolbar
-{
- public class ToolbarManager : IToolbarManager
- {
- private static bool? toolbarAvailable;
- private static IToolbarManager instance_;
- private object realToolbarManager;
- private System.Reflection.MethodInfo addMethod;
- private System.Collections.Generic.Dictionary