commit a547a31a378bbc8d4c01a60887030170347cc28e Author: brbarnesEA <161645603+brbarnesEA@users.noreply.github.com> Date: Tue Mar 5 11:56:45 2024 -0800 TS_RA2_Mission_Editor_sourcecode_23.02.2023_1 TS_RA2_Mission_Editor_sourcecode_23.02.2023_1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d07bc44 --- /dev/null +++ b/.gitignore @@ -0,0 +1,71 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# MSVC +[Dd]ebug*/ +[Rr]elease*/ +build/ +build_*/ +*.vs +*.user +*.spec +*.ncb +*.sdf +*.suo +*.sln +*.vcxproj +*.filters +*.aps + +# CMake +CMakeFiles/ +CMakeCache.txt +CMakeUserPresets.json +*.dir + +# Windows +thumbs.db +desktop.ini +*.log + +# Misc +*.tmp +*.bak +*.idb + +# FinalSun/FinalAlert specific +dist/ +intermediate/ +vcpkg_installed/ +vcpkg_downloads/ +[Tt]emplate/ diff --git a/3rdParty/xcc/.gitignore b/3rdParty/xcc/.gitignore new file mode 100644 index 0000000..962f2c9 --- /dev/null +++ b/3rdParty/xcc/.gitignore @@ -0,0 +1,3 @@ +.vs/ +Debug/ +Release/ diff --git a/3rdParty/xcc/COPYING b/3rdParty/xcc/COPYING new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/3rdParty/xcc/COPYING @@ -0,0 +1,674 @@ + 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 + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/3rdParty/xcc/Library/StdAfx.cpp b/3rdParty/xcc/Library/StdAfx.cpp new file mode 100644 index 0000000..799dfed --- /dev/null +++ b/3rdParty/xcc/Library/StdAfx.cpp @@ -0,0 +1,19 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" diff --git a/3rdParty/xcc/Library/StdAfx.h b/3rdParty/xcc/Library/StdAfx.h new file mode 100644 index 0000000..ce37391 --- /dev/null +++ b/3rdParty/xcc/Library/StdAfx.h @@ -0,0 +1,45 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +// #define WIN32_LEAN_AND_MEAN + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef XCC_MINIMAL_BUILD +#include +#endif + +using namespace std; +using boost::iequals; +using boost::to_lower_copy; +using boost::trim_copy; diff --git a/3rdParty/xcc/XCC.props b/3rdParty/xcc/XCC.props new file mode 100644 index 0000000..1e1a74b --- /dev/null +++ b/3rdParty/xcc/XCC.props @@ -0,0 +1,19 @@ + + + + <_ProjectFileVersion>10.0.30319.1 + + + + ..\misc;%(AdditionalIncludeDirectories) + 4018;4201;4267;4554;4806;%(DisableSpecificWarnings) + stdcpplatest + _HAS_STD_BYTE=0;NOMINMAX;%(PreprocessorDefinitions) + + + "type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'" + dsound.lib;gdiplus.lib;%(AdditionalDependencies) + + + + diff --git a/3rdParty/xcc/misc/blowfish.cpp b/3rdParty/xcc/misc/blowfish.cpp new file mode 100644 index 0000000..9e1833c --- /dev/null +++ b/3rdParty/xcc/misc/blowfish.cpp @@ -0,0 +1,427 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include + +#include + +const Cblowfish::t_bf_p g_p = +{ + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, + 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, + 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, + 0x9216d5d9, 0x8979fb1b, +}; + +const Cblowfish::t_bf_s g_s = +{ + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, + 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, + 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, + 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, + 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, + 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, + 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, + 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, + 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, + 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, + 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, + 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, + 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, + 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, + 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, + 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, + 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, + 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, + 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, + 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, + 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, + 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, + 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, + 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, + 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, + 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, + 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, + 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, + 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, + 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, + 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, + 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, + 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, + 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, + 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, + 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, + 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, + 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, + 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, + 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, + 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, + 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, + 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, + 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, + 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, + 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, + 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, + 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, + 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, + 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, + 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, + 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, + 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, + 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, + 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, + 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, + 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, + 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, + 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, + 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, + 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, + 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, + 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, + 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, + 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, + 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, + 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, + 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, + 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, + 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, + 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, + 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, + 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, + 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, + 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, + 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, + 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, + 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, + 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, + 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, + 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, + 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, + 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, + 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, + 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, + 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, + 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, + 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, + 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, + 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, + 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, + 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, + 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, + 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, + 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, + 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, + 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, + 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, + 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, + 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, + 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, + 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, + 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, + 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, + 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, + 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, + 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, + 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, + 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, + 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, + 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, + 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, + 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, + 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, + 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, + 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, + 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, + 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, + 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, + 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, + 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, + 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, + 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, + 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, + 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, + 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, + 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, + 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, + 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, + 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, + 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, + 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, + 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, + 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, + 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, + 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, + 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, + 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, + 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, + 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, + 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, + 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, + 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, + 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, + 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, + 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, + 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, + 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, + 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, + 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, + 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, + 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, + 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, + 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, + 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, + 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, + 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, + 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, + 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, + 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, + 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, + 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, + 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, + 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, + 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, + 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, + 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, + 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, + 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6, +}; + +void Cblowfish::set_key(data_ref key) +{ + memcpy(m_p, g_p, sizeof(t_bf_p)); + memcpy(m_s, g_s, sizeof(t_bf_s)); + + int j = 0; + for (int i = 0; i < 18; i++) + { + int a = key[j++]; j %= key.size(); + int b = key[j++]; j %= key.size(); + int c = key[j++]; j %= key.size(); + int d = key[j++]; j %= key.size(); + m_p[i] ^= a << 24 | b << 16 | c << 8 | d; + } + + uint32_t datal = 0; + uint32_t datar = 0; + + for (int i = 0; i < 18; ) + { + encipher(datal, datar); + + m_p[i++] = datal; + m_p[i++] = datar; + } + + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 256; ) + { + encipher(datal, datar); + + m_s[i][j++] = datal; + m_s[i][j++] = datar; + } + } +} + +uint32_t Cblowfish::S(uint32_t x, int i) const +{ + return m_s[i][(x >> ((3 - i) << 3)) & 0xff]; +} + +uint32_t Cblowfish::bf_f(uint32_t x) const +{ + return ((S(x, 0) + S(x, 1)) ^ S(x, 2)) + S(x, 3); +} + +void Cblowfish::ROUND(uint32_t& a, uint32_t b, int n) const +{ + a ^= bf_f(b) ^ m_p[n]; +} + +void Cblowfish::encipher(uint32_t& xl, uint32_t& xr) const +{ + uint32_t Xl = xl; + uint32_t Xr = xr; + + Xl ^= m_p[0]; + ROUND (Xr, Xl, 1); ROUND (Xl, Xr, 2); + ROUND (Xr, Xl, 3); ROUND (Xl, Xr, 4); + ROUND (Xr, Xl, 5); ROUND (Xl, Xr, 6); + ROUND (Xr, Xl, 7); ROUND (Xl, Xr, 8); + ROUND (Xr, Xl, 9); ROUND (Xl, Xr, 10); + ROUND (Xr, Xl, 11); ROUND (Xl, Xr, 12); + ROUND (Xr, Xl, 13); ROUND (Xl, Xr, 14); + ROUND (Xr, Xl, 15); ROUND (Xl, Xr, 16); + Xr ^= m_p[17]; + + xr = Xl; + xl = Xr; +} + +void Cblowfish::decipher(uint32_t& xl, uint32_t& xr) const +{ + uint32_t Xl = xl; + uint32_t Xr = xr; + + Xl ^= m_p[17]; + ROUND (Xr, Xl, 16); ROUND (Xl, Xr, 15); + ROUND (Xr, Xl, 14); ROUND (Xl, Xr, 13); + ROUND (Xr, Xl, 12); ROUND (Xl, Xr, 11); + ROUND (Xr, Xl, 10); ROUND (Xl, Xr, 9); + ROUND (Xr, Xl, 8); ROUND (Xl, Xr, 7); + ROUND (Xr, Xl, 6); ROUND (Xl, Xr, 5); + ROUND (Xr, Xl, 4); ROUND (Xl, Xr, 3); + ROUND (Xr, Xl, 2); ROUND (Xl, Xr, 1); + Xr ^= m_p[0]; + + xl = Xr; + xr = Xl; +} + +static uint32_t reverse(uint32_t v) +{ + _asm + { + mov eax, v + xchg al, ah + rol eax, 16 + xchg al, ah + mov v, eax + } + return v; +} + +void Cblowfish::encipher(const void* s, void* d, int size) const +{ + const uint32_t* r = reinterpret_cast(s); + uint32_t* w = reinterpret_cast(d); + size >>= 3; + while (size--) + { + uint32_t a = reverse(*r++); + uint32_t b = reverse(*r++); + encipher(a, b); + *w++ = reverse(a); + *w++ = reverse(b); + } +} + +void Cblowfish::decipher(const void* s, void* d, int size) const +{ + const uint32_t* r = reinterpret_cast(s); + uint32_t* w = reinterpret_cast(d); + size >>= 3; + while (size--) + { + uint32_t a = reverse(*r++); + uint32_t b = reverse(*r++); + decipher(a, b); + *w++ = reverse(a); + *w++ = reverse(b); + } +} \ No newline at end of file diff --git a/3rdParty/xcc/misc/blowfish.h b/3rdParty/xcc/misc/blowfish.h new file mode 100644 index 0000000..72a3f3f --- /dev/null +++ b/3rdParty/xcc/misc/blowfish.h @@ -0,0 +1,41 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include + +class Cblowfish +{ +public: + using t_bf_p = uint32_t[18]; + using t_bf_s = uint32_t[4][256]; + + void set_key(data_ref); + void encipher(const void* s, void* d, int size) const; + void decipher(const void* s, void* d, int size) const; +private: + void encipher(uint32_t& xl, uint32_t& xr) const; + void decipher(uint32_t& xl, uint32_t& xr) const; + uint32_t S(uint32_t x, int i) const; + uint32_t bf_f(uint32_t x) const; + void ROUND(uint32_t& a, uint32_t b, int n) const; + + t_bf_p m_p; + t_bf_s m_s; +}; diff --git a/3rdParty/xcc/misc/cc_file.cpp b/3rdParty/xcc/misc/cc_file.cpp new file mode 100644 index 0000000..d9e9e11 --- /dev/null +++ b/3rdParty/xcc/misc/cc_file.cpp @@ -0,0 +1,520 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "cc_file.h" + +#ifndef XCC_MINIMAL_BUILD +#include "aud_file.h" +#include "avi_file.h" +#include "big_file.h" +#include "bin_file.h" +#include "bink_file.h" +#include "bmp_file.h" +#include "csf_file.h" +#include "cps_file.h" +#include "dds_file.h" +#include "fnt_file.h" +#include "hva_file.h" +#include "id_log.h" +#include "jpeg_file.h" +#include "map_td_ini_reader.h" +#include "map_ra_ini_reader.h" +#include "map_ts_ini_reader.h" +#include "mix_file.h" +#include "mix_rg_file.h" +#include "mp3_file.h" +#include "null_ini_reader.h" +#include "ogg_file.h" +#include "pak_file.h" +#include "pal_file.h" +#include "pcx_file.h" +#include "png_file.h" +#include "pkt_ts_ini_reader.h" +#include "shp_dune2_file.h" +#include "shp_file.h" +#include "shp_ts_file.h" +#include "sound_ts_ini_reader.h" +#include "st_file.h" +#include "string_conversion.h" +#include "text_file.h" +#include "tga_file.h" +#include "theme_ts_ini_reader.h" +#include "tmp_file.h" +#include "tmp_ra_file.h" +#include "tmp_ts_file.h" +#include "virtual_tfile.h" +#include "voc_file.h" +#include "vqa_file.h" +#include "vqp_file.h" +#include "vxl_file.h" +#include "w3d_file.h" +#include "wav_file.h" +#include "wsa_dune2_file.h" +#include "wsa_file.h" +#include "xcc_dirs.h" +#include "xcc_file.h" +#include "xcc_lmd_file.h" +#include "xif_file.h" +#else +#include "mix_file.h" +#include "xcc_dirs.h" +#endif + + +const char* ft_name[] = +{ + "aud", + "avi", + "big", + "bin", + "bink", + "bmp", + "clipboard", + "csf", + "cps", + "csv", + "dds", + "dir", + "drive", + "fnt", + "html", + "hva", + "ini", + "jpeg", + "jpeg (single)", + "map (dune2)", + "map (td)", + "map (ra)", + "map (ts)", + "map (ts) preview", + "map (ra2)", + "mix", + "mix (rg)", + "mng", + "mp3", + "mrf", + "ogg", + "pak", + "pal", + "pal (jasc)", + "pcx (single)", + "pcx", + "png (single)", + "png", + "pkt (ts)", + "riff", + "rules ini (ts)", + "rules ini (ra2)", + "shp (dune2)", + "shp", + "shp (ts)", + "sound ini (ts)", + "sound ini (ra2)", + "string table", + "text", + "tga", + "tga (single)", + "theme ini (ts)", + "theme ini (ra2)", + "tmp", + "tmp (ra)", + "tmp (ts)", + "voc", + "vpl", + "vqa", + "vqp", + "vxl", + "w3d", + "wav", + "pcm wav", + "ima adpcm wav", + "wsa (dune2)", + "wsa", + "xcc lmd", + "xcc unknown", + "xif", + "zip", + "unknown" +}; + +Ccc_file::Ccc_file(bool read_on_open) : + m_read_on_open(read_on_open) +{ +} + +#define test_fail(res) { int v = res; if (v) { close(); return v; }} + +#ifndef NO_MIX_SUPPORT + int Ccc_file::open(unsigned int id, Cmix_file& mix_f) + { + if (mix_f.get_index(id) == -1) + return -1; + m_f = mix_f.m_f; + m_offset = mix_f.m_offset + mix_f.get_offset(id); + m_size = mix_f.get_size(id); + m_p = 0; + m_is_open = true; + if (m_read_on_open || mix_f.data()) + m_data = mix_f.get_vdata(id); + test_fail(post_open()) + return 0; + } + + int Ccc_file::open(const string& name, Cmix_file& mix_f) + { + return open(Cmix_file::get_id(mix_f.get_game(), name), mix_f); + } +#endif + + int Ccc_file::open(const string& name) + { + close(); + assert(!is_open()); +#ifdef NO_MIX_SUPPORT + test_fail(m_f.open_read(name)); +#else + test_fail(m_f.open_read(xcc_dirs::find_file(name))); +#endif + m_offset = 0; + m_size = m_f.size(); + m_p = 0; + m_is_open = true; + m_data = m_f.get_mm(); + if (m_read_on_open) + m_f.close(); +#ifndef NO_FT_SUPPORT + Cfname fname = to_lower_copy(name); + if (fname.get_fext() == ".mmx") + { + fname.set_ext(".map"); + mix_database::add_name(game_ra2, fname.get_fname(), "-"); + fname.set_ext(".pkt"); + mix_database::add_name(game_ra2, fname.get_fname(), "-"); + } +#endif + test_fail(post_open()) + return 0; + } + + const Cwin_handle& Ccc_file::h() + { + assert(is_open()); + return m_f.h(); + } + + int Ccc_file::open(const Cwin_handle& h) + { + assert(!is_open()); + m_f.open(h); + m_offset = 0; + m_size = m_f.size(); + m_p = 0; + m_is_open = true; + m_data = m_f.get_mm(); + if (m_read_on_open) + m_f.close(); + test_fail(post_open()) + return 0; + } + + void Ccc_file::load(const Cvirtual_binary& d, int size) + { + m_data = d; + m_offset = 0; + m_is_open = true; + m_p = 0; + m_size = size == -1 ? d.size() : size; + post_open(); + } + + void Ccc_file::load(const Ccc_file& f) + { + load(f.vdata()); + } + + int Ccc_file::read() + { + seek(0); + Cvirtual_binary d; + if (int error = read(d.write_start(get_size()), get_size())) + return error; + m_data = d; + return 0; + } + + int Ccc_file::read(void* data, int size) + { + if (get_p() < 0 || get_p() + size > get_size()) + return 1; + if (get_data()) + { + memcpy(data, m_data.data() + m_p, size); + skip(size); + return 0; + } + assert(is_open()); + m_f.seek(m_offset + m_p); + int res = m_f.read(data, size); + if (!res) + skip(size); + return res; + } + + int Ccc_file::extract(const string& name) + { + assert(is_open()); + if (data()) + return vdata().save(name); + seek(0); + Cfile32 f; + if (int error = f.open_write(name)) + return error; + Cvirtual_binary data; + for (int size = get_size(); size; ) + { + int cb_write = min(size, 1 << 20); + if (int error = read(data.write_start(cb_write), cb_write)) + return error; + if (int error = f.write(data.data(), cb_write)) + return error; + size -= cb_write; + } + return 0; + } + + void Ccc_file::close() + { + m_data.clear(); + m_f.close(); + m_is_open = false; + } + + +#ifndef NO_MIX_SUPPORT +#ifndef NO_FT_SUPPORT + t_file_type Ccc_file::get_file_type(bool fast) + { + Cvirtual_binary data; + int size; + if (m_data.data()) + { + data = m_data; + size = m_size; + } + else + { + size = min(m_size, 64 << 10); + seek(0); + if (read(data.write_start(size), size)) + return ft_unknown; + seek(0); + } + Caud_file aud_f; + Cbin_file bin_f; + Cbink_file bink_f; + Cbig_file big_f; + Cbmp_file bmp_f; + Ccsf_file csf_f; + Ccps_file cps_f; + Cdds_file dds_f; + Cfnt_file fnt_f; + Chva_file hva_f; + Cmix_file mix_f; + Cmix_rg_file mix_rg_f; + Cmp3_file mp3_f; + Cjpeg_file jpeg_f; + Cogg_file ogg_f; + Cpak_file pak_f; + Cpal_file pal_f; + Cpcx_file pcx_f; + Cpng_file png_f; + Criff_file riff_f; + Cshp_dune2_file shp_dune2_f; + Cshp_file shp_f; + Cshp_ts_file shp_ts_f; + Cst_file st_f; + Ctext_file text_f; + Ctga_file tga_f; + Ctmp_file tmp_f; + Ctmp_ra_file tmp_ra_f; + Ctmp_ts_file tmp_ts_f; + Cvoc_file voc_f; + Cvqa_file vqa_f; + Cvqp_file vqp_f; + Cvxl_file vxl_f; + Cw3d_file w3d_f; + Cwsa_dune2_file wsa_dune2_f; + Cwsa_file wsa_f; + Cxcc_file xcc_f; + Cxif_file xif_f; + if (aud_f.load(data, m_size), aud_f.is_valid()) + return ft_aud; + if (big_f.load(data, m_size), big_f.is_valid()) + return ft_big; + if (bin_f.load(data, m_size), bin_f.is_valid()) + return ft_bin; + if (bink_f.load(data, m_size), bink_f.is_valid()) + return ft_bink; + if (bmp_f.load(data, m_size), bmp_f.is_valid()) + return ft_bmp; + if (csf_f.load(data, m_size), csf_f.is_valid()) + return ft_csf; + if (cps_f.load(data, m_size), cps_f.is_valid()) + return ft_cps; + if (dds_f.load(data, m_size), dds_f.is_valid()) + return ft_dds; + if (fnt_f.load(data, m_size), fnt_f.is_valid()) + return ft_fnt; + if (hva_f.load(data, m_size), hva_f.is_valid()) + return ft_hva; + if (mp3_f.load(data, m_size), mp3_f.is_valid()) + return ft_mp3; + if (jpeg_f.load(data, m_size), jpeg_f.is_valid()) + return ft_jpeg; + if (ogg_f.load(data, m_size), ogg_f.is_valid()) + return ft_ogg; + if (pal_f.load(data, m_size), pal_f.is_valid()) + return ft_pal; + if (pcx_f.load(data, m_size), pcx_f.is_valid()) + return ft_pcx; + if (png_f.load(data, m_size), png_f.is_valid()) + return ft_png; + if (riff_f.load(data, m_size), riff_f.is_valid()) + { + Cavi_file avi_f; + Cwav_file wav_f; + avi_f.load(data, m_size); + wav_f.load(data, m_size); + if (avi_f.is_valid()) + return ft_avi; + if (wav_f.is_valid()) + return ft_wav; + return ft_riff; + } + if (shp_dune2_f.load(data, m_size), shp_dune2_f.is_valid()) + return ft_shp_dune2; + if (shp_f.load(data, m_size), shp_f.is_valid()) + return ft_shp; + if (shp_ts_f.load(data, m_size), shp_ts_f.is_valid()) + return ft_shp_ts; + if (st_f.load(data, m_size), st_f.is_valid()) + return ft_st; + if (tga_f.load(data, m_size), tga_f.is_valid()) + return ft_tga; + if (tmp_f.load(data, m_size), tmp_f.is_valid()) + return ft_tmp; + if (tmp_ra_f.load(data, m_size), tmp_ra_f.is_valid()) + return ft_tmp_ra; + if (tmp_ts_f.load(data, m_size), tmp_ts_f.is_valid()) + return ft_tmp_ts; + if (voc_f.load(data, m_size), voc_f.is_valid()) + return ft_voc; + if (vqa_f.load(data, m_size), vqa_f.is_valid()) + return ft_vqa; + if (vqp_f.load(data, m_size), vqp_f.is_valid()) + return ft_vqp; + if (vxl_f.load(data, m_size), vxl_f.is_valid()) + return ft_vxl; + if (wsa_dune2_f.load(data, m_size), wsa_dune2_f.is_valid()) + return ft_wsa_dune2; + if (wsa_f.load(data, m_size), wsa_f.is_valid()) + return ft_wsa; + if (xcc_f.load(data, m_size), xcc_f.is_valid()) + { + switch (xcc_f.get_ft()) + { + case xcc_ft_lmd: + return ft_xcc_lmd; + } + return ft_xcc_unknown; + } + if (xif_f.load(data, m_size), xif_f.is_valid()) + return ft_xif; + if (mix_f.load(data, m_size), mix_f.is_valid()) + return ft_mix; + if (mix_rg_f.load(data, m_size), mix_rg_f.is_valid()) + return ft_mix_rg; + if (pak_f.load(data, m_size), pak_f.is_valid()) + return ft_pak; + if (w3d_f.load(data, m_size), w3d_f.is_valid()) + return ft_w3d; + if (text_f.load(data, m_size), text_f.is_valid()) + { + if (fast) + return ft_text; + Cvirtual_tfile tf; + tf.load_data(data); + Cnull_ini_reader ir; + int error = 0; + while (!error && !tf.eof()) + { + error = ir.process_line(tf.read_line()); + if (tf.eof()) + error = 0; + } + if (!error && ir.is_valid()) + { + if (!m_read_on_open && m_size != size) + { + size = m_size; + if (read(data.write_start(size), size)) + return ft_unknown; + seek(0); + } + { + Cmap_td_ini_reader ir; + if (!ir.process(data) && ir.is_valid()) + return ft_map_td; + } + { + Cmap_ra_ini_reader ir; + if (!ir.process(data) && ir.is_valid()) + return ft_map_ra; + } + { + Cmap_ts_ini_reader ir; + ir.fast(true); + if (!ir.process(data) && ir.is_valid()) + return ft_map_ts; + } + { + Cpkt_ts_ini_reader ir; + ir.fast(true); + if (!ir.process(data) && ir.is_valid()) + return ft_pkt_ts; + } + { + Csound_ts_ini_reader ir; + ir.fast(true); + if (!ir.process(data) && ir.is_valid()) + return ft_sound_ini_ts; + } + { + Ctheme_ts_ini_reader ir; + if (!ir.process(data) && ir.is_valid()) + return ft_theme_ini_ts; + } + return ft_ini; + } + return ft_text; + } + return ft_unknown; + } +#endif +#endif diff --git a/3rdParty/xcc/misc/cc_file.h b/3rdParty/xcc/misc/cc_file.h new file mode 100644 index 0000000..264e954 --- /dev/null +++ b/3rdParty/xcc/misc/cc_file.h @@ -0,0 +1,195 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "file32.h" +#include + +enum t_file_type +{ + ft_aud, + ft_avi, + ft_big, + ft_bin, + ft_bink, + ft_bmp, + ft_clipboard, + ft_csf, + ft_cps, + ft_csv, + ft_dds, + ft_dir, + ft_drive, + ft_fnt, + ft_html, + ft_hva, + ft_ini, + ft_jpeg, + ft_jpeg_single, + ft_map_dune2, + ft_map_td, + ft_map_ra, + ft_map_ts, + ft_map_ts_preview, + ft_map_ra2, + ft_mix, + ft_mix_rg, + ft_mng, + ft_mp3, + ft_mrf, + ft_ogg, + ft_pak, + ft_pal, + ft_pal_jasc, + ft_pcx_single, + ft_pcx, + ft_png_single, + ft_png, + ft_pkt_ts, + ft_riff, + ft_rules_ini_ts, + ft_rules_ini_ra2, + ft_shp_dune2, + ft_shp, + ft_shp_ts, + ft_sound_ini_ts, + ft_sound_ini_ra2, + ft_st, + ft_text, + ft_tga, + ft_tga_single, + ft_theme_ini_ts, + ft_theme_ini_ra2, + ft_tmp, + ft_tmp_ra, + ft_tmp_ts, + ft_voc, + ft_vpl, + ft_vqa, + ft_vqp, + ft_vxl, + ft_w3d, + ft_wav, + ft_wav_ima_adpcm, + ft_wav_pcm, + ft_wsa_dune2, + ft_wsa, + ft_xcc_lmd, + ft_xcc_unknown, + ft_xif, + ft_zip, + ft_unknown, + ft_count +}; + +const char* ft_name[]; + +class Cmix_file; + +class Ccc_file +{ +public: + const Cwin_handle& h(); + int open(const Cwin_handle& h); + int open(unsigned int id, Cmix_file& mix_f); + int open(const string& name, Cmix_file& mix_f); + int open(const string& name); + void load(const Cvirtual_binary& d, int size = -1); + void load(const Ccc_file& f); + t_file_type get_file_type(bool fast = true); + int read(); + int read(void* data, int size); + int extract(const string& name); + virtual void close(); + Ccc_file(bool read_on_open); + + const byte* begin() const + { + return m_data.begin(); + } + + const byte* end() const + { + return m_data.end(); + } + + const byte* data() const + { + return m_data.data(); + } + + long long size() const + { + return m_size; + } + + const byte* get_data() const + { + return m_data.data(); + } + + const byte* data_end() const + { + return m_data.data_end(); + } + + Cvirtual_binary vdata() const + { + return m_data; + } + + int get_p() const + { + return m_p; + } + + long long get_size() const + { + return m_size; + } + + bool is_open() const + { + return m_is_open; + } + + void seek(int p) + { + m_p = p; + } + + void skip(int p) + { + m_p += p; + } + + virtual int post_open() + { + return 0; + } +protected: + int m_offset; +private: + Cvirtual_binary m_data; + Cfile32 m_f; + bool m_is_open = false; + int m_p; + const bool m_read_on_open; + long long m_size; +}; diff --git a/3rdParty/xcc/misc/cc_file_sh.h b/3rdParty/xcc/misc/cc_file_sh.h new file mode 100644 index 0000000..a304dcf --- /dev/null +++ b/3rdParty/xcc/misc/cc_file_sh.h @@ -0,0 +1,31 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include + +template +class Ccc_file_sh : public Ccc_file_small +{ +public: + const T& header() const + { + return *reinterpret_cast(data()); + } +}; diff --git a/3rdParty/xcc/misc/cc_file_small.h b/3rdParty/xcc/misc/cc_file_small.h new file mode 100644 index 0000000..3428d7f --- /dev/null +++ b/3rdParty/xcc/misc/cc_file_small.h @@ -0,0 +1,29 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include + +class Ccc_file_small : public Ccc_file +{ +public: + Ccc_file_small() : Ccc_file(true) + { + } +}; diff --git a/3rdParty/xcc/misc/cc_structures.cpp b/3rdParty/xcc/misc/cc_structures.cpp new file mode 100644 index 0000000..43fb582 --- /dev/null +++ b/3rdParty/xcc/misc/cc_structures.cpp @@ -0,0 +1,40 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "cc_structures.h" + +const char* game_name[] = +{ + "Tiberian Dawn", + "Red Alert", + "Tiberian Sun", + "Dune 2", + "Dune 2000", + "Red Alert 2", + "Red Alert 2 Yuri's Revenge", + "Renegade", + "Generals", + "Generals Zero Hour", + "Emperor Battle for Dune", + "Nox", + "Battle for Middle Earth", + "Battle for Middle Earth 2", + "Tiberium Wars", + "Tiberian Sun Firestorm", +}; diff --git a/3rdParty/xcc/misc/cc_structures.h b/3rdParty/xcc/misc/cc_structures.h new file mode 100644 index 0000000..2e93ff5 --- /dev/null +++ b/3rdParty/xcc/misc/cc_structures.h @@ -0,0 +1,566 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "palet.h" + +enum t_game +{ + game_td, + game_ra, + game_ts, + game_dune2, + game_dune2000, + game_ra2, + game_ra2_yr, + game_rg, + game_gr, + game_gr_zh, + game_ebfd, + game_nox, + game_bfme, + game_bfme2, + game_tw, + game_ts_fs, + game_unknown +}; + +const char* game_name[]; + +inline __int32 reverse(__int32 v) +{ + _asm + { + mov eax, v + xchg al, ah + rol eax, 16 + xchg al, ah + mov v, eax + } + return v; +} + +#pragma pack(push, 1) + +struct t_aud_header +{ + unsigned __int16 samplerate; + unsigned __int32 size_in; + unsigned __int32 size_out; + __int8 flags; + __int8 compression; +}; + +struct t_aud_chunk_header +{ + unsigned __int16 size_in; + unsigned __int16 size_out; + __int32 id; +}; + +const __int32 aud_chunk_id = 0x0000deaf; + +struct t_audio_idx_header +{ + __int32 id; + __int32 two; + __int32 c_sounds; +}; + +struct t_audio_idx_entry +{ + char fname[16]; + __int32 offset; + __int32 size; + __int32 samplerate; + __int32 flags; + __int32 chunk_size; +}; + +const __int32 audio_idx_id = *(__int32*)"GABA"; + +struct t_big_header +{ + __int32 id; + __int32 size; + __int32 mc_files; + __int32 mcb_header; + + int c_files() const + { + return reverse(mc_files); + } + + int cb_header() const + { + return reverse(mcb_header); + } +}; + +struct t_big_index_entry +{ + __int32 offset; + __int32 size; +}; + +const int big_id = 'FGIB'; +const int big4_id = '4GIB'; + +struct t_cps_header +{ + unsigned __int16 size; + __int16 unknown; + unsigned __int16 image_size; + __int16 zero; + __int16 palet_size; +}; + +struct t_csf_header +{ + __int32 id; + __int32 flags1; + __int32 count1; + __int32 count2; + __int32 zero; + __int32 flags2; +}; + +const __int32 csf_file_id = 'CSF '; +const __int32 csf_label_id = 'LBL '; +const __int32 csf_string_id = 'STR '; +const __int32 csf_string_w_id = 'STRW'; + +struct t_fnt_header +{ + unsigned __int16 size; + __int16 id1; + __int16 id2; + __int16 id3; + unsigned __int16 cx_ofs; + unsigned __int16 image_ofs; + unsigned __int16 cy_ofs; + __int16 id4; + __int8 zero; + unsigned __int8 c_chars; + __int8 cy; + __int8 cmax_x; +}; + +struct t_hva_header +{ + char id[16]; + __int32 c_frames; + __int32 c_sections; +}; + +using t_hva_transform_matrix = float[3][4]; + +struct t_jpeg_header +{ + __int8 unknown[6]; + __int8 id[4]; +}; + +const char jpeg_id[] = "JFIF"; + +union t_mix_header +{ + struct + { + __int16 c_files; + __int32 size; + }; + __int32 flags; +}; + +const int mix_checksum = 0x00010000; +const int mix_encrypted = 0x00020000; +const int cb_mix_key = 56; +const int cb_mix_key_source = 80; +const int cb_mix_checksum = 20; + +struct t_mix_index_entry +{ + t_mix_index_entry() = default; + + t_mix_index_entry(unsigned int id_, int offset_, int size_) + { + id = id_; + offset = offset_; + size = size_; + } + + unsigned __int32 id; + __int32 offset; + __int32 size; +}; + +struct t_mix_rg_header +{ + __int32 id; + __int32 index_offset; + __int32 tailer_offset; + __int32 zero; +}; + +struct t_mix_rg_index_entry +{ + __int32 id; + __int32 offset; + __int32 size; +}; + +const int mix_rg_id = '1XIM'; + +struct t_iso_map_pack_entry +{ + unsigned __int16 x; + unsigned __int16 y; + __int16 tile; + unsigned __int8 zero1; + unsigned __int8 zero2; + unsigned __int8 sub_tile; + unsigned __int8 z; + unsigned __int8 zero3; +}; + +struct t_ogg_header +{ + __int8 id[4]; +}; + +const char ogg_id[] = "OggS"; + +struct t_pack_section_header +{ + unsigned __int16 size_in; + unsigned __int16 size_out; +}; + +struct t_pcx_header +{ + __int8 manufacturer; + __int8 version; + __int8 encoding; + __int8 cbits_pixel; + __int16 xmin; + __int16 ymin; + __int16 xmax; + __int16 ymax; + __int16 cx_inch; + __int16 cy_inch; + __int8 colorpap[16][3]; + __int8 reserved; + __int8 c_planes; + __int16 cb_line; + __int8 filler[60]; +}; + +struct t_png_header +{ + __int8 id[8]; +}; + +const char png_id[] = "\x89PNG\r\n\x1A\n"; + +struct t_shp_dune2_header +{ + __int16 c_images; +}; + +struct t_shp_dune2_image_header +{ + __int16 compression; + unsigned __int8 cy; + unsigned __int16 cx; + unsigned __int8 cy2; + unsigned __int16 size_in; + unsigned __int16 size_out; +}; + +struct t_shp_header +{ + __int16 c_images; + __int16 unknown1; + __int16 unknown2; + __int16 cx; + __int16 cy; + __int32 unknown3; +}; + +struct t_shp_ts_header +{ + __int16 zero; + __int16 cx; + __int16 cy; + __int16 c_images; +}; + +struct t_shp_ts_image_header +{ + __int16 x; + __int16 y; + __int16 cx; + __int16 cy; + __int32 compression; + __int32 unknown; + __int32 zero; + __int32 offset; +}; + +struct t_tga_header +{ + byte id_size; + byte map_t; + byte image_t; + unsigned __int16 map_first; + unsigned __int16 map_size; + byte map_entry_size; + unsigned __int16 x; + unsigned __int16 y; + unsigned __int16 cx; + unsigned __int16 cy; + byte cb_pixel; + byte alpha:4; + byte horizontal:1; + byte vertical:1; +}; + +struct t_tmp_header +{ + __int16 cx; + __int16 cy; + __int16 c_tiles; + __int16 zero1; + __int32 size; + __int32 image_offset; + __int32 zero2; + __int32 id; + __int32 index2; + __int32 index1; +}; + +struct t_tmp_ra_header +{ + __int16 cx; + __int16 cy; + __int16 c_tiles; + __int16 zero1; + __int16 cblocks_x; + __int16 cblocks_y; + __int32 size; + __int32 image_offset; + __int32 zero2; + __int32 unknown1; + __int32 index2; + __int32 unknown2; + __int32 index1; +}; + +struct t_tmp_ts_header +{ + __int32 cblocks_x; + __int32 cblocks_y; + __int32 cx; + __int32 cy; +}; + +struct t_tmp_image_header +{ + __int32 x; + __int32 y; + __int32 extra_ofs; + __int32 z_ofs; + __int32 extra_z_ofs; + __int32 x_extra; + __int32 y_extra; + __int32 cx_extra; + __int32 cy_extra; + unsigned int has_extra_data: 1; + unsigned int has_z_data: 1; + unsigned int has_damaged_data: 1; + __int8 height; + __int8 terrain_type; + __int8 ramp_type; + unsigned __int8 radar_red_left; + unsigned __int8 radar_green_left; + unsigned __int8 radar_blue_left; + unsigned __int8 radar_red_right; + unsigned __int8 radar_green_right; + unsigned __int8 radar_blue_right; + __int8 pad[3]; +}; + +struct t_voc_header +{ + char id[20]; + __int16 offset; + __int32 version; +}; + +struct t_voc_sound_data_header +{ + unsigned __int8 samplerate; + __int8 compression; +}; + +const char voc_id[] = "Creative Voice File\x1a"; + +struct t_vqa_chunk_header +{ + __int32 id; + __int32 size; +}; + +struct t_vqa_header +{ + t_vqa_chunk_header file_header; + // 'FORM' + __int64 id; + // 'WVQAVQHD' + __int32 startpos; + __int16 version; + __int16 video_flags; + __int16 c_frames; + __int16 cx; + __int16 cy; + __int8 cx_block; + __int8 cy_block; + __int16 unknown3; + __int16 c_colors; + __int16 cb_max_cbp_chunk; + __int32 unknown4; + __int16 unknown5; + unsigned __int16 samplerate; + __int8 c_channels; + __int8 cbits_sample; + __int8 unknown6[14]; +}; + +const __int32 vqa_c_mask = 0xff000000; +const __int32 vqa_t_mask = 0x00ffffff; +const __int32 vqa_file_id = *(__int32*)"FORM"; +const __int64 vqa_form_id = {*(__int64*)"WVQAVQHD"}; +const __int32 vqa_cbf_id = *(__int32*)"CBF\0"; +const __int32 vqa_cbp_id = *(__int32*)"CBP\0"; +const __int32 vqa_cpl_id = *(__int32*)"CPL\0"; +const __int32 vqa_finf_id = *(__int32*)"FINF"; +const __int32 vqa_sn2j_id = *(__int32*)"SN2J"; +const __int32 vqa_snd_id = *(__int32*)"SND\0"; +const __int32 vqa_vpt_id = *(__int32*)"VPT\0"; +const __int32 vqa_vpr_id = *(__int32*)"VPR\0"; +const __int32 vqa_vqfl_id = *(__int32*)"VQFL"; +const __int32 vqa_vqfr_id = *(__int32*)"VQFR"; + +struct t_vqp_header +{ + unsigned __int32 c_tables; +}; + +struct t_vxl_header +{ + char id[16]; + __int32 one; + unsigned __int32 c_section_headers; + unsigned __int32 c_section_tailers; + unsigned __int32 size; + __int16 unknown; + t_palet palet; +}; + +struct t_vxl_section_header +{ + char id[16]; + __int32 section_i; + __int32 one; + __int32 zero; +}; + +struct t_vxl_section_tailer +{ + __int32 span_start_ofs; + __int32 span_end_ofs; + __int32 span_data_ofs; + float scale; + float transform[3][4]; + float x_min_scale; + float y_min_scale; + float z_min_scale; + float x_max_scale; + float y_max_scale; + float z_max_scale; + unsigned __int8 cx; + unsigned __int8 cy; + unsigned __int8 cz; + __int8 unknown; +}; + +const char vxl_id[] = "Voxel Animation"; + +struct t_w3d_header +{ + __int32 id; + __int32 m_size; + + bool container() const + { + return m_size & 0x80000000; + } + + int size() const + { + return m_size & ~0x80000000; + } +}; + +struct t_wsa_dune2_header +{ + __int16 c_frames; + __int16 cx; + __int16 cy; + __int16 delta; +}; + +struct t_wsa_header +{ + __int16 c_frames; + __int16 x; + __int16 y; + __int16 cx; + __int16 cy; + __int32 delta; +}; + +struct t_xcc_header +{ + char id[32]; + __int32 size; + __int32 type; + __int32 version; +}; + +const char xcc_id[] = "XCC by Olaf van der Spek\x1a\x04\x17\x27\x10\x19\x80"; + +struct t_xcc_lmd_header +{ + __int32 game; + __int32 c_fnames; +}; + +#pragma pack(pop) diff --git a/3rdParty/xcc/misc/crc.h b/3rdParty/xcc/misc/crc.h new file mode 100644 index 0000000..9a68d52 --- /dev/null +++ b/3rdParty/xcc/misc/crc.h @@ -0,0 +1,28 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include + +inline int compute_crc(const void* d, int cb_d) +{ + boost::crc_32_type crc; + crc.process_bytes(d, cb_d); + return crc(); +} diff --git a/3rdParty/xcc/misc/ddpf_conversion.cpp b/3rdParty/xcc/misc/ddpf_conversion.cpp new file mode 100644 index 0000000..6581bdc --- /dev/null +++ b/3rdParty/xcc/misc/ddpf_conversion.cpp @@ -0,0 +1,72 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "ddpf_conversion.h" + +static int get_shift(unsigned int v) +{ + if (!v) + return 0; + int r = 0; + while (~v & 1) + { + r++; + v >>= 1; + } + return r; +} + +static int get_size(unsigned int v) +{ + int r = 0; + while (v) + { + if (v & 1) + r++; + v >>= 1; + } + return r; +} + +void Cddpf_conversion::set_pf(const DDPIXELFORMAT& pf) +{ + a_shift = get_shift(pf.dwRGBAlphaBitMask); + r_shift = get_shift(pf.dwRBitMask); + g_shift = get_shift(pf.dwGBitMask); + b_shift = get_shift(pf.dwBBitMask); + a_size = get_size(pf.dwRGBAlphaBitMask); + r_size = get_size(pf.dwRBitMask); + g_size = get_size(pf.dwGBitMask); + b_size = get_size(pf.dwBBitMask); +} + +int Cddpf_conversion::get_color(int a, int r, int g, int b) +{ + return a >> (8 - a_size) << a_shift | r >> (8 - r_size) << r_shift | g >> (8 - g_size) << g_shift | b >> (8 - b_size) << b_shift; +} + +int Cddpf_conversion::get_color(int r, int g, int b) +{ + return get_color(0, r, g, b); +} + +int Cddpf_conversion::get_color(int v) +{ + return get_color(v >> 24, v >> 16 & 0xff, v >> 8 & 0xff, v & 0xff); +} diff --git a/3rdParty/xcc/misc/ddpf_conversion.h b/3rdParty/xcc/misc/ddpf_conversion.h new file mode 100644 index 0000000..3aab406 --- /dev/null +++ b/3rdParty/xcc/misc/ddpf_conversion.h @@ -0,0 +1,33 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include + +class Cddpf_conversion +{ +public: + int get_color(int a, int r, int g, int b); + int get_color(int r, int g, int b); + int get_color(int v); + void set_pf(const DDPIXELFORMAT& pf); +private: + int a_shift, r_shift, g_shift, b_shift; + int a_size, r_size, g_size, b_size; +}; \ No newline at end of file diff --git a/3rdParty/xcc/misc/file32.cpp b/3rdParty/xcc/misc/file32.cpp new file mode 100644 index 0000000..e895bfe --- /dev/null +++ b/3rdParty/xcc/misc/file32.cpp @@ -0,0 +1,153 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "file32.h" + +int Cfile32::open(const Cwin_handle& h) +{ + m_h = h; + m_p = 0; + return !is_open(); +} + +int Cfile32::open(const string& name, int access) +{ + return access & GENERIC_WRITE ? open(name, access, CREATE_ALWAYS, 0) : open(name, access, OPEN_EXISTING, FILE_SHARE_READ); +} + +int Cfile32::open(const string& name, int access, int creation, int share) +{ + m_h = Cwin_handle(CreateFileA(name.c_str(), access, share, NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL)); + m_p = 0; + return !is_open(); +} + +FILETIME Cfile32::get_creation_time() const +{ + assert(is_open()); + FILETIME time; + int r = GetFileTime(h(), &time, NULL, NULL); + assert(r); + return time; +} + +FILETIME Cfile32::get_last_access_time() const +{ + assert(is_open()); + FILETIME time; + int r = GetFileTime(h(), NULL, &time, NULL); + assert(r); + return time; +} + +FILETIME Cfile32::get_last_write_time() const +{ + assert(is_open()); + FILETIME time; + int r = GetFileTime(h(), NULL, NULL, &time); + assert(r); + return time; +} + +int Cfile32::open_read(const string& name) +{ + return open(name, GENERIC_READ, OPEN_EXISTING, FILE_SHARE_READ); +} + +int Cfile32::open_edit(const string& name) +{ + return open(name, GENERIC_READ | GENERIC_WRITE, OPEN_ALWAYS, 0); +} + +int Cfile32::open_write(const string& name) +{ + return open(name, GENERIC_WRITE, CREATE_ALWAYS, 0); +} + +long long Cfile32::size() const +{ + assert(is_open()); + LARGE_INTEGER v; + return GetFileSizeEx(h(), &v) ? v.QuadPart : -1; +} + +int Cfile32::read(void* data, int size) +{ + assert(is_open()); + if (SetFilePointer(h(), m_p, 0, FILE_BEGIN) == -1) + return 1; + DWORD cb_read; + if (!ReadFile(h(), data, size, &cb_read, 0) || cb_read != size) + return 1; + m_p += size; + return 0; +} + +int Cfile32::write(const void* data, int size) +{ + assert(is_open()); + if (SetFilePointer(h(), m_p, 0, FILE_BEGIN) == -1) + return 1; + DWORD cb_write; + if (!WriteFile(h(), data, size, &cb_write, 0) || cb_write != size) + return 1; + m_p += size; + return 0; +} + +int Cfile32::write(data_ref v) +{ + return write(v.data(), v.size()); +}; + +int Cfile32::set_eof() +{ + assert(is_open()); + if (SetFilePointer(h(), m_p, 0, FILE_BEGIN) == -1) + return 1; + return !SetEndOfFile(h()); +} + +void Cfile32::close() +{ + m_h.clear(); +} + +Cvirtual_binary Cfile32::get_mm() +{ + if (!size()) + return Cvirtual_binary(); + Cwin_handle mh(CreateFileMapping(h(), NULL, PAGE_READONLY, 0, 0, NULL)); + void* d = mh ? MapViewOfFile(mh, FILE_MAP_READ, 0, 0, 0) : NULL; + return d ? Cvirtual_binary(d, size(), std::shared_ptr(d, UnmapViewOfFile)) : Cvirtual_binary(); +} + +Cvirtual_binary file32_read(const string& name) +{ + Cfile32 f; + return f.open_read(name) ? Cvirtual_binary() : f.get_mm(); +} + +int file32_write(const string& name, const void* s, int cb_s) +{ + Cfile32 f; + if (int error = f.open_write(name)) + return error; + return f.write(s, cb_s); +} diff --git a/3rdParty/xcc/misc/file32.h b/3rdParty/xcc/misc/file32.h new file mode 100644 index 0000000..7e2cbfc --- /dev/null +++ b/3rdParty/xcc/misc/file32.h @@ -0,0 +1,83 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include +#include +#include +#include "win_handle.h" + +using namespace std; + +class Cfile32 +{ +public: + Cvirtual_binary get_mm(); + int open(const Cwin_handle& h); + int open(const string& name, int access); + int open(const string& name, int access, int creation, int share); + int open_read(const string& name); + int open_edit(const string& name); + int open_write(const string& name); + long long size() const; + FILETIME get_creation_time() const; + FILETIME get_last_access_time() const; + FILETIME get_last_write_time() const; + int read(void* data, int size); + int write(const void* data, int size); + int write(data_ref); + int set_eof(); + void close(); + + bool eof() const + { + return m_p >= size(); + } + + const Cwin_handle& h() const + { + return m_h; + } + + bool is_open() const + { + return h(); + } + + int get_p() const + { + return m_p; + } + + void seek(int p) + { + m_p = p; + } + + void skip(int p) + { + m_p += p; + } +private: + Cwin_handle m_h; + int m_p; +}; + +Cvirtual_binary file32_read(const string& name); +int file32_write(const string& name, const void* s, int cb_s); diff --git a/3rdParty/xcc/misc/fname.cpp b/3rdParty/xcc/misc/fname.cpp new file mode 100644 index 0000000..04654b5 --- /dev/null +++ b/3rdParty/xcc/misc/fname.cpp @@ -0,0 +1,217 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "fname.h" + +Cfname::Cfname(const string& s) +{ + *this = string_view(s); +} + +string Cfname::get_fname() const +{ + return title + ext; +} + +string Cfname::get_ftitle() const +{ + return title; +} + +string Cfname::get_fext() const +{ + return ext; +} + +string Cfname::get_path() const +{ + return path; +} + +string Cfname::get_all() const +{ + return path + title + ext; +} + +/* +void Cfname::expand() +{ + char t[MAX_PATH]; + _fullpath(t, get_all().c_str(), MAX_PATH); + Cfname((t)); +} +*/ + +Cfname GetModuleFileName(HMODULE hModule) +{ + char s[MAX_PATH]; + if (GetModuleFileNameA(hModule, s, MAX_PATH)) + return Cfname(s); + return {}; +} + +string get_temp_path() +{ + char temp_dir[MAX_PATH]; + return GetTempPathA(MAX_PATH, temp_dir) ? temp_dir : ".\\"; +} + +string get_temp_fname(string path) +{ + char temp_fname[MAX_PATH]; + return GetTempFileNameA(path.c_str(), "XCC", 0, temp_fname) ? temp_fname : ""; +} + +string get_temp_fname() +{ + return get_temp_fname(get_temp_path()); +} + +void Cfname::set_title(string_view s) +{ + title = s; +} + +void Cfname::set_ext(string_view s) +{ + ext = s; +} + +void Cfname::use_default_ext(string_view s) +{ + if (ext == "") + ext = s; +} + +void Cfname::set_path(string_view s) +{ + path = s; + if (!path.empty() && path[path.length() - 1] != '\\') + path += '\\'; +} + +void Cfname::use_default_path(string_view s) +{ + if (path.empty()) + set_path(s); +} + +void Cfname::make_path() +{ + if ((title + ext).empty()) + return; + path += title + ext + '\\'; + title = ext = ""; +} + +bool Cfname::exists() const +{ + HANDLE h; + WIN32_FIND_DATAA d; + h = FindFirstFileA(get_all().c_str(), &d); + if (h == INVALID_HANDLE_VALUE) + return false; + FindClose(h); + return true; +} + +const Cfname& Cfname::operator=(string_view s) +{ + long p1 = s.rfind('\\'); + long p2 = s.rfind('.'); + char t[MAX_PATH]; + if (p1 != string::npos) + { + //copy last \ also + t[s.copy(t, p1 + 1)] = 0; + path = t; + } + t[s.copy(t, p2 - p1 - 1, p1 + 1)] = 0; + title = t; + if (p2 != s.npos && p1 < p2) + { + t[s.copy(t, s.npos, p2)] = 0; + ext = t; + } + return *this; +} + +string operator+(const string& a, const Cfname& b) +{ + return a + static_cast(b); +} + +int create_dir(const string& dir) +{ + return !CreateDirectoryA(dir.c_str(), NULL); +} + +void create_deep_dir(string dir, const string& name) +{ + int a = 0; + int b; + while ((b = name.find_first_of("/\\", a)) != string::npos) + { + dir += '/' + name.substr(a, b - a); + create_dir(dir); + a = b + 1; + } +} + +int copy_file(string s, string d) +{ + return !CopyFileA(s.c_str(), d.c_str(), false); +} + +int delete_file(string fname) +{ + return !DeleteFileA(fname.c_str()); +} + +int move_file(string s, string d) +{ + return !MoveFileA(s.c_str(), d.c_str()); +} + +bool fname_filter(const string& fname, const string& filter) +{ + size_t i; + for (i = 0; i < filter.size(); i++) + { + char c = filter[i]; + if (c == '*') + { + if (filter.find('*', i + 1) == string::npos) + { + int j = fname.length() - filter.length() + 1; + return j < 0 ? false : fname_filter(fname.substr(i + j), filter.substr(i + 1)); + } + // for (int j = 0; j < min(fname.length(), filter.length()) - i; j++) + for (size_t j = 0; j < fname.size(); j++) + { + if (fname_filter(fname.substr(i + j), filter.substr(i + 1))) + return true; + } + return false; + } + if (c != '?' && c != fname[i]) + return false; + } + return fname.length() == i; +} diff --git a/3rdParty/xcc/misc/fname.h b/3rdParty/xcc/misc/fname.h new file mode 100644 index 0000000..ded5594 --- /dev/null +++ b/3rdParty/xcc/misc/fname.h @@ -0,0 +1,66 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include +#include + +using namespace std; + +class Cfname +{ +private: + string path; + string title; + string ext; +public: + const Cfname& operator=(string_view); + bool exists() const; + void make_path(); + void use_default_ext(string_view); + void use_default_path(string_view); + void set_ext(string_view); + void set_path(string_view); + void set_title(string_view); + void expand(); + string get_all() const; + string get_path() const; + string get_fname() const; + string get_ftitle() const; + string get_fext() const; + Cfname() = default; + Cfname(const string&); + + operator string() const + { + return get_all(); + } +}; + +Cfname GetModuleFileName(HMODULE hModule = 0); +bool fname_filter(const string& fname, const string& filter); +int create_dir(const string& dir); +void create_deep_dir(string dir, const string& name); +int delete_file(string fname); +int copy_file(string s, string d); +int move_file(string s, string d); +string get_temp_fname(string path); +string get_temp_path(); +string get_temp_fname(); +string operator+(const string& a, const Cfname& b); diff --git a/3rdParty/xcc/misc/hva_file.cpp b/3rdParty/xcc/misc/hva_file.cpp new file mode 100644 index 0000000..fc3b675 --- /dev/null +++ b/3rdParty/xcc/misc/hva_file.cpp @@ -0,0 +1,115 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "hva_file.h" + +#include +#include "multi_line.h" +#include "virtual_tfile.h" + +bool Chva_file::is_valid() const +{ + const t_hva_header& h = header(); + int size = get_size(); + return !(sizeof(t_hva_header) > size + || !h.c_frames + || !h.c_sections + || sizeof(t_hva_header) + (48 * h.c_frames + 16) * h.c_sections != size); +} + +int Chva_file::extract_as_csv(const string& name) const +{ + ofstream f(name.c_str()); + const int c_frames = get_c_frames(); + const int c_sections = get_c_sections(); + f << "Count frames;" << c_frames << endl + << "Count sections;" << c_sections << endl + << endl; + for (int i = 0; i < c_sections; i++) + f << get_section_id(i) << ";;;;;"; + for (int j = 0; j < c_frames; j++) + { + f << endl; + for (int y = 0; y < 3; y++) + { + for (int i = 0; i < c_sections; i++) + { + for (int x = 0; x < 4; x++) + { + f << get_transform_matrix(i, j)[x + 4 * y] << ';'; + } + f << ';'; + } + f << endl; + } + } + return f.fail(); +} + +Cvirtual_binary hva_file_write(const byte* s, int cb_s) +{ + Cvirtual_binary d; + const char sep = ';'; + Cvirtual_tfile f; + f.load_data(Cvirtual_binary(s, cb_s)); + Cmulti_line l; + l = f.read_line(); + l.get_next_line(sep); + int c_frames = atoi(l.get_next_line(sep).c_str()); + l = f.read_line(); + l.get_next_line(sep); + int c_sections = atoi(l.get_next_line(sep).c_str()); + f.read_line(); + byte* w = d.write_start(64 << 10); + t_hva_header& header = *reinterpret_cast(w); + strcpy(header.id, "NONE"); + header.c_frames = c_frames; + header.c_sections = c_sections; + w += sizeof(t_hva_header); + l = f.read_line(); + for (int i = 0; i < c_sections; i++) + { + strcpy(reinterpret_cast(w), l.get_next_line(sep).c_str()); + w += 16; + l.get_next_line(sep); + l.get_next_line(sep); + l.get_next_line(sep); + l.get_next_line(sep); + } + float* transform_matrix = reinterpret_cast(w); + for (int j = 0; j < c_frames; j++) + { + for (int y = 0; y < 3; y++) + { + l = f.read_line(); + for (int i = 0; i < c_sections; i++) + { + for (int x = 0; x < 4; x++) + { + transform_matrix[12 * (c_frames * i + j) + x + 4 * y] = atof(l.get_next_line(sep).c_str()); + } + l.get_next_line(sep); + } + } + f.read_line(); + } + w += 4 * 12 * c_frames * c_sections; + d.set_size(w - d.data()); + return d; +} diff --git a/3rdParty/xcc/misc/hva_file.h b/3rdParty/xcc/misc/hva_file.h new file mode 100644 index 0000000..63b789d --- /dev/null +++ b/3rdParty/xcc/misc/hva_file.h @@ -0,0 +1,51 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include +#include + +class Chva_file : public Ccc_file_sh +{ +public: + int extract_as_csv(const string& name) const; + bool is_valid() const; + + int get_c_frames() const + { + return header().c_frames; + } + + int get_c_sections() const + { + return header().c_sections; + } + + const char* get_section_id(int i) const + { + return reinterpret_cast(data() + sizeof(t_hva_header) + 16 * i); + } + + const float* get_transform_matrix(int i, int j) const + { + return reinterpret_cast(data() + sizeof(t_hva_header) + 16 * get_c_sections() + (get_c_frames() * i + j) * sizeof(t_hva_transform_matrix)); + } +}; + +Cvirtual_binary hva_file_write(const byte* s, int cb_s); diff --git a/3rdParty/xcc/misc/id_log.cpp b/3rdParty/xcc/misc/id_log.cpp new file mode 100644 index 0000000..ff55fcd --- /dev/null +++ b/3rdParty/xcc/misc/id_log.cpp @@ -0,0 +1,137 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include + +#include +#include +#include +#include + +struct t_idinfo +{ + string name; + string description; +}; + +using t_id_list = map; + +t_id_list td_list, ra_list, ts_list, dune2_list, ra2_list; + +static t_id_list& get_list(t_game game) +{ + switch (game) + { + case game_ra: + return ra_list; + case game_ts: + return ts_list; + case game_dune2: + return dune2_list; + case game_ra2: + return ra2_list; + } + return td_list; +} + +static void read_list(t_game game, const char*& s) +{ + t_id_list& d = get_list(game); + int count = *reinterpret_cast(s); + s += 4; + t_idinfo idinfo; + while (count--) + { + idinfo.name = s; + s += idinfo.name.length() + 1; + idinfo.description = s; + s += idinfo.description.length() + 1; + d[Cmix_file::get_id(game, idinfo.name)] = idinfo; + } +} + +int mix_database::load() +{ + if (!td_list.empty() || !ra_list.empty() || !ts_list.empty()) + return 0; + Cvirtual_binary f; + if (f.load(xcc_dirs::get_data_dir() + "global mix database.dat") || f.size() < 16) + return 1; + const char* data = reinterpret_cast(f.data()); + read_list(game_td, data); + read_list(game_ra, data); + read_list(game_ts, data); + read_list(game_ra2, data); + if (0) + { + ofstream log_f("c:\\log.txt"); + for (auto& i : ts_list) + log_f << i.second.name << '\t' << i.second.description << endl; + } + return 0; + char name[12] = "scg00ea.bin"; + const char char1[] = "bgjm"; + const char char2[] = "ew"; + const char char3[] = "abc"; + for (int i = 0; i < 2; i++) + { + if (i) + strcpy(name + 8, "ini"); + for (int j = 0; j < 4; j++) + { + name[2] = char1[j]; + for (int k = 0; k < 100; k++) + { + memcpy(name + 3, nwzl(2, k).c_str(), 2); + for (int l = 0; l < 2; l++) + { + name[5] = char2[l]; + for (int m = 0; m < 3; m++) + { + name[6] = char3[m]; + mix_database::add_name(game_td, name, ""); + mix_database::add_name(game_ra, name, ""); + mix_database::add_name(game_ts, name, ""); + } + } + } + } + } + return 0; +} + +void mix_database::add_name(t_game game, const string& name, const string& description) +{ + t_idinfo idinfo; + idinfo.name = name; + idinfo.description = description; + get_list(game)[Cmix_file::get_id(game, name)] = idinfo; +} + +string mix_database::get_name(t_game game, int id) +{ + auto i = find_ptr(get_list(game), id); + return i ? i->name : ""; +} + +string mix_database::get_description(t_game game, int id) +{ + auto i = find_ptr(get_list(game), id); + return i ? i->description : ""; +} diff --git a/3rdParty/xcc/misc/id_log.h b/3rdParty/xcc/misc/id_log.h new file mode 100644 index 0000000..c866f86 --- /dev/null +++ b/3rdParty/xcc/misc/id_log.h @@ -0,0 +1,30 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include +#include + +namespace mix_database +{ + void add_name(t_game, const std::string& name, const std::string& description); + std::string get_name(t_game, int id); + std::string get_description(t_game, int id); + int load(); +}; diff --git a/3rdParty/xcc/misc/image_file.h b/3rdParty/xcc/misc/image_file.h new file mode 100644 index 0000000..b9e9fb5 --- /dev/null +++ b/3rdParty/xcc/misc/image_file.h @@ -0,0 +1,52 @@ +/* + XCC Utilities and Library + Copyright (C) 2001 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "cc_structures.h" +#include "palet.h" +#include "video_file.h" +#include "virtual_file.h" +#include "virtual_image.h" + +template +class Cimage_file : public Cvideo_file +{ +public: + virtual void decode(void*) const = 0; + +#ifndef XCC_MINIMAL_BUILD + virtual Cvirtual_image vimage() const + { + Cvirtual_binary image; + decode(image.write_start(this->cb_image())); + return Cvirtual_image(image, this->cx(), this->cy(), this->cb_pixel(), this->palet()); + } +#endif + + int cf() const override + { + return 1; + } +}; + +#ifndef XCC_MINIMAL_BUILD +int image_file_write(Cvirtual_file&, t_file_type, const byte* image, const t_palet_entry*, int cx, int cy); +Cvirtual_file image_file_write(t_file_type, const byte* image, const t_palet_entry*, int cx, int cy); +int image_file_write(const string& name, t_file_type, const byte* image, const t_palet_entry*, int cx, int cy); +#endif diff --git a/3rdParty/xcc/misc/mix_decode.cpp b/3rdParty/xcc/misc/mix_decode.cpp new file mode 100644 index 0000000..5dbfc4e --- /dev/null +++ b/3rdParty/xcc/misc/mix_decode.cpp @@ -0,0 +1,439 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include +#include + +const static char* pubkey_str = "AihRvNoIbTn85FZRYNZRcT+i6KpU+maCsEqr3Q5q+LDB5tH7Tz2qQ38V"; + +const static char char2num[] = +{ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +using word = unsigned short; +using bignum = uint32_t[64]; + +static struct +{ + bignum key1; + bignum key2; + uint32_t len; +} pubkey; + +static bignum glob1; +static uint32_t glob1_bitlen; +static uint32_t glob1_len_x2; +static uint32_t glob2[130]; +static uint32_t glob1_hi[4]; +static uint32_t glob1_hi_inv[4]; +static uint32_t glob1_hi_bitlen; +static uint32_t glob1_hi_inv_lo; +static uint32_t glob1_hi_inv_hi; + +static void init_bignum(bignum n, uint32_t val, uint32_t len) +{ + memset(n, 0, len * 4); + n[0] = val; +} + +static void move_key_to_big(bignum n, const char* key, uint32_t klen, uint32_t blen) +{ + uint32_t sign = key[0] & 0x80 ? 0xff : 0; + int i = blen * 4; + for (; i > klen; i--) + ((char *)n)[i - 1] = sign; + for (; i > 0; i--) + ((char *)n)[i - 1] = key[klen - i]; +} + +static void key_to_bignum(bignum n, char *key, uint32_t len) +{ + uint32_t keylen; + int i; + + if (key[0] != 2) + return; + key++; + + if (key[0] & 0x80) + { + keylen = 0; + for (i = 0; i < (key[0] & 0x7f); i++) keylen = (keylen << 8) | key[i+1]; + key += (key[0] & 0x7f) + 1; + } + else + { + keylen = key[0]; + key++; + } + if (keylen <= len * 4) + move_key_to_big(n, key, keylen, len); +} + +static uint32_t len_bignum(bignum n, uint32_t len) +{ + int i = len - 1; + while (i >= 0 && n[i] == 0) + i--; + return i + 1; +} + +static uint32_t bitlen_bignum(bignum n, uint32_t len) +{ + uint32_t ddlen = len_bignum(n, len); + if (ddlen == 0) + return 0; + uint32_t bitlen = ddlen * 32; + uint32_t mask = 0x80000000; + while ((mask & n[ddlen - 1]) == 0) + { + mask >>= 1; + bitlen--; + } + return bitlen; +} + +static void init_pubkey() +{ + init_bignum(pubkey.key2, 0x10001, 64); + char keytmp[256]; + uint32_t i2 = 0; + for (uint32_t i = 0; i < strlen(pubkey_str);) + { + uint32_t tmp = char2num[pubkey_str[i++]]; + tmp <<= 6; tmp |= char2num[pubkey_str[i++]]; + tmp <<= 6; tmp |= char2num[pubkey_str[i++]]; + tmp <<= 6; tmp |= char2num[pubkey_str[i++]]; + keytmp[i2++] = (tmp >> 16) & 0xff; + keytmp[i2++] = (tmp >> 8) & 0xff; + keytmp[i2++] = tmp & 0xff; + } + key_to_bignum(pubkey.key1, keytmp, 64); + pubkey.len = bitlen_bignum(pubkey.key1, 64) - 1; +} + +static uint32_t len_predata() +{ + uint32_t a = (pubkey.len - 1) / 8; + return (55 / a + 1) * (a + 1); +} + +static int cmp_bignum(bignum n1, bignum n2, uint32_t len) +{ + n1 += len - 1; + n2 += len - 1; + while (len > 0) + { + if (*n1 < *n2) return -1; + if (*n1 > *n2) return 1; + n1--; + n2--; + len--; + } + return 0; +} + +static void mov_bignum(bignum dest, bignum src, uint32_t len) +{ + memmove(dest, src, len * 4); +} + +static void shr_bignum(bignum n, uint32_t bits, long int len) +{ + uint32_t i; + if (uint32_t i2 = bits / 32) + { + for (i = 0; i < len - i2; i++) + n[i] = n[i + i2]; + for (; i < len; i++) + n[i] = 0; + bits %= 32; + } + if (!bits) + return; + for (i = 0; i < len - 1; i++) + n[i] = (n[i] >> bits) | (n[i + 1] << (32 - bits)); + n[i] >>= bits; +} + +static void shl_bignum(bignum n, uint32_t bits, uint32_t len) +{ + uint32_t i; + if (uint32_t i2 = bits / 32) + { + for (i = len - 1; i > i2; i--) + n[i] = n[i - i2]; + for (; i > 0; i--) + n[i] = 0; + bits %= 32; + } + if (!bits) + return; + for (i = len - 1; i > 0; i--) + n[i] = (n[i] << bits) | (n[i - 1] >> (32 - bits)); + n[0] <<= bits; +} + +static uint32_t sub_bignum(bignum dest, bignum src1, bignum src2, uint32_t carry, uint32_t len) +{ + len *= 2; + while (--len != -1) + { + uint32_t i1 = *(word *)src1; + uint32_t i2 = *(word *)src2; + *(word *)dest = i1 - i2 - carry; + src1 = (uint32_t *)(((word *)src1) + 1); + src2 = (uint32_t *)(((word *)src2) + 1); + dest = (uint32_t *)(((word *)dest) + 1); + carry = ((i1 - i2 - carry) & 0x10000) ? 1 : 0; + } + return carry; +} + +static void inv_bignum(bignum n1, bignum n2, uint32_t len) +{ + bignum n_tmp; + + init_bignum(n_tmp, 0, len); + init_bignum(n1, 0, len); + int n2_bitlen = bitlen_bignum(n2, len); + uint32_t bit = ((uint32_t)1) << (n2_bitlen % 32); + n1 += ((n2_bitlen + 32) / 32) - 1; + uint32_t n2_bytelen = ((n2_bitlen - 1) / 32) * 4; + n_tmp[n2_bytelen / 4] |= ((uint32_t)1) << ((n2_bitlen - 1) & 0x1f); + + while (n2_bitlen > 0) + { + n2_bitlen--; + shl_bignum(n_tmp, 1, len); + if (cmp_bignum(n_tmp, n2, len) != -1) + { + sub_bignum(n_tmp, n_tmp, n2, 0, len); + *n1 |= bit; + } + bit >>= 1; + if (bit == 0) + { + n1--; + bit = 0x80000000; + } + } + init_bignum(n_tmp, 0, len); +} + +static void inc_bignum(bignum n, uint32_t len) +{ + while ((++*n == 0) && (--len > 0)) + n++; +} + +static void init_two_dw(bignum n, uint32_t len) +{ + mov_bignum(glob1, n, len); + glob1_bitlen = bitlen_bignum(glob1, len); + glob1_len_x2 = (glob1_bitlen + 15) / 16; + mov_bignum(glob1_hi, glob1 + len_bignum(glob1, len) - 2, 2); + glob1_hi_bitlen = bitlen_bignum(glob1_hi, 2) - 32; + shr_bignum(glob1_hi, glob1_hi_bitlen, 2); + inv_bignum(glob1_hi_inv, glob1_hi, 2); + shr_bignum(glob1_hi_inv, 1, 2); + glob1_hi_bitlen = (glob1_hi_bitlen + 15) % 16 + 1; + inc_bignum(glob1_hi_inv, 2); + if (bitlen_bignum(glob1_hi_inv, 2) > 32) + { + shr_bignum(glob1_hi_inv, 1, 2); + glob1_hi_bitlen--; + } + glob1_hi_inv_lo = *(word *)glob1_hi_inv; + glob1_hi_inv_hi = *(((word *)glob1_hi_inv) + 1); +} + +static void mul_bignum_word(bignum n1, bignum n2, uint32_t mul, uint32_t len) +{ + uint32_t tmp = 0; + for (uint32_t i = 0; i < len; i++) + { + tmp = mul * (*(word *)n2) + *(word *)n1 + tmp; + *(word *)n1 = tmp; + n1 = (uint32_t *)(((word *)n1) + 1); + n2 = (uint32_t *)(((word *)n2) + 1); + tmp >>= 16; + } + *(word *)n1 += tmp; +} + +static void mul_bignum(bignum dest, bignum src1, bignum src2, uint32_t len) +{ + init_bignum(dest, 0, len * 2); + for (uint32_t i = 0; i < len * 2; i++) + { + mul_bignum_word(dest, src1, *(word *)src2, len * 2); + src2 = (uint32_t *)(((word *)src2) + 1); + dest = (uint32_t *)(((word *)dest) + 1); + } +} + +static void not_bignum(bignum n, uint32_t len) +{ + for (uint32_t i = 0; i < len; i++) + *(n++) = ~*n; +} + +static void neg_bignum(bignum n, uint32_t len) +{ + not_bignum(n, len); + inc_bignum(n, len); +} + +static uint32_t get_mulword(bignum n) +{ + word* wn = (word *)n; + uint32_t i = (((((((((*(wn - 1) ^ 0xffff) & 0xffff) * glob1_hi_inv_lo + 0x10000) >> 1) + + (((*(wn-2) ^ 0xffff) * glob1_hi_inv_hi + glob1_hi_inv_hi) >> 1) + 1) + >> 16) + ((((*(wn-1) ^ 0xffff) & 0xffff) * glob1_hi_inv_hi) >> 1) + + (((*wn ^ 0xffff) * glob1_hi_inv_lo) >> 1) + 1) >> 14) + glob1_hi_inv_hi + * (*wn ^ 0xffff) * 2) >> glob1_hi_bitlen; + if (i > 0xffff) + i = 0xffff; + return i & 0xffff; +} + +static void dec_bignum(bignum n, uint32_t len) +{ + while ((--*n == 0xffffffff) && (--len > 0)) + n++; +} + +static void calc_a_bignum(bignum n1, bignum n2, bignum n3, uint32_t len) +{ + mul_bignum(glob2, n2, n3, len); + glob2[len * 2] = 0; + uint32_t g2_len_x2 = len_bignum(glob2, len * 2 + 1) * 2; + if (g2_len_x2 >= glob1_len_x2) + { + inc_bignum(glob2, len * 2 + 1); + neg_bignum(glob2, len * 2 + 1); + uint32_t len_diff = g2_len_x2 + 1 - glob1_len_x2; + word* esi = ((word *)glob2) + (1 + g2_len_x2 - glob1_len_x2); + word* edi = ((word *)glob2) + (g2_len_x2 + 1); + for (; len_diff != 0; len_diff--) + { + edi--; + word tmp = get_mulword((uint32_t *)edi); + esi--; + if (tmp > 0) + { + mul_bignum_word((uint32_t *)esi, glob1, tmp, 2 * len); + if ((*edi & 0x8000) == 0) + { + if (sub_bignum((uint32_t *)esi, (uint32_t *)esi, glob1, 0, len)) + (*edi)--; + } + } + } + neg_bignum(glob2, len); + dec_bignum(glob2, len); + } + mov_bignum(n1, glob2, len); +} + +static void calc_a_key(bignum n1, bignum n2, bignum n3, bignum n4, uint32_t len) +{ + bignum n_tmp; + init_bignum(n1, 1, len); + uint32_t n4_len = len_bignum(n4, len); + init_two_dw(n4, n4_len); + uint32_t n3_bitlen = bitlen_bignum(n3, n4_len); + uint32_t n3_len = (n3_bitlen + 31) / 32; + uint32_t bit_mask = (((uint32_t)1) << ((n3_bitlen - 1) % 32)) >> 1; + n3 += n3_len - 1; + n3_bitlen--; + mov_bignum(n1, n2, n4_len); + while (--n3_bitlen != -1) + { + if (bit_mask == 0) + { + bit_mask = 0x80000000; + n3--; + } + calc_a_bignum(n_tmp, n1, n1, n4_len); + if (*n3 & bit_mask) + calc_a_bignum(n1, n_tmp, n2, n4_len); + else + mov_bignum(n1, n_tmp, n4_len); + bit_mask >>= 1; + } + init_bignum(n_tmp, 0, n4_len); + init_bignum(glob1, 0, len); + init_bignum(glob2, 0, len); + init_bignum(glob1_hi_inv, 0, 4); + init_bignum(glob1_hi, 0, 4); + glob1_bitlen = 0; + glob1_hi_bitlen = 0; + glob1_len_x2 = 0; + glob1_hi_inv_lo = 0; + glob1_hi_inv_hi = 0; +} + +static void process_predata(const byte* pre, uint32_t pre_len, byte *buf) +{ + bignum n2, n3; + const uint32_t a = (pubkey.len - 1) / 8; + while (a + 1 <= pre_len) + { + init_bignum(n2, 0, 64); + memmove(n2, pre, a + 1); + calc_a_key(n3, n2, pubkey.key2, pubkey.key1, 64); + + memmove(buf, n3, a); + + pre_len -= a + 1; + pre += a + 1; + buf += a; + } +} + +void get_blowfish_key(const byte* s, span d) +{ + static bool public_key_initialized = false; + if (!public_key_initialized) + { + init_pubkey(); + public_key_initialized = true; + } + byte key[256]; + process_predata(s, len_predata(), key); + memcpy(d.data(), key, 56); +} diff --git a/3rdParty/xcc/misc/mix_decode.h b/3rdParty/xcc/misc/mix_decode.h new file mode 100644 index 0000000..388f8ed --- /dev/null +++ b/3rdParty/xcc/misc/mix_decode.h @@ -0,0 +1,21 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +void get_blowfish_key(const byte* s, span d); diff --git a/3rdParty/xcc/misc/mix_file.cpp b/3rdParty/xcc/misc/mix_file.cpp new file mode 100644 index 0000000..874ff31 --- /dev/null +++ b/3rdParty/xcc/misc/mix_file.cpp @@ -0,0 +1,424 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include "mix_file.h" + +#ifndef NO_FT_SUPPORT +#include "big_file.h" +#endif +#include "blowfish.h" +#include "crc.h" +#include "id_log.h" +#ifndef NO_FT_SUPPORT +#include "mix_cache.h" +#endif +#include "mix_decode.h" +#ifndef NO_FT_SUPPORT +#include "mix_rg_file.h" +#include "pak_file.h" +#endif +#include "string_conversion.h" +#include "xcc_lmd_file.h" + +bool Cmix_file::m_ft_support = false; + +Cmix_file::Cmix_file() : + Ccc_file(false) +{ +} + +bool Cmix_file::is_valid() +{ + const byte* data = get_data(); + if (!data) + return false; + const t_mix_header& header = *reinterpret_cast(data); + int size = get_size(); + if (sizeof(t_mix_header) > size) + return false; + if (header.c_files && sizeof(t_mix_header) + header.c_files * sizeof(t_mix_index_entry) + header.size == size) + return true; + if (header.flags & ~(mix_encrypted | mix_checksum)) + return false; + m_has_checksum = header.flags & mix_checksum; + m_is_encrypted = header.flags & mix_encrypted; + if (m_is_encrypted) + { + Cblowfish bf; + std::array key; + get_blowfish_key(data + 4, key); + bf.set_key(key); + byte e[8]; + bf.decipher(data + 84, e, 8); + t_mix_header* header = reinterpret_cast(e); + if (!header->c_files || 84 + (sizeof(t_mix_header) + header->c_files * sizeof(t_mix_index_entry) + 7 & ~7) + header->size + (m_has_checksum ? 20 : 0) != size) + return false; + } + else + { + const t_mix_header* header = reinterpret_cast(data + 4); + if (!header->c_files || 4 + sizeof(t_mix_header) + header->c_files * sizeof(t_mix_index_entry) + header->size + (m_has_checksum ? 20 : 0) != size) + return false; + } + return true; +} + +#define test_fail(res) { int v = res; if (v) { close(); return v; }} + +int Cmix_file::post_open() +{ +#ifndef NO_FT_SUPPORT + bool index_read = false; + if (h()) + { + Cmix_rg_file f; + if (get_data()) + f.load(vdata()); + else + f.open(h()); + if (f.is_open() && f.is_valid()) + { + m_game = game_rg; + m_is_encrypted = m_has_checksum = false; + int c_files = f.get_c_files(); + m_index.resize(c_files); + for (int i = 0; i < c_files; i++) + { + string name = f.get_name(i); + mix_database::add_name(m_game, name, "-"); + m_index[i] = t_mix_index_entry(get_id(get_game(), name), f.get_offset(name), f.get_size(name)); + } + index_read = true; + } + else + { + Cbig_file f; + if (get_data()) + f.load(vdata()); + else + f.open(h()); + if (f.is_open() && f.is_valid()) + { + m_game = game_gr; + m_is_encrypted = m_has_checksum = false; + int c_files = f.get_c_files(); + m_index.resize(c_files); + for (int i = 0; i < c_files; i++) + { + string name = f.get_name(i); + mix_database::add_name(m_game, name, "-"); + m_index[i] = t_mix_index_entry(get_id(get_game(), name), f.get_offset(name), f.get_size(name)); + } + index_read = true; + } + } + } + if (!index_read) + { + Cpak_file f; + if (get_data()) + f.load(vdata()); + else + { + int size = min(get_size(), 64 << 10); + Cvirtual_binary data; + test_fail(read(data.write_start(size), size)); + f.load(data, get_size()); + } + if (f.is_valid()) + { + m_game = game_dune2; + m_is_encrypted = m_has_checksum = false; + int c_files = f.get_c_files(); + if (c_files >> 12) + test_fail(1); + m_index.resize(c_files); + for (int i = 0; i < c_files; i++) + { + string name = f.get_name(i); + mix_database::add_name(m_game, name, "-"); + m_index[i] = t_mix_index_entry(get_id(get_game(), name), f.get_offset(name), f.get_size(name)); + } + index_read = true; + } + } + if (!index_read) +#endif + { + t_mix_header header; + seek(0); + test_fail(read(&header, sizeof(t_mix_header))); + if (header.c_files) + { + m_game = game_td; + m_is_encrypted = m_has_checksum = false; + int c_files = header.c_files; + int cb_index = c_files * sizeof(t_mix_index_entry); + if (header.c_files >> 12 || get_size() != 6 + cb_index + header.size) + test_fail(1); + m_index.resize(c_files); + test_fail(read(&m_index[0], cb_index)); + for (int i = 0; i < c_files; i++) + m_index[i].offset += 6 + cb_index; + } + else + { + m_has_checksum = header.flags & mix_checksum; + m_is_encrypted = header.flags & mix_encrypted; + bool aligned = true; + Cblowfish bf; + seek(4); + if (m_is_encrypted) + { + byte key_source[cb_mix_key_source]; + read(key_source, cb_mix_key_source); + std::array key; + get_blowfish_key(key_source, key); + bf.set_key(key); + byte e[8]; + read(e, 8); + bf.decipher(e, e, 8); + memcpy(&header, e, sizeof(t_mix_header)); + int c_files = header.c_files; + const int cb_index = c_files * sizeof(t_mix_index_entry); + const int cb_f = cb_index + 5 & ~7; + if (get_size() != 92 + cb_f + header.size + (m_has_checksum ? 20 : 0)) + test_fail(1); + if (c_files) + { + Cvirtual_binary f; + read(f.write_start(cb_f), cb_f); + bf.decipher(f.data_edit(), f.data_edit(), cb_f); + m_index.resize(c_files); + memcpy(&m_index[0], e + 6, 2); + memcpy(reinterpret_cast(&m_index[0]) + 2, f.data(), cb_index - 2); + for (int i = 0; i < c_files; i++) + { + if (m_index[i].offset & 0xf) + aligned = false; + m_index[i].offset += 92 + cb_f; + } + } + } + else + { + read(&header, sizeof(header)); + int c_files = header.c_files; + const int cb_index = c_files * sizeof(t_mix_index_entry); + if (get_size() != 4 + sizeof(t_mix_header) + cb_index + header.size + (m_has_checksum ? 20 : 0)) + test_fail(1); + m_index.resize(c_files); + read(&m_index[0], cb_index); + for (int i = 0; i < c_files; i++) + { + if (m_index[i].offset & 0xf) + aligned = false; + m_index[i].offset += 4 + sizeof(t_mix_header) + cb_index; + } + } + m_game = is_encrypted() ? game_ra : game_ts; + for (int i = 0; i < get_c_files(); i++) + { + if (get_id(i) == 0x763c81dd) + { + m_game = game_ts; + break; + } + } + if (m_game == game_ra && aligned) + m_game = game_ts; + } + } + for (int i = 0; i < get_c_files(); i++) + m_id_index[get_id(i)] = i; +#ifndef NO_FT_SUPPORT + if (m_ft_support) + { + switch (m_game) + { + case game_dune2: + case game_rg: + break; + default: + int count[game_unknown] = {0}; + for (int i = 0; i < get_c_files(); i++) + { + int id = get_id(i); + for (int game = game_td; game < game_unknown; game++) + count[game] += mix_database::get_name(static_cast(game), id).empty(); + } + int min = count[0]; + for (int game = 0; game < game_unknown; game++) + { + if (count[game] < min) + { + m_game = static_cast(game); + min = count[game]; + } + } + } + if (vdata().size() == get_size()) + { + int crc = compute_crc(&m_index[0], get_c_files() * sizeof(t_mix_index_entry)); + Cvirtual_binary s = mix_cache::get_data(crc); + m_index_ft.resize(get_c_files()); + if (s.size() == get_c_files() * sizeof(t_file_type)) + memcpy(&m_index_ft[0], s.data(), get_c_files() * sizeof(t_file_type)); + else + { + using t_block_map = multimap; + + t_block_map block_map; + for (int i = 0; i < get_c_files(); i++) + block_map.insert(t_block_map::value_type(get_offset(get_id(i)), i)); + for (auto& i : block_map) + { + Ccc_file f(false); + f.open(get_id(i.second), *this); + m_index_ft[i.second] = f.get_file_type(); + } + mix_cache::set_data(crc, Cvirtual_binary(&m_index_ft[0], get_c_files() * sizeof(t_file_type))); + } + for (int i = 0; i < get_c_files(); i++) + { + int id = get_id(i); + Cxcc_lmd_file f; + if (get_type(id) != ft_xcc_lmd || f.open(id, *this) || !f.is_valid()) + continue; + m_game = f.get_game(); + int count = f.get_c_fnames(); + const char* r = f.get_fnames(); + while (count--) + { + string name = r; + r += name.length() + 1; + mix_database::add_name(m_game, name, "-"); + } + } + } + } +#endif + if (m_mix_expansion) + { + int c_files = get_c_files(); + for (int i = 0; i < c_files; i++) + { + if (get_type(m_index[i].id) != ft_mix) + continue; + Cmix_file f; + f.open(m_index[i].id, *this); + int c_files = get_c_files(); + int new_c_files = f.get_c_files(); + m_index.resize(c_files + new_c_files); + for (int j = 0; j < new_c_files; j++) + { + int id = f.get_id(j); + m_index[c_files + j] = t_mix_index_entry(id, f.get_offset(id) + get_offset(m_index[i].id), f.get_size(id)); + m_id_index[id] = c_files + j; + } + m_index_ft.resize(c_files + new_c_files); + memcpy(&m_index_ft[c_files], &f.m_index_ft[0], new_c_files * sizeof(t_file_type)); + } + } + return 0; +} + +void Cmix_file::close() +{ + m_id_index.clear(); + m_index_ft.clear(); + m_index.clear(); + Ccc_file::close(); +} + +string Cmix_file::get_name(int id) +{ +#ifdef NO_FT_SUPPORT + return ""; +#else + return mix_database::get_name(get_game(), id); +#endif +} + +int Cmix_file::get_id(t_game game, string name) +{ + boost::to_upper(name); + std::replace(name.begin(), name.end(), '/', '\\'); + switch (game) + { + case game_ts: + case game_ra2: + case game_ra2_yr: + { + const int l = name.length(); + int a = l & ~3; + if (l & 3) + { + name += static_cast(l - a); + name.append(3 - (l & 3), name[a]); + } + return compute_crc(name.c_str(), name.length()); + } + case game_rg: + case game_gr: + case game_gr_zh: + return compute_crc(name.c_str(), name.length()); + default: + int i = 0; + unsigned int id = 0; + int l = name.length(); + while (i < l) + { + unsigned int a = 0; + for (int j = 0; j < 4; j++) + { + a >>= 8; + if (i < l) + a |= static_cast(name[i++]) << 24; + } + id = (id << 1 | id >> 31) + a; + } + return id; + } +} + +int Cmix_file::get_index(unsigned int id) const +{ + auto i = find_ptr(m_id_index, id); + return i ? *i : -1; +} + +Cvirtual_binary Cmix_file::get_vdata(int id) +{ + if (get_index(id) == -1) + return Cvirtual_binary(); + if (get_data()) + return vdata().sub_bin(get_offset(id), get_size(id)); + Cvirtual_binary d; + seek(get_offset(id)); + int size = get_size(id); + if (read(d.write_start(size), size)) + d.clear(); + return d; +} + +Cvirtual_binary Cmix_file::get_vdata(const string& name) +{ + return get_vdata(get_id(m_game, name)); +} diff --git a/3rdParty/xcc/misc/mix_file.h b/3rdParty/xcc/misc/mix_file.h new file mode 100644 index 0000000..fbf6681 --- /dev/null +++ b/3rdParty/xcc/misc/mix_file.h @@ -0,0 +1,115 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "cc_file.h" +#include "cc_structures.h" + +class Cmix_file : public Ccc_file +{ +public: + int post_open(); + string get_name(int id); + static int get_id(t_game game, string name); + int get_index(unsigned int id) const; + using Ccc_file::get_size; + using Ccc_file::vdata; + Cvirtual_binary get_vdata(int id); + Cvirtual_binary get_vdata(const string& name); + bool is_valid(); + void close(); + Cmix_file(); + + static void enable_ft_support() + { + assert(!m_ft_support); + m_ft_support = true; + } + + void enable_mix_expansion() + { + assert(!m_mix_expansion); + m_mix_expansion = true; + } + + int get_c_files() const + { + return m_index.size(); + } + + t_game get_game() const + { + return m_game; + } + + void set_game(t_game game) + { + m_game = game; + } + + t_file_type get_type(int id) + { + assert(get_index(id) != -1); + return m_index_ft[get_index(id)]; + } + + int get_id(int index) const + { + return m_index[index].id; + } + + int get_offset(unsigned int id) const + { + assert(get_index(id) != -1); + return m_index[get_index(id)].offset; + } + + int get_size(unsigned int id) const + { + assert(get_index(id) != -1); + return m_index[get_index(id)].size; + } + + bool has_checksum() const + { + return m_has_checksum; + } + + bool is_encrypted() const + { + return m_is_encrypted; + } + + const t_mix_index_entry* index() const + { + return &m_index[0]; + } +private: + using t_id_index = map; + + static bool m_ft_support; + + t_game m_game; + bool m_mix_expansion = false; + bool m_is_encrypted; + bool m_has_checksum; + vector m_index; + vector m_index_ft; + t_id_index m_id_index; +}; diff --git a/3rdParty/xcc/misc/mix_file_write.cpp b/3rdParty/xcc/misc/mix_file_write.cpp new file mode 100644 index 0000000..85b750f --- /dev/null +++ b/3rdParty/xcc/misc/mix_file_write.cpp @@ -0,0 +1,83 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "mix_file_write.h" + +#include "mix_file.h" +#include "string_conversion.h" + +Cmix_file_write::Cmix_file_write(t_game game) +{ + m_game = game; +} + +void Cmix_file_write::add_file(int id, const Cvirtual_binary d) +{ + m_index[id] = d; +} + +void Cmix_file_write::add_file(string name, const Cvirtual_binary d) +{ + add_file(Cmix_file::get_id(m_game, name), d); + m_lmd_fw.add_fname(name); +} + +void Cmix_file_write::clear() +{ + m_index.clear(); +} + +int Cmix_file_write::write_start() +{ + add_file("local mix database.dat", m_lmd_fw.write(m_game)); + int r = 4 + sizeof(t_mix_header) + m_index.size() * sizeof(t_mix_index_entry); + for (auto& i : m_index) + r += i.second.size(); + return r; +} + +int Cmix_file_write::write(byte* d) const +{ + byte* w = d; + *reinterpret_cast<__int32*>(w) = 0; + w += 4; + t_mix_header& header = *reinterpret_cast(w); + header.c_files = m_index.size(); + w += sizeof(t_mix_header); + t_mix_index_entry* index = reinterpret_cast(w); + w += m_index.size() * sizeof(t_mix_index_entry); + byte* body_start = w; + for (auto& i : m_index) + { + index->id = i.first; + index->offset = w - body_start; + index->size = i.second.size(); + index++; + w += i.second.read(w); + } + header.size = w - body_start; + return w - d; +} + +Cvirtual_binary Cmix_file_write::write() +{ + Cvirtual_binary d; + write(d.write_start(write_start())); + return d; +} diff --git a/3rdParty/xcc/misc/mix_file_write.h b/3rdParty/xcc/misc/mix_file_write.h new file mode 100644 index 0000000..c1b4fae --- /dev/null +++ b/3rdParty/xcc/misc/mix_file_write.h @@ -0,0 +1,42 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "cc_structures.h" +#include +#include "xcc_lmd_file_write.h" + +class Cmix_file_write +{ +public: + void add_file(int id, const Cvirtual_binary d); + void add_file(string name, const Cvirtual_binary d); + void clear(); + Cvirtual_binary write(); + Cmix_file_write(t_game game); +private: + using t_index = map; + + int write_start(); + int write(byte* d) const; + + t_game m_game; + t_index m_index; + Cxcc_lmd_file_write m_lmd_fw; +}; diff --git a/3rdParty/xcc/misc/null_ini_reader.h b/3rdParty/xcc/misc/null_ini_reader.h new file mode 100644 index 0000000..846b270 --- /dev/null +++ b/3rdParty/xcc/misc/null_ini_reader.h @@ -0,0 +1,48 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "ini_reader.h" + +class Cnull_ini_reader : public Cini_reader +{ +public: + int process_section_start(string_view) override + { + mc_sections++; + return 0; + } + + bool process_section() const override + { + return true; + } + + int process_key(string_view, string_view) override + { + return 0; + } + + bool is_valid() const + { + return mc_sections; + } +private: + int mc_sections = 0; +}; diff --git a/3rdParty/xcc/misc/pal_file.cpp b/3rdParty/xcc/misc/pal_file.cpp new file mode 100644 index 0000000..801f245 --- /dev/null +++ b/3rdParty/xcc/misc/pal_file.cpp @@ -0,0 +1,50 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "pal_file.h" + +#include + +bool Cpal_file::is_valid() const +{ + if (get_size() != sizeof(t_palet)) + return false; + const t_palet_entry* p = get_palet(); + for (int i = 0; i < 256; i++) + { + if ((p[i].r | p[i].g | p[i].b) & 0xc0) + return false; + } + return true; +} + +ostream& Cpal_file::extract_as_pal_jasc(ostream& os, bool shift_left) const +{ + os << "JASC-PAL" << endl + << "0100" << endl + << "256" << endl; + t_palet palet; + if (shift_left) + convert_palet_18_to_24(get_palet(), palet); + else + memcpy(palet, get_palet(), sizeof(t_palet)); + for (int i = 0; i < 256; i++) + os << static_cast(palet[i].r) << ' ' << static_cast(palet[i].g) << ' ' << static_cast(palet[i].b) << endl; + return os; +} diff --git a/3rdParty/xcc/misc/pal_file.h b/3rdParty/xcc/misc/pal_file.h new file mode 100644 index 0000000..9d57687 --- /dev/null +++ b/3rdParty/xcc/misc/pal_file.h @@ -0,0 +1,39 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include +#include + +class Cpal_file : public Ccc_file_small +{ +public: + ostream& extract_as_pal_jasc(ostream&, bool shift_left = true) const; + bool is_valid() const; + + void decode(t_palet& palet) const + { + convert_palet_18_to_24(get_palet(), palet); + } + + const t_palet_entry* get_palet() const + { + return reinterpret_cast(data()); + } +}; diff --git a/3rdParty/xcc/misc/palet.cpp b/3rdParty/xcc/misc/palet.cpp new file mode 100644 index 0000000..e24071b --- /dev/null +++ b/3rdParty/xcc/misc/palet.cpp @@ -0,0 +1,214 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include +#include "palet.h" + +void convert_image_8_to_24(const byte* s, byte* d, int cx, int cy, const t_palet palet) +{ + const byte* r = s; + byte* w = d; + int c = cx * cy; + while (c--) + { + const t_palet_entry* v = palet + *r++; + *w++ = v->r; + *w++ = v->g; + *w++ = v->b; + } +} + +void create_downsample_table(const t_palet palet, byte* rp) +{ + byte* rp_w = rp; + for (int b = 0; b < 0x40; b++) + { + for (int g = 0; g < 0x40; g++) + { + for (int r = 0; r < 0x40; r++) + *rp_w++ = find_color(r * 255 / 63, g * 255 / 63, b * 255 / 63, palet); + } + } +} + +void convert_image_24_to_8(const byte* s, byte* d, int cx, int cy, const byte* rp) +{ + const byte* r = s; + byte* w = d; + int c = cx * cy; + while (c--) + { + int red = *r++ >> 2 & 0x3f; + int green = *r++ >> 2 & 0x3f; + int blue = *r++ >> 2 & 0x3f; + *w++ = rp[red | green << 6 | blue << 12]; + } +} + +void convert_image_24_to_8(const byte* s, byte* d, int cx, int cy, const t_palet palet) +{ + const byte* r = s; + byte* w = d; + int c = cx * cy; + while (c--) + { + int red = *r++; + int green = *r++; + int blue = *r++; + *w++ = find_color(red, green, blue, palet); + } +} + +void downsample_image(const t_palet32entry* s, byte* d, int cx, int cy, const byte* rp) +{ + const t_palet32entry* r = s; + byte* w = d; + int c = cx * cy; + while (c--) + { + t_palet32entry e = *r++; + *w++ = e.a < 0x80 ? 0 : rp[e.r >> 2 | (e.g & 0xfc) << 4 | (e.b & 0xfc) << 10]; + } +} + +void downsample_image(const t_palet32entry* s, byte* d, int cx, int cy, const t_palet palet) +{ + const t_palet32entry* r = s; + byte* w = d; + int c = cx * cy; + while (c--) + { + t_palet32entry e = *r++; + if (e.a < 0x80) + *w++ = 0; + else + *w++ = find_color(e.r, e.g, e.b, palet); + } +} + +void upsample_image(const byte* s, t_palet32entry* d, int cx, int cy, const t_palet palet) +{ + const byte* r = s; + t_palet32entry* w = d; + int c = cx * cy; + while (c--) + { + t_palet32entry& e = *w++; + int z = *r++; + if (z) + { + const t_palet_entry* v = palet + z; + e.r = v->r; + e.g = v->g; + e.b = v->b; + e.a = 0xff; + } + else + { + e.r = 0x80; + e.g = 0x80; + e.b = 0x80; + e.a = 0; + } + } +} + +void convert_palet_18_to_24(const t_palet s, t_palet d) +{ + for (int i = 0; i < 256; i++) + { + d[i].r = (s[i].r & 63) * 255 / 63; + d[i].g = (s[i].g & 63) * 255 / 63; + d[i].b = (s[i].b & 63) * 255 / 63; + } +} + +void convert_palet_24_to_18(const t_palet s, t_palet d) +{ + for (int i = 0; i < 256; i++) + { + d[i].r = s[i].r >> 2; + d[i].g = s[i].g >> 2; + d[i].b = s[i].b >> 2; + } +} + +void convert_palet_18_to_24(t_palet palet) +{ + convert_palet_18_to_24(palet, palet); +} + +void convert_palet_24_to_18(t_palet palet) +{ + convert_palet_24_to_18(palet, palet); +} + +int find_color(int r, int g, int b, const t_palet p) +{ + int best_i; + int min_d = INT_MAX; + for (int i = 0; i < 256; i++) + { + int d_r = p[i].r - r; + int d_g = p[i].g - g; + int d_b = p[i].b - b; + int d = d_r * d_r + d_g * d_g + d_b * d_b; + if (d < min_d) + { + min_d = d; + best_i = i; + } + } + return best_i; +} + +int find_color_t(int r, int g, int b, const t_palet p) +{ + int best_i; + int min_d = INT_MAX; + for (int i = 1; i < 256; i++) + { + int d_r = p[i].r - r; + int d_g = p[i].g - g; + int d_b = p[i].b - b; + int d = d_r * d_r + d_g * d_g + d_b * d_b; + if (d < min_d) + { + min_d = d; + best_i = i; + } + } + return best_i; +} + +void create_rp(const t_palet s1, const t_palet s2, byte* d) +{ + d[0] = 0; + for (int i = 1; i < 256; i++) + d[i] = find_color(s1[i].r, s1[i].g, s1[i].b, s2); +} + +void apply_rp(byte* d, int cb_d, const byte* rp) +{ + while (cb_d--) + { + *d = rp[*d]; + d++; + } +} \ No newline at end of file diff --git a/3rdParty/xcc/misc/palet.h b/3rdParty/xcc/misc/palet.h new file mode 100644 index 0000000..539fbab --- /dev/null +++ b/3rdParty/xcc/misc/palet.h @@ -0,0 +1,76 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include + +#pragma pack(push, 1) + +struct t_palet_entry +{ + byte r, g, b; +}; + +struct t_palet24rgb_entry +{ + byte r, g, b; +}; + +struct t_palet24bgr_entry +{ + byte b, g, r; +}; + +union t_palet32entry +{ + struct + { + byte r, g, b, a; + }; + unsigned __int32 v; +}; + +union t_palet32bgr_entry +{ + struct + { + byte b, g, r, a; + }; + unsigned __int32 v; +}; + +using t_palet = t_palet_entry[256]; + +void apply_rp(byte* d, int cb_d, const byte* rp); +void convert_image_8_to_24(const byte* s, byte* d, int cx, int cy, const t_palet palet); +void convert_image_24_to_8(const byte* s, byte* d, int cx, int cy, const byte* rp); +void convert_image_24_to_8(const byte* s, byte* d, int cx, int cy, const t_palet palet); +void convert_palet_18_to_24(const t_palet s, t_palet d); +void convert_palet_18_to_24(t_palet palet); +void convert_palet_24_to_18(const t_palet s, t_palet d); +void convert_palet_24_to_18(t_palet palet); +void create_downsample_table(const t_palet palet, byte* rp); +void create_rp(const t_palet s1, const t_palet s2, byte* d); +void downsample_image(const t_palet32entry* s, byte* d, int cx, int cy, const byte* rp); +void downsample_image(const t_palet32entry* s, byte* d, int cx, int cy, const t_palet palet); +void upsample_image(const byte* s, t_palet32entry* d, int cx, int cy, const t_palet palet); +int find_color(int r, int g, int b, const t_palet p); +int find_color_t(int r, int g, int b, const t_palet p); + +#pragma pack(pop) diff --git a/3rdParty/xcc/misc/reg_key.cpp b/3rdParty/xcc/misc/reg_key.cpp new file mode 100644 index 0000000..93401e9 --- /dev/null +++ b/3rdParty/xcc/misc/reg_key.cpp @@ -0,0 +1,105 @@ +/* + XCC Utilities and Library + Copyright (C) 2006 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "reg_key.h" + +#include + +using namespace std; + +Creg_key::Creg_key(HKEY key, const string& name, REGSAM sam_desired) +{ + m_h = NULL; + if (open(key, name, sam_desired) != ERROR_SUCCESS) + throw exception(); +} + +Creg_key::Creg_key(const Creg_key& key, const string& name, REGSAM sam_desired) +{ + m_h = NULL; + if (open(key.m_h, name, sam_desired) != ERROR_SUCCESS) + throw exception(); +} + +Creg_key::~Creg_key() +{ + close(); +} + +LONG Creg_key::create(HKEY key, const string& name) +{ + close(); + return RegCreateKeyExA(key, name.c_str(), 0, NULL, 0, KEY_ALL_ACCESS, NULL, &m_h, NULL); +} + +LONG Creg_key::open(HKEY key, const string& name, REGSAM sam_desired) +{ + close(); + return RegOpenKeyExA(key, name.c_str(), 0, sam_desired, &m_h); +}; + +LONG Creg_key::open(const Creg_key& key, const string& name, REGSAM sam_desired) +{ + return open(key.m_h, name, sam_desired); +}; + +LONG Creg_key::close() +{ + if (!m_h) + return ERROR_SUCCESS; + LONG result = RegCloseKey(m_h); + m_h = NULL; + return result; +} + +LONG Creg_key::query_value(const string& name, string& value) +{ + DWORD cb_d = 0; + LONG result = RegQueryValueExA(m_h, name.c_str(), NULL, NULL, NULL, &cb_d); + if (result != ERROR_SUCCESS) + return result; + if (!cb_d) + { + value.erase(); + return result; + } + vector d(cb_d); + result = RegQueryValueExA(m_h, name.c_str(), NULL, NULL, &d.front(), &cb_d); + if (result == ERROR_SUCCESS) + { + if (cb_d) + value.assign(reinterpret_cast(&d.front()), cb_d - 1); + else + value.erase(); + } + return result; +} + +string Creg_key::query_value(const string& name) +{ + string d; + if (query_value(name, d) != ERROR_SUCCESS) + throw exception(); + return d; +} + +LONG Creg_key::set_value(const string& name, const string& value) +{ + return RegSetValueExA(m_h, name.c_str(), 0, REG_SZ, reinterpret_cast(value.c_str()), value.size()); +} diff --git a/3rdParty/xcc/misc/reg_key.h b/3rdParty/xcc/misc/reg_key.h new file mode 100644 index 0000000..d087766 --- /dev/null +++ b/3rdParty/xcc/misc/reg_key.h @@ -0,0 +1,41 @@ +/* + XCC Utilities and Library + Copyright (C) 2006 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include +#include +#include + +class Creg_key : boost::noncopyable +{ +public: + Creg_key() = default; + Creg_key(HKEY, const std::string& name, REGSAM sam_desired); + Creg_key(const Creg_key&, const std::string& name, REGSAM sam_desired); + ~Creg_key(); + LONG create(HKEY key, const std::string& name); + LONG open(HKEY, const std::string& name, REGSAM sam_desired); + LONG open(const Creg_key&, const std::string& name, REGSAM sam_desired); + LONG close(); + LONG query_value(const std::string& name, std::string& value); + std::string query_value(const std::string& name); + LONG set_value(const std::string& name, const std::string& value); +private: + HKEY m_h = NULL; +}; diff --git a/3rdParty/xcc/misc/shp_decode.cpp b/3rdParty/xcc/misc/shp_decode.cpp new file mode 100644 index 0000000..e78be75 --- /dev/null +++ b/3rdParty/xcc/misc/shp_decode.cpp @@ -0,0 +1,1196 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "shp_decode.h" + +#include +#include +#include "cc_structures.h" + +static const char* encode64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const int decode64_table[256] = +{ + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1 +}; + +static int read_w(const byte*& r) +{ + int v = *reinterpret_cast(r); + r += 2; + return v; +} + +static void write_w(int v, byte*& w) +{ + *w++ = v & 0xff; + *w++ = v >> 8; +} + +static void write_v40(byte v, int count, byte*& d) +{ + while (count) + { + if (v) + { + if (count < 0x100) + { + *d++ = 0x00; + *d++ = count; + *d++ = v; + break; + } + int c_write = min(count, 0x3fff); + *d++ = 0x80; + write_w(0xc000 | c_write, d); + count -= c_write; + *d++ = v; + } + else if (count < 0x80) + { + *d++ = 0x80 | count; + count = 0; + } + else + { + int c_write = count < 0x8000 ? count : 0x7fff; + *d++ = 0x80; + write_w(c_write, d); + count -= c_write; + } + } +} + +int get_run_length(const byte* r, const byte* s_end) +{ + int count = 1; + int v = *r++; + while (r < s_end && *r++ == v) + count++; + return count; +} + +static void write40_c0(byte*& w, int count, int v) +{ + *w++ = 0; + *w++ = count; + *w++ = v; +} + +static void write40_c1(byte*& w, int count, const byte* r) +{ + *w++ = count; + memcpy(w, r, count); + w += count; +} + +static void write40_c2(byte*& w, int count) +{ + *w++ = 0x80; + write_w(count, w); +} + +static void write40_c3(byte*& w, int count, const byte* r) +{ + *w++ = 0x80; + write_w(0x8000 | count, w); + memcpy(w, r, count); + w += count; +} + +static void write40_c4(byte*& w, int count, int v) +{ + *w++ = 0x80; + write_w(0xc000 | count, w); + *w++ = v; +} + +static void write40_c5(byte*& w, int count) +{ + *w++ = 0x80 | count; +} + +static void write40_copy(byte*& w, int count, const byte* r) +{ + while (count) + { + if (count < 0x80) + { + write40_c1(w, count, r); + count = 0; + } + else + { + int c_write = count < 0x4000 ? count : 0x3fff; + write40_c3(w, c_write, r); + r += c_write; + count -= c_write; + } + } +} + +static void write40_fill(byte*& w, int count, int v) +{ + while (count) + { + if (count < 0x100) + { + write40_c0(w, count, v); + count = 0; + } + else + { + int c_write = count < 0x4000 ? count : 0x3fff; + write40_c4(w, c_write, v); + count -= c_write; + } + } +} + +static void write40_skip(byte*& w, int count) +{ + while (count) + { + if (count < 0x80) + { + write40_c5(w, count); + count = 0; + } + else + { + int c_write = count < 0x8000 ? count : 0x7fff; + write40_c2(w, c_write); + count -= c_write; + } + } +} + +static void flush_copy(byte*& w, const byte* r, const byte*& copy_from) +{ + if (copy_from) + { + write40_copy(w, r - copy_from, copy_from); + copy_from = NULL; + } +} + +int encode40(const byte* last_s, const byte* x, byte* d, int cb_s) +{ + // full compression + byte* s = new byte[cb_s]; + { + byte* a = s; + int size = cb_s; + while (size--) + *a++ = *last_s++ ^ *x++; + } + const byte* s_end = s + cb_s; + const byte* r = s; + byte* w = d; + const byte* copy_from = NULL; + while (r < s_end) + { + int v = *r; + int t = get_run_length(r, s_end); + if (!v) + { + flush_copy(w, r, copy_from); + write40_skip(w, t); + } + else if (t > 2) + { + flush_copy(w, r, copy_from); + write40_fill(w, t, v); + } + else + { + if (!copy_from) + copy_from = r; + } + r += t; + } + flush_copy(w, r, copy_from); + write40_c2(w, 0); + delete[] s; + return w - d; +} + +int encode40_y(const byte* last_r, const byte* r, byte* d, int cb_s) +{ + // run length encoding + byte* w = d; + int count = 0; + byte last = ~(*last_r ^ *r); + + while (cb_s--) + { + byte v = *last_r++ ^ *r++; + if (last == v) + count++; + else + { + write_v40(last, count, w); + count = 1; + last = v; + } + } + write_v40(last, count, w); + *w++ = 0x80; + write_w(0, w); + return w - d; +} + +int encode40_z(const byte* last_s, const byte* s, byte* d, int cb_s) +{ + // no compression + const byte* last_r = last_s; + const byte* r = s; + byte* w = d; + while (cb_s) + { + int c_write = cb_s > 0x3fff ? 0x3fff : cb_s; + cb_s -= c_write; + *w++ = 0x80; + *w++ = c_write & 0xff; + *w++ = 0x80 | c_write >> 8; + while (c_write--) + *w++ = *last_r++ ^ *r++; + } + *w++ = 0x80; + *w++ = 0x00; + *w++ = 0x00; + return w - d; +} + +int decode40(const byte* s, byte* d) +{ + /* + 0 fill 00000000 c v + 1 copy 0ccccccc + 2 skip 10000000 c 0ccccccc + 3 copy 10000000 c 10cccccc + 4 fill 10000000 c 11cccccc v + 5 skip 1ccccccc + */ + + const byte* r = s; + byte* w = d; + int count; + while (1) + { + int code = *r++; + if (code & 0x80) + { + if (count = code & 0x7f) + { + w += count; + } + else + { + count = *(uint16_t*)r; + r += 2; + code = count >> 8; + if (code & 0x80) + { + count &= 0x3fff; + if (code & 0x40) + { + code = *r++; + while (count--) + *w++ ^= code; + } + else + { + while (count--) + *w++ ^= *r++; + } + } + else + { + if (!count) + break; + w += count; + } + } + } + else if (code) + { + count = code; + while (count--) + *w++ ^= *r++; + } + else + { + count = *r++; + code = *r++; + while (count--) + *w++ ^= code; + } + } + return w - d; +} + +static void write_v80(byte v, int count, byte*& d) +{ + if (count > 3) + { + *d++ = 0xfe; + write_w(count, d); + *d++ = v; + } + else if (count) + { + *d++ = 0x80 | count; + while (count--) + *d++ = v; + } +} + +void get_same(const byte* s, const byte* r, const byte* s_end, byte*& p, int& cb_p) +{ + _asm + { + push esi + push edi + mov eax, s_end + mov ebx, s + xor ecx, ecx + mov edi, p + mov [edi], ecx + dec ebx +next_s: + inc ebx + xor edx, edx + mov esi, r + mov edi, ebx + cmp edi, esi + jnb end0 +next0: + inc edx + cmp esi, eax + jnb end_line + cmpsb + je next0 +end_line: + dec edx + cmp edx, ecx + jl next_s + mov ecx, edx + mov edi, p + mov [edi], ebx + jmp next_s +end0: + mov edi, cb_p + mov [edi], ecx + pop edi + pop esi + } +} + +static void write80_c0(byte*& w, int count, int p) +{ + *w++ = (count - 3) << 4 | p >> 8; + *w++ = p & 0xff; +} + +static void write80_c1(byte*& w, int count, const byte* r) +{ + do + { + int c_write = count < 0x40 ? count : 0x3f; + *w++ = 0x80 | c_write; + memcpy(w, r, c_write); + r += c_write; + w += c_write; + count -= c_write; + } + while (count); +} + +static void write80_c2(byte*& w, int count, int p) +{ + *w++ = 0xc0 | (count - 3); + write_w(p, w); +} + +static void write80_c3(byte*& w, int count, int v) +{ + *w++ = 0xfe; + write_w(count, w); + *w++ = v; +} + +static void write80_c4(byte*& w, int count, int p) +{ + *w++ = 0xff; + write_w(count, w); + write_w(p, w); +} + +static void flush_c1(byte*& w, const byte* r, const byte*& copy_from) +{ + if (copy_from) + { + write80_c1(w, r - copy_from, copy_from); + copy_from = NULL; + } +} + +int encode80(const byte* s, byte* d, int cb_s) +{ + // full compression + const byte* s_end = s + cb_s; + const byte* r = s; + byte* w = d; + const byte* copy_from = NULL; + while (r < s_end) + { + byte* p; + int cb_p; + int t = get_run_length(r, s_end); + get_same(s, r, s_end, p, cb_p); + if (t < cb_p && cb_p > 2) + { + flush_c1(w, r, copy_from); + if (cb_p - 3 < 8 && r - p < 0x1000) + write80_c0(w, cb_p, r - p); + else if (cb_p - 3 < 0x3e) + write80_c2(w, cb_p, p - s); + else + write80_c4(w, cb_p, p - s); + r += cb_p; + } + else + { + if (t < 3) + { + if (!copy_from) + copy_from = r; + } + else + { + flush_c1(w, r, copy_from); + write80_c3(w, t, *r); + } + r += t; + } + } + flush_c1(w, r, copy_from); + write80_c1(w, 0, NULL); + return w - d; +} + +int encode80_y(const byte* s, byte* d, int cb_s) +{ + // run length encoding + const byte* r = s; + byte* w = d; + int count = 0; + byte last = ~*r; + + while (cb_s--) + { + byte v = *r++; + if (last == v) + count++; + else + { + write_v80(last, count, w); + count = 1; + last = v; + } + + } + write_v80(last, count, w); + *w++ = 0x80; + return w - d; +} + +int decode80c(const byte image_in[], byte image_out[], int cb_in) +{ + /* + 0 copy 0cccpppp p + 1 copy 10cccccc + 2 copy 11cccccc p p + 3 fill 11111110 c c v + 4 copy 11111111 c c p p + */ + + const byte* copyp; + const byte* r = image_in; + byte* w = image_out; + int code; + int count; + while (1) + { + code = *r++; + if (~code & 0x80) + { + //bit 7 = 0 + //command 0 (0cccpppp p): copy + count = (code >> 4) + 3; + copyp = w - (((code & 0xf) << 8) + *r++); + while (count--) + *w++ = *copyp++; + } + else + { + //bit 7 = 1 + count = code & 0x3f; + if (~code & 0x40) + { + //bit 6 = 0 + if (!count) + //end of image + break; + //command 1 (10cccccc): copy + while (count--) + *w++ = *r++; + } + else + { + //bit 6 = 1 + if (count < 0x3e) + { + //command 2 (11cccccc p p): copy + count += 3; + copyp = &image_out[*(unsigned __int16*)r]; + r += 2; + while (count--) + *w++ = *copyp++; + } + else + if (count == 0x3e) + { + //command 3 (11111110 c c v): fill + count = *(unsigned __int16*)r; + r += 2; + code = *r++; + while (count--) + *w++ = byte(code); + } + else + { + //command 4 (copy 11111111 c c p p): copy + count = *(unsigned __int16*)r; + r += 2; + copyp = &image_out[*(unsigned __int16*)r]; + r += 2; + while (count--) + *w++ = *copyp++; + } + } + } + } + assert(cb_in == r - image_in); + return (w - image_out); +} + +int decode80(const byte image_in[], byte image_out[]) +{ + int cb_out; + /* + 0 copy 0cccpppp p + 1 copy 10cccccc + 2 copy 11cccccc p p + 3 fill 11111110 c c v + 4 copy 11111111 c c p p + */ + + _asm + { + push esi + push edi + mov ax, ds + mov es, ax + mov esi, image_in + mov edi, image_out +next0: + xor eax, eax + lodsb + mov ecx, eax + test eax, 0x80 + jnz c1c + shr ecx, 4 + add ecx, 3 + and eax, 0xf + shl eax, 8 + lodsb + mov edx, esi + mov esi, edi + sub esi, eax + jmp copy_from_destination +c1c: + and ecx, 0x3f + test eax, 0x40 + jnz c2c + or ecx, ecx + jz end0 + jmp copy_from_source +c2c: + xor eax, eax + lodsw + cmp ecx, 0x3e + je c3 + ja c4 + mov edx, esi + mov esi, image_out + add esi, eax + add ecx, 3 + jmp copy_from_destination +c3: + mov ecx, eax + lodsb + rep stosb + jmp next0 +c4: + mov ecx, eax + lodsw + mov edx, esi + mov esi, image_out + add esi, eax +copy_from_destination: + rep movsb + mov esi, edx + jmp next0 +copy_from_source: + rep movsb + jmp next0 +end0: + sub edi, image_out + mov cb_out, edi + pop edi + pop esi + } + return cb_out; +} + +int decode80r(const byte image_in[], byte image_out[]) +{ + int cb_out; + /* + 0 copy 0cccpppp p + 1 copy 10cccccc + 2 copy 11cccccc p p + 3 fill 11111110 c c v + 4 copy 11111111 c c p p + */ + + _asm + { + push esi + push edi + mov ax, ds + mov es, ax + mov esi, image_in + mov edi, image_out +next0: + xor eax, eax + lodsb + mov ecx, eax + test eax, 0x80 + jnz c1c + shr ecx, 4 + add ecx, 3 + and eax, 0xf + shl eax, 8 + lodsb + mov edx, esi + mov esi, edi + sub esi, eax + jmp copy_from_destination +c1c: + and ecx, 0x3f + test eax, 0x40 + jnz c2c + or ecx, ecx + jz end0 + jmp copy_from_source +c2c: + xor eax, eax + lodsw + cmp ecx, 0x3e + je c3 + ja c4 + mov edx, esi + mov esi, edi + sub esi, eax + add ecx, 3 + jmp copy_from_destination +c3: + mov ecx, eax + lodsb + rep stosb + jmp next0 +c4: + mov ecx, eax + lodsw + mov edx, esi + mov esi, edi + sub esi, eax +copy_from_destination: + rep movsb + mov esi, edx + jmp next0 +copy_from_source: + rep movsb + jmp next0 +end0: + sub edi, image_out + mov cb_out, edi + pop edi + pop esi + } + return cb_out; +} + +int decode2(const byte* s, byte* d, int cb_s, const byte* reference_palet) +{ + const byte* r = s; + const byte* r_end = s + cb_s; + byte* w = d; + while (r < r_end) + { + int v = *r++; + if (v) + *w++ = v; + else + { + v = *r++; + memset(w, 0, v); + w += v; + } + } + if (reference_palet) + apply_rp(d, w - d, reference_palet); + return w - d; +} + +int decode3(const byte* s, byte* d, int cx, int cy) +{ + const byte* r = s; + byte* w = d; + for (int y = 0; y < cy; y++) + { + int count = *reinterpret_cast(r) - 2; + r += 2; + int x = 0; + while (count--) + { + int v = *r++; + if (v) + { + x++; + *w++ = v; + } + else + { + count--; + v = *r++; + if (x + v > cx) + v = cx - x; + x += v; + while (v--) + *w++ = 0; + } + } + } + return w - d; +} + +int encode3(const byte* s, byte* d, int cx, int cy) +{ + const byte* r = s; + byte* w = d; + for (int y = 0; y < cy; y++) + { + const byte* r_end = r + cx; + byte* w_line = w; + w += 2; + while (r < r_end) + { + + int v = *r; + *w++ = v; + if (v) + r++; + else + { + int c = get_run_length(r, r_end); + if (c > 0xff) + c = 0xff; + r += c; + *w++ = c; + } + } + *reinterpret_cast(w_line) = w - w_line; + } + return w - d; +} + +Cvirtual_binary encode64(data_ref s) +{ + Cvirtual_binary d; + const byte* r = s.data(); + int cb_s = s.size(); + byte* w = d.write_start(s.size() << 1); + while (cb_s) + { + int c1 = *r++; + *w++ = encode64_table[c1>>2]; + + int c2 = --cb_s == 0 ? 0 : *r++; + *w++ = encode64_table[((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4)]; + if (cb_s == 0) + { + *w++ = '='; + *w++ = '='; + break; + } + + int c3 = --cb_s == 0 ? 0 : *r++; + + *w++ = encode64_table[((c2 & 0xf) << 2) | ((c3 & 0xc0) >> 6)]; + if (cb_s == 0) + { + *w++ = '='; + break; + } + --cb_s; + *w++ = encode64_table[c3 & 0x3f]; + } + d.set_size(w - d.data()); + return d; +} + +Cvirtual_binary decode64(data_ref s) +{ + Cvirtual_binary d; + const byte* r = s.data(); + byte* w = d.write_start(s.size() << 1); + while (*r) + { + int c1 = *r++; + if (decode64_table[c1] == -1) + return Cvirtual_binary(); + int c2 = *r++; + if (decode64_table[c2] == -1) + return Cvirtual_binary(); + int c3 = *r++; + if (c3 != '=' && decode64_table[c3] == -1) + return Cvirtual_binary(); + int c4 = *r++; + if (c4 != '=' && decode64_table[c4] == -1) + return Cvirtual_binary(); + *w++ = (decode64_table[c1] << 2) | (decode64_table[c2] >> 4); + if (c3 == '=') + break; + *w++ = ((decode64_table[c2] << 4) & 0xf0) | (decode64_table[c3] >> 2); + if (c4 == '=') + break; + *w++ = ((decode64_table[c3] << 6) & 0xc0) | decode64_table[c4]; + } + d.set_size(w - d.data()); + return d; +} + +static void write5_count(byte*& w, int count) +{ + while (count > 255) + { + *w++ = 0; + count -= 255; + } + *w++ = count; +} + +static void write5_c0(byte*& w, int count, const byte* r, byte* small_copy) +{ + if (count < 4 && !small_copy) + count = count; + if ((count < 4 || count > 7) && small_copy) + { + int small_count = min(count, 3); + *small_copy |= small_count; + memcpy(w, r, small_count); + r += small_count; + w += small_count; + count -= small_count; + } + if (count) + { + assert(count > 3); + if (count > 18) + { + *w++ = 0; + write5_count(w, count - 18); + } + else + *w++ = count - 3; + memcpy(w, r, count); + w += count; + } +} + +static void write5_c1(byte*& w, int count, int p) +{ + assert(count > 2); + assert(p >= 0); + assert(p < 32768); + count -= 2; + if (count > 7) + { + *w++ = 0x10 | (p >> 11) & 8; + write5_count(w, count - 7); + } + else + *w++ = 0x10 | (p >> 11) & 8 | count; + write_w((p << 2) & 0xfffc, w); +} + +static void write5_c2(byte*& w, int count, int p) +{ + assert(count > 2); + assert(p > 0); + assert(p <= 16384); + count -= 2; + p--; + if (count > 31) + { + *w++ = 0x20; + write5_count(w, count - 31); + } + else + *w++ = 0x20 | count; + write_w(p << 2, w); +} + +static void write5_c3(byte*& w, int count, int p) +{ + assert(count > 1); + assert(count < 7); + assert(p > 0); + assert(p <= 2048); + count -= 2; + p--; + *w++ = (count + 1) << 5 | (p & 7) << 2; + *w++ = p >> 3; +} + +int get_count(const byte*& r) +{ + int count = -255; + int v; + do + { + count += 255; + v = *r++; + } + while (!v); + return count + v; +} + +static void flush_c0(byte*& w, const byte* r, const byte*& copy_from, byte* small_copy, bool start) +{ + if (copy_from) + { + int count = r - copy_from; + /* + if (start) + { + int small_count = count; + if (count > 241) + small_count = 238; + else if (count > 238) + small_count = count - 4; + *w++ = small_count + 17; + memcpy(w, copy_from, small_count); + copy_from += small_count; + w += small_count; + count -= small_count; + } + */ + if (count) + write5_c0(w, count, copy_from, small_copy); + copy_from = NULL; + } +} + +int encode5s(const byte* s, byte* d, int cb_s) +{ + lzo_init(); + static Cvirtual_binary t; + lzo_uint cb_d; + if (LZO_E_OK != lzo1x_1_compress(s, cb_s, d, &cb_d, t.write_start(LZO1X_1_MEM_COMPRESS))) + cb_d = 0; + return cb_d; +} + +int encode5s_z(const byte* s, byte* d, int cb_s) +{ + // no compression + const byte* r = s; + const byte* r_end = s + cb_s; + byte* w = d; + write5_c0(w, cb_s, r, NULL); + r += cb_s; + write5_c1(w, 3, 0); + assert(cb_s == r - s); + return w - d; +} + +int decode5s(const byte* s, byte* d, int cb_s) +{ + lzo_init(); + lzo_uint cb_d; + if (LZO_E_OK != lzo1x_decompress(s, cb_s, d, &cb_d, NULL)) + return 0; + return cb_d; + /* + 0 copy 0000cccc + 1 copy 0001pccc ppppppzz p + 2 copy 001ccccc ppppppzz p + 3 copy cccpppzz p + */ + + const byte* c; + const byte* r = s; + byte* w = d; + int code; + int count; + code = *r; + if (code > 17) + { + r++; + count = code - 17; + while (count--) + *w++ = *r++; + } + while (1) + { + code = *r++; + if (code & 0xf0) + { + if (code & 0xc0) + { + count = (code >> 5) - 1; + c = w - (code >> 2 & 7); + c -= *r++ << 3; + c--; + } + else if (code & 0x20) + { + count = code & 0x1f; + if (!count) + count = get_count(r) + 31; + c = w - (read_w(r) >> 2); + c--; + } + else + { + c = w - ((code & 8) << 11); + count = code & 7; + if (!count) + count = get_count(r) + 7; + c -= read_w(r) >> 2; + if (c == w) + break; + } + count += 2; + while (count--) + { + if (*w != *c) + *w = *c; + w++; + c++; + } + count = *(r - 2) & 3; + while (count--) + { + if (*w != *r) + *w = *r; + w++; + r++; + } + } + else + { + count = code ? code + 3: get_count(r) + 18; + while (count--) + { + if (*w != *r) + *w = *r; + w++; + r++; + } + } + } + assert(cb_s == r - s); + return w - d; +} + +int encode5(const byte* s, byte* d, int cb_s, int format) +{ + const byte* r = s; + const byte* r_end = s + cb_s; + byte* w = d; + while (r < r_end) + { + int cb_section = min(r_end - r, 8192); + t_pack_section_header& header = *reinterpret_cast(w); + w += sizeof(t_pack_section_header); + w += header.size_in = format == 80 ? encode80(r, w, cb_section) : encode5s(r, w, cb_section); + r += header.size_out = cb_section; + } + return w - d; +} + +int decode5(const byte* s, byte* d, int cb_s, int format) +{ + const byte* r = s; + const byte* r_end = s + cb_s; + byte* w = d; + while (r < r_end) + { + const t_pack_section_header& header = *reinterpret_cast(r); + r += sizeof(t_pack_section_header); + if (format == 80) + decode80(r, w); + else + decode5s(r, w, header.size_in); + r += header.size_in; + w += header.size_out; + } + return w - d; +} diff --git a/3rdParty/xcc/misc/shp_decode.h b/3rdParty/xcc/misc/shp_decode.h new file mode 100644 index 0000000..df17b2e --- /dev/null +++ b/3rdParty/xcc/misc/shp_decode.h @@ -0,0 +1,39 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include + +int decode2(const byte* s, byte* d, int cb_s, const byte* reference_palet); +int decode3(const byte* s, byte* d, int cx, int cy); +int encode3(const byte* s, byte* d, int cx, int cy); +int decode5(const byte* s, byte* d, int cb_s, int format); +int encode5(const byte* s, byte* d, int cb_s, int format); +int decode5s(const byte* s, byte* d, int cb_s); +int encode5s(const byte* s, byte* d, int cb_s); +int decode64(const byte* s, byte* d); +Cvirtual_binary decode64(data_ref); +Cvirtual_binary encode64(data_ref); +int decode40(const byte image_in[], byte image_out[]); +int decode80(const byte image_in[], byte image_out[]); +int decode80c(const byte image_in[], byte image_out[], int cb_in); +int decode80r(const byte image_in[], byte image_out[]); +int encode40(const byte* last_s, const byte* s, byte* d, int cb_s); +int encode80(const byte* s, byte* d, int cb_s); +int get_run_length(const byte* r, const byte* s_end); diff --git a/3rdParty/xcc/misc/shp_ts_file.cpp b/3rdParty/xcc/misc/shp_ts_file.cpp new file mode 100644 index 0000000..db60a92 --- /dev/null +++ b/3rdParty/xcc/misc/shp_ts_file.cpp @@ -0,0 +1,668 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "shp_ts_file.h" + +#include "image_file.h" +#include "shp_decode.h" +#include "string_conversion.h" +#ifndef XCC_MINIMAL_BUILD +#include "xcc_log.h" +#endif + +class Cshp_ts_decoder : public Cvideo_decoder +{ +public: + int cb_pixel() const + { + return m_f.cb_pixel(); + } + + int cf() const + { + return m_f.cf(); + } + + int cx() const + { + return m_f.cx(); + } + + int cy() const + { + return m_f.cy(); + } + + int decode(void* d0) + { + if (m_frame_i >= cf()) + return 1; + byte* d = reinterpret_cast(d0); + Cvirtual_binary s; + const int cx = m_f.get_cx(m_frame_i); + const int cy = m_f.get_cy(m_frame_i); + const byte* r; + if (m_f.is_compressed(m_frame_i)) + { + decode3(m_f.get_image(m_frame_i), s.write_start(cx * cy), cx, cy); + r = s.data(); + } + else + r = m_f.get_image(m_frame_i); + memset(d, 0, cb_image()); + byte* w = d + m_f.get_x(m_frame_i) + Cshp_ts_decoder::cx() * m_f.get_y(m_frame_i); + for (int y = 0; y < cy; y++) + { + memcpy(w, r, cx); + r += cx; + w += Cshp_ts_decoder::cx(); + } + m_frame_i++; + return 0; + } + + const t_palet_entry* palet() const + { + return m_palet; + } + + int seek(int f) + { + m_frame_i = f; + return 0; + } + + Cshp_ts_decoder(const Cshp_ts_file& f, const t_palet_entry* palet) + { + m_f.load(f); + m_frame_i = 0; + memcpy(m_palet, palet, sizeof(t_palet)); + } +private: + Cshp_ts_file m_f; + int m_frame_i; + t_palet m_palet; +}; + +Cvideo_decoder* Cshp_ts_file::decoder(const t_palet_entry* palet) +{ + return new Cshp_ts_decoder(*this, palet); +} + +bool Cshp_ts_file::is_valid() const +{ + const t_shp_ts_header& h = header(); + int size = get_size(); + if (sizeof(t_shp_ts_header) > size || + h.zero || + h.c_images < 1 || h.c_images > 10000 || + sizeof(t_shp_ts_header) + get_cb_index() > size) + return false; + for (int i = 0; i < min(cf(), 1000); i++) + { + const t_shp_ts_image_header& image_header = *get_image_header(i); + if (!image_header.cx && !image_header.cy && !image_header.offset) + continue; + if (!image_header.cx || image_header.x + image_header.cx > h.cx || + !image_header.cy || image_header.y + image_header.cy > h.cy || + image_header.zero || + image_header.offset < sizeof(t_shp_ts_header) + get_cb_index()) + return false; + if (is_compressed(i)) + { + if (image_header.offset > size) + return false; + } + else + { + if (image_header.offset + image_header.cx * image_header.cy > size) + return false; + } + } + return true; +} + +int get_ofs(int x, int y, int cx, int cy) +{ + return x + cx * y; +} + +#ifndef XCC_MINIMAL_BUILD +int Cshp_ts_file::extract_as_pcx(const Cfname& name, t_file_type ft, const t_palet _palet, bool combine_shadows) const +{ + t_palet palet; + convert_palet_18_to_24(_palet, palet); + int error = 0; + const int global_cx = cx(); + const int global_cy = cy(); + const int c_images = cf(); + if (combine_shadows && ~c_images & 1) + { + bool shadow = false; + byte* image = new byte[global_cx * global_cy]; + byte* d = new byte[global_cx * global_cy * c_images >> 1]; + byte* w = d; + for (int i = 0; i < c_images; i++) + { + const int cx = get_cx(i); + const int cy = get_cy(i); + const byte* r; + if (is_compressed(i)) + { + decode3(get_image(i), image, cx, cy); + r = image; + } + else + r = get_image(i); + if (!shadow) + { + if (i == c_images >> 1) + { + shadow = true; + w = d; + } + else + memset(w, 0, global_cx * global_cy); + } + byte* w_start = w; + w += get_x(i) + global_cx * get_y(i); + for (int y = 0; y < cy; y++) + { + if (shadow) + { + for (int x = 0; x < cx; x++) + { + if (*r++) + w[x] = 4; + } + } + else + { + memcpy(w, r, cx); + r += cx; + } + w += global_cx; + } + if (shadow) + { + Cfname t = name; + t.set_title(name.get_ftitle() + " " + nwzl(4, i - (c_images >> 1))); + error = image_file_write(t, ft, w_start, palet, global_cx, global_cy); + if (error) + break; + } + w = w_start + global_cx * global_cy; + } + delete[] d; + delete[] image; + } + else + { + byte* image = new byte[global_cx * global_cy]; + byte* s = new byte[global_cx * global_cy]; + for (int i = 0; i < c_images; i++) + { + const int cx = get_cx(i); + const int cy = get_cy(i); + const byte* r; + if (is_compressed(i)) + { + decode3(get_image(i), image, cx, cy); + r = image; + } + else + r = get_image(i); + memset(s, 0, global_cx * global_cy); + byte* w = s + get_x(i) + global_cx * get_y(i); + for (int y = 0; y < cy; y++) + { + memcpy(w, r, cx); + r += cx; + w += global_cx; + } + // xcc_log::write_line("" + name.get_ftitle() + ""); + Cfname t = name; + t.set_title(name.get_ftitle() + " " + nwzl(4, i)); + error = image_file_write(t, ft, s, palet, global_cx, global_cy); + if (error) + break; + } + delete[] s; + delete[] image; + } + return error; +} + +Cvirtual_image Cshp_ts_file::extract_as_pcx_single(const t_palet _palet, bool combine_shadows) const +{ + t_palet palet; + convert_palet_18_to_24(_palet, palet); + const int global_cx = cx(); + const int global_cy = cy(); + int c_images = cf(); + combine_shadows &= ~c_images & 1; + if (combine_shadows) + c_images >>= 1; + const int cblocks_x = min(c_images, 1024 / global_cx); + const int cblocks_y = (c_images + cblocks_x - 1) / cblocks_x; + int cx_s = cblocks_x * global_cx; + int cy_s = cblocks_y * global_cy; + Cvirtual_binary image; + Cvirtual_binary s; + memset(s.write_start(cx_s * cy_s), 0, cx_s * cy_s); + if (combine_shadows) + { + c_images <<= 1; + bool shadow = false; + for (int i = 0; i < c_images; i++) + { + const int cx = get_cx(i); + const int cy = get_cy(i); + const byte* r; + if (is_compressed(i)) + { + decode3(get_image(i), image.write_start(global_cx * global_cy), cx, cy); + r = image.data(); + } + else + r = get_image(i); + if (!shadow && i == c_images >> 1) + shadow = true; + int j = i % (c_images >> 1); + byte* w = s.data_edit() + get_ofs(j % cblocks_x * global_cx + get_x(i), j / cblocks_x * global_cy + get_y(i), cx_s, cy_s); + for (int y = 0; y < cy; y++) + { + if (shadow) + { + for (int x = 0; x < cx; x++) + { + if (*r++) + w[x] = 4; + } + } + else + { + memcpy(w, r, cx); + r += cx; + } + w += cx_s; + } + } + } + else + { + for (int i = 0; i < c_images; i++) + { + const int cx = get_cx(i); + const int cy = get_cy(i); + const byte* r; + if (is_compressed(i)) + { + decode3(get_image(i), image.write_start(global_cx * global_cy), cx, cy); + r = image.data(); + } + else + r = get_image(i); + byte* w = s.data_edit() + get_ofs(i % cblocks_x * global_cx + get_x(i), i / cblocks_x * global_cy + get_y(i), cx_s, cy_s); + for (int y = 0; y < cy; y++) + { + memcpy(w, r, cx); + r += cx; + w += cx_s; + } + } + } + return Cvirtual_image(s, cx_s, cy_s, 1, palet); +} + +void shp_split_frames(Cvirtual_image& image, int cblocks_x, int cblocks_y) +{ + int cx = image.cx() / cblocks_x; + int cy = image.cy() / cblocks_y; + int cx_d = image.cx() / cblocks_x; + int cy_d = image.cy() * cblocks_x; + byte* d = new byte[cx_d * cy_d]; + byte* w = d; + const byte* r_line = image.image(); + for (int yb = 0; yb < cblocks_y; yb++) + { + for (int xb = 0; xb < cblocks_x; xb++) + { + const byte* r = r_line + cx * xb; + for (int y = 0; y < cy; y++) + { + memcpy(w, r, cx); + r += image.cx(); + w += cx_d; + } + } + r_line += image.cx() * cy; + } + image.load(d, cx_d, cy_d, image.cb_pixel(), image.palet()); + delete[] d; +} + +void shp_split_shadows(Cvirtual_image& image) +{ + int cx = image.cx(); + int cy = image.cy(); + int count = cx * cy; + byte* d = new byte[count << 1]; + memcpy(d, image.image(), count); + byte* r = d; + byte* w = d + count; + while (count--) + { + byte& v = *r++; + if (v == 4) + { + v = 0; + *w++ = 1; + } + else + *w++ = 0; + } + image.load(d, cx, cy << 1, image.cb_pixel(), image.palet()); + delete[] d; +} +#endif + +/* +void shp_xor_decode_frames(Cvirtual_image& image, int c_frames) +{ + int cx = image.cx(); + int cy = image.cy() / c_frames; + int count = cx * cy * (c_frames - 1); + const byte* r = image.image(); + byte* w = image.image_edit() + cx * cy; + while (count--) + { + *w++ ^= *r++; + } +} + +void shp_xor_encode_frames(Cvirtual_image& image, int c_frames) +{ + int cx = image.cx(); + int cy = image.cy() / c_frames; + int count = cx * cy * c_frames; + byte* w = image.image_edit() + count; + count -= cx * cy; + const byte* r = image.image() + count; + while (count--) + { + *--w ^= *--r; + } +} +*/ + +static int get_left_margin(const byte* r, int cx) +{ + int c = 0; + while (cx-- && !*r++) + c++; + return c; +} + +static int get_right_margin(const byte* r, int cx) +{ + int c = 0; + while (cx-- && !*--r) + c++; + return c; +} + +static int encode4_line(const byte* r, byte* d, int cx) +{ + const byte* s_end = r + cx; + byte* w = d; + while (r < s_end) + { + int v = *w++ = *r++; + if (!v) + { + int c = min(get_run_length(r - 1, s_end), 0xff); + r += c - 1; + *w++ = c; + } + } + return w - d; +} + +static int decode4_line_size(const byte*& r, int cx) +{ + int w = 0; + while (cx--) + { + w++; + if (!*r++) + { + cx -= *r++ - 1; + w++; + } + } + return w; +} + +static int decode4_line(const byte* s, byte*& w, int cx) +{ + const byte* r = s; + while (cx--) + { + if (!(*w++ = *r++)) + cx -= (*w++ = *r++) - 1; + } + return r - s; +} + +static int encode4(const byte* s, byte* d, int cx, int cy) +{ + const byte* s_end = s + cx * cy; + const byte* r = s; + byte* w = d; + for (int y = 0; y < cy; y++) + { + int lm = min(get_left_margin(r, cx), 0xff); + int rm = min(get_right_margin(r + cx, cx - lm), 0xff); + *w++ = lm; + *w++ = rm; + w += encode4_line(r + lm, w, cx - lm - rm); + r += cx; + } + return w - d; +} + +static int decode4_size(const byte*& r, int cx, int cy) +{ + int w = 0; + for (int y = 0; y < cy; y++) + { + int lm = *r++; + int rm = *r++; + w += 2; + if (lm) + w += 2; + w += decode4_line_size(r, cx - lm - rm); + if (rm) + w += 2; + } + return w; +} + +static int decode4(const byte* s, byte*& w, int cx, int cy) +{ + const byte* r = s; + for (int y = 0; y < cy; y++) + { + int lm = *r++; + int rm = *r++; + byte* w_line = w; + w += 2; + if (lm) + { + *w++ = 0; + *w++ = lm; + } + r += decode4_line(r, w, cx - lm - rm); + if (rm) + { + *w++ = 0; + *w++ = rm; + } + *reinterpret_cast(w_line) = w - w_line; + } + return r - s; +} + +struct t_shp4_header +{ + unsigned __int16 cx; + unsigned __int16 cy; + unsigned __int16 c_frames; +}; + +struct t_shp4_frame_header +{ + unsigned __int8 lm; + unsigned __int8 rm; + unsigned __int8 tm; + unsigned __int8 bm; +}; + +int shp_encode4(const Cshp_ts_file& f, byte* d) +{ + const int global_cx = f.cx(); + const int global_cy = f.cy(); + const int c_frames = f.cf(); + + byte* w = d; + t_shp4_header& header = *reinterpret_cast(w); + header.cx = global_cx; + header.cy = global_cy; + header.c_frames = c_frames; + w += sizeof(t_shp4_header); + + for (int i = 0; i < c_frames; i++) + { + const t_shp_ts_image_header& image_header = *f.get_image_header(i); + + const int cx = image_header.cx; + const int cy = image_header.cy; + + t_shp4_frame_header& frame_header = *reinterpret_cast(w); + if (image_header.cx && image_header.cy) + { + frame_header.lm = image_header.x; + frame_header.tm = image_header.y; + } + else + { + frame_header.lm = min(global_cx, 0xff); + frame_header.tm = min(global_cy, 0xff); + } + if (global_cx - frame_header.lm - cx > 0xff + || global_cy - frame_header.tm - cy > 0xff) + return 0; + frame_header.rm = global_cx - frame_header.lm - cx; + frame_header.bm = global_cy - frame_header.tm - cy; + w += sizeof(t_shp4_frame_header); + + if (f.is_compressed(i)) + { + Cvirtual_binary image; + decode3(f.get_image(i), image.write_start(cx * cy), cx, cy); + w += encode4(image.data(), w, cx, cy); + } + else + w += encode4(f.get_image(i), w, cx, cy); + } + return w - d; +} + +int shp_decode4_size(const byte* s) +{ + Cvirtual_binary d; + const byte* r = s; + const t_shp4_header& s_header = *reinterpret_cast(r); + const int global_cx = s_header.cx; + const int global_cy = s_header.cy; + const int c_frames = s_header.c_frames; + r += sizeof(t_shp4_header); + int w = 0; + for (int i = 0; i < c_frames; i++) + { + const t_shp4_frame_header& frame_header = *reinterpret_cast(r); + int x = frame_header.lm; + int y = frame_header.tm; + int cx = global_cx - x - frame_header.rm; + int cy = global_cy - y - frame_header.bm; + r += sizeof(t_shp4_frame_header); + if (cy) + w += decode4_size(r, cx, cy); + w = w + 7 & ~7; + } + return w + + sizeof(t_shp_ts_header) + + c_frames * sizeof(t_shp_ts_image_header); +} + +Cvirtual_binary shp_decode4(const byte* s, int cb_d) +{ + Cvirtual_binary d; + const byte* r = s; + const t_shp4_header& s_header = *reinterpret_cast(r); + const int global_cx = s_header.cx; + const int global_cy = s_header.cy; + const int c_frames = s_header.c_frames; + r += sizeof(t_shp4_header); + byte* w = d.write_start(cb_d ? cb_d : Cshp_ts_file::get_max_size(global_cx, global_cy, c_frames)); + t_shp_ts_header& header = *reinterpret_cast(w); + header.zero = 0; + header.cx = global_cx; + header.cy = global_cy; + header.c_images = c_frames; + w += sizeof(t_shp_ts_header); + byte* w1 = w + c_frames * sizeof(t_shp_ts_image_header); + for (int i = 0; i < c_frames; i++) + { + const t_shp4_frame_header& frame_header = *reinterpret_cast(r); + int x = frame_header.lm; + int y = frame_header.tm; + int cx = global_cx - x - frame_header.rm; + int cy = global_cy - y - frame_header.bm; + r += sizeof(t_shp4_frame_header); + t_shp_ts_image_header& image_header = *reinterpret_cast(w); + image_header.x = x; + image_header.y = y; + image_header.cx = cx; + image_header.cy = cy; + image_header.compression = 3; + image_header.unknown = 0; + image_header.zero = 0; + image_header.offset = w1 - d.data(); + w += sizeof(t_shp_ts_image_header); + if (cy) + r += decode4(r, w1, cx, cy); + else + image_header.offset = 0; + w1 = d.data_edit() + (w1 - d.data() + 7 & ~7); + } + assert(!cb_d || d.size() == w1 - d.data()); + return cb_d ? d : Cvirtual_binary(d.data(), w1 - d.data()); +} diff --git a/3rdParty/xcc/misc/shp_ts_file.h b/3rdParty/xcc/misc/shp_ts_file.h new file mode 100644 index 0000000..76261cd --- /dev/null +++ b/3rdParty/xcc/misc/shp_ts_file.h @@ -0,0 +1,117 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "cc_structures.h" +#include "fname.h" +#include "palet.h" +#include "video_file.h" +#include "virtual_image.h" + +class Cshp_ts_file : public Cvideo_file +{ +public: + Cvideo_decoder* decoder(const t_palet_entry*); +#ifndef XCC_MINIMAL_BUILD + int extract_as_pcx(const Cfname& name, t_file_type ft, const t_palet palet, bool combine_shadows = false) const; + Cvirtual_image extract_as_pcx_single(const t_palet _palet, bool combine_shadows = false) const; +#endif + bool is_valid() const; + + int cb_pixel() const + { + return 1; + } + + int cf() const + { + return header().c_images; + } + + int cx() const + { + return header().cx; + } + + int cy() const + { + return header().cy; + } + + int get_x(int i) const + { + return get_image_header(i)->x; + } + + int get_y(int i) const + { + return get_image_header(i)->y; + } + + int get_cx(int i) const + { + return get_image_header(i)->cx; + } + + int get_cy(int i) const + { + return get_image_header(i)->cy; + } + + int get_cb_index() const + { + return sizeof(t_shp_ts_image_header) * cf(); + } + + bool is_compressed(int i) const + { + return get_image_header(i)->compression & 2; + } + + const t_shp_ts_image_header* get_image_header(int i) const + { + return reinterpret_cast(data() + sizeof(t_shp_ts_header) + sizeof(t_shp_ts_image_header) * i); + } + + int get_offset(int i) const + { + return get_image_header(i)->offset; + } + + const byte* get_image(int i) const + { + return data() + get_offset(i); + } + + static int get_max_size(int cx, int cy, int c_images) + { + return sizeof(t_shp_ts_header) + (sizeof(t_shp_ts_image_header) + (2 * (cx + 1) * cy + 7 & ~7)) * c_images; + } +}; + +int shp_decode4_size(const byte* s); +Cvirtual_binary shp_decode4(const byte* s, int cb_d); +int shp_encode4(const Cshp_ts_file& f, byte* d); + +#ifndef XCC_MINIMAL_BUILD +void shp_split_frames(Cvirtual_image& image, int cblocks_x, int cblocks_y); +void shp_split_shadows(Cvirtual_image& image); +void shp_xor_decode_frames(Cvirtual_image& image, int c_frames); +void shp_xor_encode_frames(Cvirtual_image& image, int c_frames); +#endif diff --git a/3rdParty/xcc/misc/stdafx.h b/3rdParty/xcc/misc/stdafx.h new file mode 100644 index 0000000..de008af --- /dev/null +++ b/3rdParty/xcc/misc/stdafx.h @@ -0,0 +1,18 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + diff --git a/3rdParty/xcc/misc/string_conversion.cpp b/3rdParty/xcc/misc/string_conversion.cpp new file mode 100644 index 0000000..e1c1eff --- /dev/null +++ b/3rdParty/xcc/misc/string_conversion.cpp @@ -0,0 +1,266 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "string_conversion.h" + +#include + +using namespace std; + +int a2ip(const string& s) +{ + int r = 0; + int l = 0; + for (int i = 0; i < 3; i++) + { + int c = s.find('.', l); + r = r << 8 | atoi(s.substr(l, c - l).c_str()); + l = c + 1; + } + r = r << 8 | atoi(s.substr(l).c_str()); + return r; +} + +string ip2a(int v) +{ + return n(v >> 24 & 0xff) + '.' + n(v >> 16 & 0xff) + '.' + n(v >> 8 & 0xff) + '.' + n(v & 0xff); +} + +int get_net_mask(int v) +{ + if (v & 0x80000000) + return 0xffffff00; + if (v & 0x40000000) + return 0xffff0000; + return 0xff000000; +} + +int get_net_part(int v) +{ + return v & get_net_mask(v); +} + +bool atob(string s) +{ + return s == "true" || s == "yes"; +} + +string btoa(bool v) +{ + return v ? "yes" : "no"; +} + +string n(unsigned int v) +{ + return to_string(v); +} + +string n(int v) +{ + return to_string(v); +} + +string n(long long v) +{ + return to_string(v); +} + +string n(unsigned long long v) +{ + return to_string(v); +} + +string swsl(int l, string s) +{ + while (s.size() < l) + s = ' ' + s; + return s; +} + +string swsr(int l, string s) +{ + while (s.size() < l) + s += ' '; + return s; +} + +string nwzl(int l, unsigned int v) +{ + string s = n(v); + while (s.size() < l) + s = '0' + s; + return s; +} + +string nwsl(int l, unsigned int v) +{ + return swsl(l, n(v)); +} + +string nh(int l, __int64 v) +{ + string s; + int w; + while (l) + { + w = v & 0xf; + if (w > 9) + w += 7; + s = char(w + 48) + s; + v >>= 4; + l--; + } + return s; +} + +string nwp(int l, unsigned int v) +{ + string r; + string s = n(v); + while (1) + { + int l = s.size(); + if (l > 3) + { + r = '.' + s.substr(l - 3, 3) + r; + s.erase(l - 3, 3); + } + else + { + r = s + r; + break; + } + + } + return swsl(l, r); +} + +void split_key(const string& key, string& name, string& value) +{ + size_t i = key.find('='); + if (i == string::npos) + { + name = key; + value.erase(); + } + else + { + name = key.substr(0, i); + value = key.substr(i + 1); + } +} + +string tabs2spaces(const string& v) +{ + string r; + for (size_t i = 0; i < v.size(); i++) + { + char c = v[i]; + if (c == '\t') + { + do + r += ' '; + while (r.size() & 3); + } + else + r += c; + } + return r; +} + +string time2a(time_t v) +{ + char b[20]; + const tm* date = gmtime(&v); + if (date) + sprintf(b, "%04d-%02d-%02d %02d:%02d:%02d", date->tm_year + 1900, date->tm_mon + 1, date->tm_mday, date->tm_hour, date->tm_min, date->tm_sec); + else + *b = 0; + return b; +} + +string js_encode(const string& v) +{ + string r; + for (size_t i = 0; i < v.size(); i++) + { + switch (v[i]) + { + case '<': + r += "<"; + break; + case '\"': + case '\'': + case '\\': + r += '\\'; + default: + r += v[i]; + } + } + return r; +} + +string trim_field(const string& v) +{ + string r; + bool copy_white = false; + for (size_t i = 0; i < v.size(); i++) + { + if (isspace(v[i])) + copy_white = true; + else + { + if (copy_white) + { + if (!r.empty()) + r += ' '; + copy_white = false; + } + r += v[i]; + } + } + return r; +} + +string trim_text(const string& v) +{ + string r; + bool copy_white = false; + for (size_t i = 0; i < v.size(); ) + { + int p = v.find('\n', i); + if (p == string::npos) + p = v.size(); + string line = trim_field(v.substr(i, p - i)); + if (line.empty()) + copy_white = true; + else + { + if (copy_white) + { + if (!r.empty()) + r += '\n'; + copy_white = false; + } + r += line + '\n'; + } + i = p + 1; + } + return r; +} diff --git a/3rdParty/xcc/misc/string_conversion.h b/3rdParty/xcc/misc/string_conversion.h new file mode 100644 index 0000000..8271255 --- /dev/null +++ b/3rdParty/xcc/misc/string_conversion.h @@ -0,0 +1,41 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include + +int a2ip(const std::string&); +std::string ip2a(int); +int get_net_mask(int); +int get_net_part(int); +bool atob(std::string); +std::string btoa(bool); +std::string js_encode(const std::string&); +std::string n(long long); +std::string swsl(int l, std::string); +std::string swsr(int l, std::string); +std::string nwp(int l, unsigned int); +std::string nwsl(int l, unsigned int); +std::string nwzl(int l, unsigned int); +std::string nh(int l, long long v); +void split_key(const std::string& key, std::string& name, std::string& value); +std::string tabs2spaces(const std::string&); +std::string time2a(time_t); +std::string trim_field(const std::string&); +std::string trim_text(const std::string&); diff --git a/3rdParty/xcc/misc/tmp_file.h b/3rdParty/xcc/misc/tmp_file.h new file mode 100644 index 0000000..da7334e --- /dev/null +++ b/3rdParty/xcc/misc/tmp_file.h @@ -0,0 +1,56 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include +#include + +class Ctmp_file : public Ccc_file_sh +{ +public: + bool is_valid() const + { + const t_tmp_header& h = header(); + int size = get_size(); + return !(sizeof(t_tmp_header) > size || + h.cx != 24 || + h.cy != 24 || + h.c_tiles > 128 || + h.zero1 || + h.size != size || + h.image_offset > size || + h.zero2 || + h.id != 0x0d1affff); + } + + int get_c_tiles() const + { + return header().c_tiles; + } + + const byte* get_image(int i) const + { + return data() + header().image_offset + 576 * get_index1()[i]; + } + + const byte* get_index1() const + { + return data() + header().index1; + } +}; diff --git a/3rdParty/xcc/misc/tmp_ts_file.cpp b/3rdParty/xcc/misc/tmp_ts_file.cpp new file mode 100644 index 0000000..4347f86 --- /dev/null +++ b/3rdParty/xcc/misc/tmp_ts_file.cpp @@ -0,0 +1,185 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "tmp_ts_file.h" + +#include "image_file.h" + +void Ctmp_ts_file::get_rect(int& x, int& y, int& cx, int& cy) const +{ + x = INT_MAX; + y = INT_MAX; + cx = INT_MIN; + cy = INT_MIN; + int bigy = INT_MIN; + int bigyval = 0; + for (int i = 0; i < get_c_tiles(); i++) + { + if (get_index()[i]) + { + int height = get_height() - get_height(i); + int x_t = get_x(i); + int y_t = get_y(i) + (height * (get_cy() / 2)); + int x2_t = x_t + get_cx(); + int y2_t = y_t + get_cy(); + if (has_extra_graphics(i)) + { + int y_t_extra = get_y_extra(i) + (height * (get_cy() / 2)); + int y2_t_extra = y_t_extra + get_cy_extra(i); + if (y_t_extra < y) + y = y_t_extra; + if (y2_t_extra > cy) + cy = y2_t_extra; + } + if (x_t < x) + x = x_t; + if (x2_t > cx) + cx = x2_t; + if (y_t < y) + y = y_t; + if (y2_t > cy) + cy = y2_t; + if (bigy < get_y(i)) + { + bigy = get_y(i); + bigyval = get_y(i) + get_cy() + (get_height(i) * (get_cy() / 2)); + if (has_extra_graphics(i)) + bigyval -= get_y_extra(i); + } + } + } + cx -= x; + cy -= y; + if (cy < bigyval) + cy = bigyval; +} + +void Ctmp_ts_file::draw(byte* d) const +{ + int global_x, global_y, global_cx, global_cy; + get_rect(global_x, global_y, global_cx, global_cy); + memset(d, 0, global_cx * global_cy); + for (int i = 0; i < get_c_tiles(); i++) + { + if (get_index()[i]) + { + int height = get_height() - get_height(i); + const byte* r = get_image(i); + byte* w_line = d + get_x(i) - global_x + global_cx * (get_y(i) - global_y + (height * (get_cy() / 2))); + int x = get_cx() / 2; + int cx = 0; + int y = 0; + for (; y < get_cy() / 2; y++) + { + cx += 4; + x -= 2; + memcpy(w_line + x, r, cx); + r += cx; + w_line += global_cx; + } + for (; y < get_cy(); y++) + { + cx -= 4; + x += 2; + memcpy(w_line + x, r, cx); + r += cx; + w_line += global_cx; + } + if (has_extra_graphics(i)) + { + r += get_cx() * get_cy() / 2; + w_line = d + get_x_extra(i) - global_x + global_cx * (get_y_extra(i) - global_y + (height * (get_cy() / 2))); + int cx = get_cx_extra(i); + int cy = get_cy_extra(i); + for (y = 0; y < cy; y++) + { + byte* w = w_line; + for (int i = 0; i < cx; i++) + { + int v = *r++; + if (v) + *w = v; + w++; + } + w_line += global_cx; + } + } + } + } +} + +int decode_tile(const byte* s, byte* d, int cx_d) +{ + int cy = cx_d >> 1; + memset(d, 0, cx_d * cy); + const byte* r = s; + byte* w = d; + int x = cx_d / 2; + int cx = 0; + int y = 0; + for (; y < cy / 2; y++) + { + cx += 4; + x -= 2; + memcpy(w + x, r, cx); + r += cx; + w += cx_d; + } + for (; y < cy; y++) + { + cx -= 4; + x += 2; + memcpy(w + x, r, cx); + r += cx; + w += cx_d; + } + return w - d; +} + +int encode_tile(const byte* s, byte* d, int cx_s) +{ + int cy = cx_s >> 1; + const byte* r = s; + byte* w = d; + int x = cx_s / 2; + int cx = 0; + int y = 0; + for (; y < cy / 2; y++) + { + cx += 4; + x -= 2; + memcpy(w, r + x, cx); + r += cx_s; + w += cx; + } + for (; y < cy; y++) + { + cx -= 4; + x += 2; + memcpy(w, r + x, cx); + r += cx_s; + w += cx; + } + return w - d; +} + +void Ctmp_ts_file::decode(void* d) const +{ + draw(reinterpret_cast(d)); +} diff --git a/3rdParty/xcc/misc/tmp_ts_file.h b/3rdParty/xcc/misc/tmp_ts_file.h new file mode 100644 index 0000000..43958bf --- /dev/null +++ b/3rdParty/xcc/misc/tmp_ts_file.h @@ -0,0 +1,210 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include +#include +#include "fname.h" +#include "image_file.h" +#include "palet.h" + +class Ctmp_ts_file : public Cimage_file +{ +public: + void decode(void*) const; + void draw(byte* d) const; + void get_rect(int& x, int& y, int& cx, int& cy) const; + + bool is_valid() const + { + const t_tmp_ts_header& h = header(); + int size = get_size(); + if (sizeof(t_tmp_ts_header) > size || + !h.cblocks_x || !h.cblocks_y || + h.cx != 48 && h.cx != 60 || + 2 * h.cy != h.cx || + sizeof(t_tmp_ts_header) + 4 * get_c_tiles() > size) + return false; + for (int i = 0; i < min(get_c_tiles(), 64); i++) + { + if (get_index()[i]) + { + const t_tmp_image_header& image_header = *get_image_header(i); + } + } + return true; + } + + int cb_pixel() const + { + return 1; + } + + int cx() const + { + int x, y, cx, cy; + get_rect(x, y, cx, cy); + return cx; + } + + int cy() const + { + int x, y, cx, cy; + get_rect(x, y, cx, cy); + return cy; + } + + int get_c_tiles() const + { + return get_cblocks_x() * get_cblocks_y(); + } + + int get_cblocks_x() const + { + return header().cblocks_x; + } + + int get_cblocks_y() const + { + return header().cblocks_y; + } + + const t_tmp_image_header* get_image_header(int i) const + { + return reinterpret_cast(data() + get_index()[i]); + } + + int get_x(int i) const + { + return get_image_header(i)->x; + } + + int get_y(int i) const + { + return get_image_header(i)->y; + } + + int get_cx() const + { + return header().cx; + } + + int get_cy() const + { + return header().cy; + } + + int get_x_extra(int i) const + { + return get_image_header(i)->x_extra; + } + + int get_height() const + { + int height = 0; + for (int i = 0; i < get_c_tiles(); i++) + { + if (get_index()[i]) + { + if (get_height(i) > height) + height = get_height(i); + } + } + return height; + } + + int get_height(int i) const + { + return get_image_header(i)->height; + } + + /* + int get_ramp_type(int i) const + { + return get_image_header(i)->ramp_type; + } + + int get_terrain_type(int i) const + { + return get_image_header(i)->terrain_type; + } + */ + + int get_y_extra(int i) const + { + return get_image_header(i)->y_extra; + } + + int get_cx_extra(int i) const + { + return get_image_header(i)->cx_extra; + } + + int get_cy_extra(int i) const + { + return get_image_header(i)->cy_extra; + } + + bool has_extra_graphics(int i) const + { + return get_image_header(i)->has_extra_data; + } + + int get_cb_diamond() const + { + return get_cx() * get_cy() >> 1; + } + + int get_cb_extra_data(int i) const + { + return get_cx_extra(i) * get_cy_extra(i); + } + + const byte* get_image(int i) const + { + return reinterpret_cast(get_image_header(i) + 1); + } + + const byte* get_z_image(int i) const + { + int a = get_index()[i] + get_image_header(i)->z_ofs; + int b = get_image(i) + get_cb_diamond() - data(); + assert(a == b); + return data() + get_index()[i] + get_image_header(i)->z_ofs; + } + + const byte* get_extra_data(int i) const + { + return data() + get_index()[i] + get_image_header(i)->extra_ofs; + } + + const byte* get_extra_z_data(int i) const + { + return data() + get_index()[i] + get_image_header(i)->extra_z_ofs; + } + + const int* get_index() const + { + return reinterpret_cast(data() + sizeof(t_tmp_ts_header)); + } +}; + +int decode_tile(const byte* s, byte* d, int cx_d); +int encode_tile(const byte* s, byte* d, int cx_s); +int tmp_ts_file_write(const byte* s, byte* d, int cx, int cy); diff --git a/3rdParty/xcc/misc/vartypes.h b/3rdParty/xcc/misc/vartypes.h new file mode 100644 index 0000000..9621128 --- /dev/null +++ b/3rdParty/xcc/misc/vartypes.h @@ -0,0 +1,22 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include + +using byte = unsigned char; +// using std::byte; diff --git a/3rdParty/xcc/misc/video_decoder.cpp b/3rdParty/xcc/misc/video_decoder.cpp new file mode 100644 index 0000000..8366838 --- /dev/null +++ b/3rdParty/xcc/misc/video_decoder.cpp @@ -0,0 +1,29 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "video_decoder.h" + +Cvideo_decoder::~Cvideo_decoder() +{ +} + +const t_palet_entry* Cvideo_decoder::palet() const +{ + return NULL; +} diff --git a/3rdParty/xcc/misc/video_decoder.h b/3rdParty/xcc/misc/video_decoder.h new file mode 100644 index 0000000..317f595 --- /dev/null +++ b/3rdParty/xcc/misc/video_decoder.h @@ -0,0 +1,44 @@ +/* + XCC Utilities and Library + Copyright (C) 2004 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "palet.h" + +class Cvideo_decoder +{ +public: + virtual int cb_pixel() const = 0; + virtual int cf() const = 0; + virtual int cx() const = 0; + virtual int cy() const = 0; + virtual int decode(void* d) = 0; + virtual const t_palet_entry* palet() const; + virtual int seek(int f) = 0; + virtual ~Cvideo_decoder(); + + int cb_image() const + { + return cb_pixel() * cx() * cy(); + } + + int cb_video() const + { + return cf() * cb_image(); + } +}; diff --git a/3rdParty/xcc/misc/video_file.cpp b/3rdParty/xcc/misc/video_file.cpp new file mode 100644 index 0000000..7f151e0 --- /dev/null +++ b/3rdParty/xcc/misc/video_file.cpp @@ -0,0 +1,20 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "video_file.h" diff --git a/3rdParty/xcc/misc/video_file.h b/3rdParty/xcc/misc/video_file.h new file mode 100644 index 0000000..a7c2872 --- /dev/null +++ b/3rdParty/xcc/misc/video_file.h @@ -0,0 +1,48 @@ +/* + XCC Utilities and Library + Copyright (C) 2004 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "cc_file_sh.h" +#include "palet.h" +#include "video_decoder.h" + +template +class Cvideo_file : public Ccc_file_sh +{ +public: + virtual int cb_pixel() const = 0; + virtual int cf() const = 0; + virtual int cx() const = 0; + virtual int cy() const = 0; + + int cb_image() const + { + return cb_pixel() * cx() * cy(); + } + + int cb_video() const + { + return cf() * cb_image(); + } + + virtual const t_palet_entry* palet() const + { + return NULL; + } +}; diff --git a/3rdParty/xcc/misc/virtual_audio.cpp b/3rdParty/xcc/misc/virtual_audio.cpp new file mode 100644 index 0000000..410ae76 --- /dev/null +++ b/3rdParty/xcc/misc/virtual_audio.cpp @@ -0,0 +1,71 @@ +/* + XCC Utilities and Library + Copyright (C) 2001 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "virtual_audio.h" + +#include "aud_file_write.h" +#include "wav_file.h" + +Cvirtual_audio::Cvirtual_audio() +{ +} + +Cvirtual_audio::~Cvirtual_audio() +{ +} + +void Cvirtual_audio::load(Cvirtual_file f, int c_samples, int samplerate, int cb_sample, int c_channels) +{ + mc_samples = c_samples; + m_samplerate = samplerate; + mcb_sample = cb_sample; + mc_channels = c_channels; + m_f = f; + m_f.compact(); +} + +Cvirtual_file Cvirtual_audio::save_as_aud() const +{ + return aud_file_write(audio(), cb_audio(), c_samples(), samplerate(), c_channels()); +} + +int Cvirtual_audio::save_as_aud(string fname) const +{ + return aud_file_write(fname, audio(), cb_audio(), c_samples(), samplerate(), c_channels()); +} + +Cvirtual_file Cvirtual_audio::save_as_wav_ima_adpcm() const +{ + return wav_ima_adpcm_file_write(audio(), cb_audio(), c_samples(), samplerate(), c_channels()); +} + +int Cvirtual_audio::save_as_wav_ima_adpcm(string fname) const +{ + return wav_ima_adpcm_file_write(fname, audio(), cb_audio(), c_samples(), samplerate(), c_channels()); +} + +Cvirtual_file Cvirtual_audio::save_as_wav_pcm() const +{ + return wav_pcm_file_write(audio(), cb_audio(), samplerate(), cb_sample(), c_channels()); +} + +int Cvirtual_audio::save_as_wav_pcm(string fname) const +{ + return wav_pcm_file_write(fname, audio(), cb_audio(), samplerate(), cb_sample(), c_channels()); +} \ No newline at end of file diff --git a/3rdParty/xcc/misc/virtual_audio.h b/3rdParty/xcc/misc/virtual_audio.h new file mode 100644 index 0000000..6cc6de8 --- /dev/null +++ b/3rdParty/xcc/misc/virtual_audio.h @@ -0,0 +1,71 @@ +/* + XCC Utilities and Library + Copyright (C) 2001 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "virtual_file.h" + +class Cvirtual_audio +{ +public: + void load(Cvirtual_file f, int c_samples, int samplerate, int cb_sample, int c_channels); + Cvirtual_file save_as_aud() const; + int save_as_aud(string fname) const; + Cvirtual_file save_as_wav_ima_adpcm() const; + int save_as_wav_ima_adpcm(string fname) const; + Cvirtual_file save_as_wav_pcm() const; + int save_as_wav_pcm(string fname) const; + Cvirtual_audio(); + ~Cvirtual_audio(); + + const __int16* audio() const + { + return reinterpret_cast(m_f.data()); + } + + int cb_audio() const + { + return mc_samples * mcb_sample * mc_channels; + } + + int c_samples() const + { + return mc_samples; + } + + int samplerate() const + { + return m_samplerate; + } + + int cb_sample() const + { + return mcb_sample; + } + + int c_channels() const + { + return mc_channels; + } +private: + Cvirtual_file m_f; + int mc_samples; + int m_samplerate; + int mcb_sample; + int mc_channels; +}; diff --git a/3rdParty/xcc/misc/virtual_binary.cpp b/3rdParty/xcc/misc/virtual_binary.cpp new file mode 100644 index 0000000..7d3ebcb --- /dev/null +++ b/3rdParty/xcc/misc/virtual_binary.cpp @@ -0,0 +1,165 @@ +/* + XCC Utilities and Library + Copyright (C) 2001 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include + +#include "file32.h" + +Cvirtual_binary_source::Cvirtual_binary_source(const void* d, size_t cb_d, const std::shared_ptr& source) +{ + if (source) + { + m_data = const_cast(reinterpret_cast(d)); + m_size = cb_d; + m_source = source; + } + else + { + m_data = new byte[cb_d]; + m_size = cb_d; + if (d) + memcpy(m_data, d, cb_d); + } + mc_references = 1; +} + +Cvirtual_binary_source* Cvirtual_binary_source::attach() +{ + if (this) + mc_references++; + return this; +} + +void Cvirtual_binary_source::detach() +{ + if (!this || --mc_references) + return; + if (!m_source) + delete[] m_data; + delete this; +} + +Cvirtual_binary_source* Cvirtual_binary_source::pre_edit() +{ + if (mc_references == 1 && !m_source) + return this; + Cvirtual_binary_source* t = new Cvirtual_binary_source(m_data, m_size, NULL); + detach(); + return t; +} + +Cvirtual_binary::Cvirtual_binary() +{ + m_source = NULL; +} + +Cvirtual_binary::Cvirtual_binary(const Cvirtual_binary& v) +{ + m_source = v.m_source->attach(); +} + +Cvirtual_binary::Cvirtual_binary(const void* d, size_t cb_d) +{ + m_source = new Cvirtual_binary_source(d, cb_d); +} + +Cvirtual_binary::Cvirtual_binary(const void* d, size_t cb_d, const std::shared_ptr& source) +{ + m_source = new Cvirtual_binary_source(d, cb_d, source); +} + +Cvirtual_binary::Cvirtual_binary(data_ref d) +{ + m_source = new Cvirtual_binary_source(d.data(), d.size()); +} + +Cvirtual_binary::Cvirtual_binary(const string& fname, bool use_mm) +{ + m_source = NULL; + load(fname, use_mm); +} + +Cvirtual_binary::~Cvirtual_binary() +{ + m_source->detach(); +} + +const Cvirtual_binary& Cvirtual_binary::operator=(const Cvirtual_binary& v) +{ + if (this != &v) + { + m_source->detach(); + m_source = v.m_source->attach(); + } + return *this; +} + +int Cvirtual_binary::save(const string& fname) const +{ + return data() ? file32_write(fname, data(), size()) : 1; +} + +int Cvirtual_binary::load(const string& fname, bool use_mm) +{ + if (use_mm) + *this = file32_read(fname); + else + { + Cvirtual_binary d = file32_read(fname); + *this = Cvirtual_binary(d.data(), d.size()); + } + return !data(); +} + +void Cvirtual_binary::clear() +{ + m_source->detach(); + m_source = NULL; +} + +void Cvirtual_binary::memset(int v) +{ + ::memset(data_edit(), v, size()); +} + +size_t Cvirtual_binary::read(void* d) const +{ + memcpy(d, data(), size()); + return size(); +} + +byte* Cvirtual_binary::write_start(size_t cb_d) +{ + if (data() && size() == cb_d) + return data_edit(); + m_source->detach(); + m_source = new Cvirtual_binary_source(NULL, cb_d); + return data_edit(); +} + +void Cvirtual_binary::write(const void* d, size_t cb_d) +{ + memcpy(write_start(cb_d), d, cb_d); +} + +Cvirtual_binary Cvirtual_binary::sub_bin(size_t offset, size_t size) const +{ + assert(offset >= 0 && offset + size <= Cvirtual_binary::size()); + return data() ? Cvirtual_binary(data() + offset, size, std::make_shared(*this)) : *this; +} \ No newline at end of file diff --git a/3rdParty/xcc/misc/virtual_binary.h b/3rdParty/xcc/misc/virtual_binary.h new file mode 100644 index 0000000..9771175 --- /dev/null +++ b/3rdParty/xcc/misc/virtual_binary.h @@ -0,0 +1,140 @@ +/* + XCC Utilities and Library + Copyright (C) 2001 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include +#include +#include +#include +#include + +using namespace std; + +class Cvirtual_binary_source +{ +public: + Cvirtual_binary_source(const void* d, size_t cb_d, const std::shared_ptr& source = NULL); + Cvirtual_binary_source* attach(); + void detach(); + Cvirtual_binary_source* pre_edit(); + + const byte* data() const + { + return m_data; + } + + const byte* data_end() const + { + return data() + size(); + } + + byte* data_edit() + { + assert(mc_references == 1 && !m_source); + return m_data; + } + + size_t size() const + { + return m_size; + } + + void size(size_t v) + { + assert(mc_references == 1 && !m_source && v <= m_size); + m_size = v; + } + + bool unique() const + { + return mc_references == 1; + } +private: + byte* m_data; + size_t m_size; + int mc_references; + std::shared_ptr m_source; +}; + +class Cvirtual_binary +{ +public: + Cvirtual_binary sub_bin(size_t offset, size_t size) const; + int save(const string& fname) const; + int load(const string& fname, bool use_mm = true); + void clear(); + void memset(int v); + size_t read(void* d) const; + byte* write_start(size_t cb_d); + void write(const void* d, size_t cb_d); + const Cvirtual_binary& operator=(const Cvirtual_binary& v); + Cvirtual_binary(); + Cvirtual_binary(const Cvirtual_binary&); + Cvirtual_binary(data_ref); + Cvirtual_binary(const void*, size_t); + Cvirtual_binary(const void*, size_t, const std::shared_ptr& source); + explicit Cvirtual_binary(const string& fname, bool use_mm = true); + ~Cvirtual_binary(); + + const byte* data() const + { + return m_source ? m_source->data() : NULL; + } + + const byte* data_end() const + { + return m_source ? m_source->data_end() : NULL; + } + + const byte* begin() const + { + return data(); + } + + const byte* end() const + { + return data_end(); + } + + byte* data_edit() + { + assert(m_source); + m_source = m_source->pre_edit(); + return m_source->data_edit(); + } + + byte* mutable_end() + { + return data_edit() + size(); + } + + size_t size() const + { + return m_source ? m_source->size() : 0; + } + + void set_size(size_t v) + { + assert(m_source); + m_source = m_source->pre_edit(); + m_source->size(v); + } +private: + Cvirtual_binary_source* m_source; +}; diff --git a/3rdParty/xcc/misc/virtual_file.cpp b/3rdParty/xcc/misc/virtual_file.cpp new file mode 100644 index 0000000..ba70183 --- /dev/null +++ b/3rdParty/xcc/misc/virtual_file.cpp @@ -0,0 +1,109 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "virtual_file.h" + +#include "file32.h" + +Cvirtual_file::Cvirtual_file() +{ +} + +Cvirtual_file::Cvirtual_file(const Cvirtual_binary& d) +{ + write(d); +} + +void Cvirtual_file::clear() +{ + m_data.clear(); +} + +void Cvirtual_file::compact() +{ + if (m_data.size() == 1) + return; + Cvirtual_binary t = read(); + clear(); + write(t); +} + +const byte* Cvirtual_file::data() const +{ + if (m_data.size() != 1) + return NULL; + return m_data.begin()->data(); +} + +int Cvirtual_file::size() const +{ + int r = 0; + for (auto& i : m_data) + r += i.size(); + return r; +} + +int Cvirtual_file::save(const string& fname) const +{ + Cfile32 f; + int error = f.open_write(fname); + if (!error) + { + for (auto& i : m_data) + error = f.write(i); + } + return error; +} + +int Cvirtual_file::load(const string& fname) +{ + clear(); + Cvirtual_binary t; + int error = t.load(fname); + if (!error) + write(t); + return error; +} + +Cvirtual_binary Cvirtual_file::read() const +{ + if (m_data.size() == 1) + return *m_data.begin(); + Cvirtual_binary r; + read(r.write_start(size())); + return r; +} + +int Cvirtual_file::read(void* d) const +{ + byte* w = reinterpret_cast(d); + for (auto& i : m_data) + w += i.read(w); + return w - reinterpret_cast(d); +} + +void Cvirtual_file::write(const Cvirtual_binary& d) +{ + m_data.push_back(d); +} + +void Cvirtual_file::write(const void* d, int cb_d) +{ + write(Cvirtual_binary(d, cb_d)); +} \ No newline at end of file diff --git a/3rdParty/xcc/misc/virtual_file.h b/3rdParty/xcc/misc/virtual_file.h new file mode 100644 index 0000000..2a4637e --- /dev/null +++ b/3rdParty/xcc/misc/virtual_file.h @@ -0,0 +1,44 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include +#include + +using namespace std; + +class Cvirtual_file +{ +public: + int save(const string& fname) const; + int load(const string& fname); + void clear(); + void compact(); + const byte* data() const; + int size() const; + Cvirtual_binary read() const; + int read(void* d) const; + void write(const Cvirtual_binary& d); + void write(const void* d, int cb_d); + Cvirtual_file(); + Cvirtual_file(const Cvirtual_binary& d); +private: + using t_data = list; + t_data m_data; +}; diff --git a/3rdParty/xcc/misc/virtual_image.cpp b/3rdParty/xcc/misc/virtual_image.cpp new file mode 100644 index 0000000..456ea2d --- /dev/null +++ b/3rdParty/xcc/misc/virtual_image.cpp @@ -0,0 +1,332 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" + +#include +#include +#include + +#ifndef XCC_MINIMAL_BUILD +#include "dds_file.h" +#include "image_file.h" +#include "jpeg_file.h" +#include "pcx_file.h" +#include "pcx_file_write.h" +#include "png_file.h" +#include "tga_file.h" +#endif +#include "virtual_image.h" + +using namespace Gdiplus; + +Cvirtual_image::Cvirtual_image(const Cvirtual_binary& image, int cx, int cy, int cb_pixel, const t_palet_entry* palet, bool inflate) +{ + load(image, cx, cy, cb_pixel, palet, inflate); +} + +Cvirtual_image::Cvirtual_image(const void* image, int cx, int cy, int cb_pixel, const t_palet_entry* palet, bool inflate) +{ + load(image, cx, cy, cb_pixel, palet, inflate); +} + +const Cvirtual_image& Cvirtual_image::palet(const t_palet_entry* palet, bool inflate) +{ + if (palet) + { + memcpy(m_palet.write_start(sizeof(t_palet)), palet, sizeof(t_palet)); + if (inflate) + convert_palet_18_to_24(reinterpret_cast(m_palet.data_edit())); + } + else + m_palet.clear(); + return *this; +} + +void Cvirtual_image::load(const Cvirtual_binary& image, int cx, int cy, int cb_pixel, const t_palet_entry* p, bool inflate) +{ + assert(cb_pixel == 1 || cb_pixel == 3 || cb_pixel == 4); + m_cx = cx; + m_cy = cy; + mcb_pixel = cb_pixel; + if (image.size() == cb_image()) + m_image = image; + else + m_image.write_start(cb_image()); + palet(p, inflate); +} + +void Cvirtual_image::load(const void* image, int cx, int cy, int cb_pixel, const t_palet_entry* p, bool inflate) +{ + assert(cb_pixel == 1 || cb_pixel == 3 || cb_pixel == 4); + m_cx = cx; + m_cy = cy; + mcb_pixel = cb_pixel; + m_image.write_start(cb_image()); + if (image) + memcpy(m_image.data_edit(), image, cb_image()); + palet(p, inflate); +} + +#ifndef XCC_MINIMAL_BUILD + +int Cvirtual_image::load(const Cvirtual_binary& s) +{ + Cdds_file dds_f; + Cpcx_file pcx_f; + Cpng_file png_f; + Ctga_file tga_f; + if (dds_f.load(s), dds_f.is_valid()) + *this = dds_f.vimage(); + else if (pcx_f.load(s), pcx_f.is_valid()) + *this = pcx_f.vimage(); + else if (png_f.load(s), png_f.is_valid()) + return png_f.decode(*this); + else if (tga_f.load(s), tga_f.is_valid()) + return tga_f.decode(*this); + else + { + IStream* is = SHCreateMemStream(s.data(), s.size()); + Gdiplus::Bitmap bmp(is); + is->Release(); + if (bmp.GetLastStatus() != Ok) + return 1; + PixelFormat pf = bmp.GetPixelFormat(); + if (bmp.GetPixelFormat() & PixelFormatIndexed) + { + load(NULL, bmp.GetWidth(), bmp.GetHeight(), 1, NULL); + BitmapData d; + d.Stride = bmp.GetWidth(); + d.Scan0 = image_edit(); + bmp.LockBits(NULL, ImageLockModeRead | ImageLockModeUserInputBuf, PixelFormat8bppIndexed, &d); + bmp.UnlockBits(&d); + } + else + { + load(NULL, bmp.GetWidth(), bmp.GetHeight(), 3, NULL); + BitmapData d; + d.Stride = bmp.GetWidth() * 3; + d.Scan0 = image_edit(); + bmp.LockBits(NULL, ImageLockModeRead | ImageLockModeUserInputBuf, PixelFormat24bppRGB, &d); + bmp.UnlockBits(&d); + swap_rb(); + } + } + return 0; +} + +int Cvirtual_image::load(const Cvirtual_file& f) +{ + return load(f.read()); +} + +int Cvirtual_image::load(const string& fname) +{ + Cvirtual_binary s; + int error = s.load(fname); + if (!error) + error = load(s); + return error; +} + +int Cvirtual_image::save(Cvirtual_file& f, t_file_type ft) const +{ + return image_file_write(f, ft, image(), palet(), m_cx, m_cy); +} + +Cvirtual_file Cvirtual_image::save(t_file_type ft) const +{ + return image_file_write(ft, image(), palet(), m_cx, m_cy); +} + +int Cvirtual_image::save(const string& fname, t_file_type ft) const +{ + return image_file_write(fname, ft, image(), palet(), m_cx, m_cy); +} + +void Cvirtual_image::swap_rb() +{ + int count = m_cx * m_cy; + t_palet_entry* r = reinterpret_cast(m_image.data_edit()); + while (count--) + { + swap(r->r, r->b); + r++; + } +} + +static void flip_frame(const byte* s, byte* d, int cx, int cy, int cb_pixel) +{ + int cb_line = cx * cb_pixel; + const byte* r = s; + byte* w = d + cb_line * cy; + while (cy--) + { + w -= cb_line; + memcpy(w, r, cb_line); + r += cb_line; + } +} + +void Cvirtual_image::flip() +{ + Cvirtual_binary t = m_image; + flip_frame(t.data(), image_edit(), cx(), cy(), cb_pixel()); +} + + +void Cvirtual_image::cb_pixel(int cb_pixel, const t_palet_entry* palet) +{ + if (cb_pixel < mcb_pixel) + decrease_color_depth(cb_pixel, palet); + else if (cb_pixel > mcb_pixel) + increase_color_depth(cb_pixel); +} + +void Cvirtual_image::decrease_color_depth(int new_cb_pixel, const t_palet_entry* palet) +{ + if (new_cb_pixel == 3) + { + remove_alpha(); + return; + } + assert(new_cb_pixel == 1); + int old_cb_pixel = cb_pixel(); + Cvirtual_binary t = m_image; + load(NULL, cx(), cy(), new_cb_pixel, palet); + byte* w = image_edit(); + int count = m_cx * m_cy; + if (old_cb_pixel == 3) + { + const t_palet_entry* r = reinterpret_cast(t.data()); + while (count--) + { + *w++ = find_color(r->r, r->g, r->b, palet); + r++; + } + } + else + { + assert(old_cb_pixel == 4); + const t_palet32entry* r = reinterpret_cast(t.data()); + while (count--) + { + *w++ = r->a < 0x80 ? find_color(r->r, r->g, r->b, palet) : 0; + r++; + } + } +} + +static t_palet32entry p32e(int r, int g, int b, int a = 0) +{ + t_palet32entry e; + e.r = r; + e.g = g; + e.b = b; + e.a = a; + return e; +} + +static t_palet32entry p32e(t_palet_entry e) +{ + return p32e(e.r, e.g, e.b); +} + +static t_palet32entry p32e(const t_palet palet, int i) +{ + return i ? p32e(palet[i]) : p32e(0x80, 0x80, 0x80, 0xff); +} + +void Cvirtual_image::increase_color_depth(int new_cb_pixel) +{ + if (cb_pixel() == 3) + { + if (new_cb_pixel == 4) + add_alpha(); + return; + } + assert(cb_pixel() == 1); + Cvirtual_image t = *this; + const byte* r = t.image(); + load(NULL, cx(), cy(), new_cb_pixel, NULL); + int count = m_cx * m_cy; + if (cb_pixel() == 3) + { + t_palet_entry* w = reinterpret_cast(image_edit()); + while (count--) + *w++ = t.palet()[*r++]; + } + else + { + assert(cb_pixel() == 4); + t_palet32entry* w = reinterpret_cast(image_edit()); + while (count--) + *w++ = p32e(t.palet(), *r++); + } +} + +void Cvirtual_image::add_alpha() +{ + assert(cb_pixel() == 3); + Cvirtual_binary t = m_image; + load(NULL, cx(), cy(), 4, NULL); + int count = m_cx * m_cy; + const byte* r = t.data(); + byte* w = image_edit(); + while (count--) + { + *w++ = *r++; + *w++ = *r++; + *w++ = *r++; + *w++ = 0; + } +} + +void Cvirtual_image::remove_alpha() +{ + if (cb_pixel() != 4) + return; + Cvirtual_binary t = m_image; + load(NULL, cx(), cy(), 3, NULL); + int count = m_cx * m_cy; + const byte* r = t.data(); + byte* w = image_edit(); + while (count--) + { + *w++ = *r++; + *w++ = *r++; + *w++ = *r++; + r++; + } +} + +void Cvirtual_image::increase_palet_depth() +{ + assert(false); + Cvirtual_binary t = m_palet; + const t_palet_entry* s = reinterpret_cast(t.data()); + t_palet_entry* d = reinterpret_cast(t.data_edit()); + for (int i = 0; i < 256; i++) + { + d[i].r = (s[i].r & 63) * 255 / 63; + d[i].g = (s[i].g & 63) * 255 / 63; + d[i].b = (s[i].b & 63) * 255 / 63; + } +} + +#endif diff --git a/3rdParty/xcc/misc/virtual_image.h b/3rdParty/xcc/misc/virtual_image.h new file mode 100644 index 0000000..0a2a2d6 --- /dev/null +++ b/3rdParty/xcc/misc/virtual_image.h @@ -0,0 +1,124 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "cc_file.h" +#include "palet.h" +#include "virtual_file.h" + +class Cvirtual_image +{ +public: + const Cvirtual_image& palet(const t_palet_entry* palet, bool inflate = false); + void remove_alpha(); + void add_alpha(); + void cb_pixel(int cb_pixel, const t_palet_entry* palet = NULL); + void decrease_color_depth(int cb_pixel, const t_palet_entry* palet = NULL); + void increase_color_depth(int cb_pixel); + void increase_palet_depth(); + void flip(); + int get_clipboard(); + int set_clipboard() const; + int load(); + int save() const; + void load(const Cvirtual_binary& image, int cx, int cy, int cb_pixel, const t_palet_entry* palet, bool inflate = false); + void load(const void* image, int cx, int cy, int cb_pixel, const t_palet_entry* palet, bool inflate = false); + int load(const Cvirtual_binary& s); + int load(const Cvirtual_file& f); + int load(const string& fname); + int save(Cvirtual_file& f, t_file_type ft) const; + Cvirtual_file save(t_file_type ft) const; + int save(const string& fname, t_file_type ft) const; + void swap_rb(); + Cvirtual_image() = default; + Cvirtual_image(const Cvirtual_binary& image, int cx, int cy, int cb_pixel, const t_palet_entry* palet = NULL, bool inflate = false); + Cvirtual_image(const void* image, int cx, int cy, int cb_pixel, const t_palet_entry* palet = NULL, bool inflate = false); + + const byte* image() const + { + return m_image.data(); + } + + byte* image_edit() + { + return m_image.data_edit(); + } + + int cx() const + { + return m_cx; + } + + int cy() const + { + return m_cy; + } + + int cb_pixel() const + { + return mcb_pixel; + } + + const t_palet_entry* palet() const + { + return reinterpret_cast(m_palet.data()); + } + + int cb_image() const + { + return m_cx * m_cy * mcb_pixel; + } + + int ofs8(int x, int y) const + { + return x + m_cx * y; + } + + int ofs24(int x, int y) const + { + return ofs8(x, y) * 3; + } + + int pixel8(int x, int y) const + { + return m_image.data()[ofs8(x, y)]; + } + + void pixel8(int x, int y, int v) + { + m_image.data_edit()[ofs8(x, y)] = v; + } + + t_palet_entry pixel24(int x, int y) const + { + return reinterpret_cast(m_image.data())[ofs8(x, y)]; + } + + void pixel24(int x, int y, t_palet_entry v) + { + reinterpret_cast(m_image.data_edit())[ofs8(x, y)] = v; + } +private: + Cvirtual_binary m_image; + Cvirtual_binary m_palet; + int m_cx = 0; + int m_cy = 0; + int mcb_pixel = 0; +}; + diff --git a/3rdParty/xcc/misc/virtual_tfile.cpp b/3rdParty/xcc/misc/virtual_tfile.cpp new file mode 100644 index 0000000..c1965f6 --- /dev/null +++ b/3rdParty/xcc/misc/virtual_tfile.cpp @@ -0,0 +1,93 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "virtual_tfile.h" + +void Cvirtual_tfile::load_data(const Cvirtual_binary s) +{ + m_data = s; + pos = 0; +} + +string Cvirtual_tfile::read_line() +{ + assert(data()); + const int first_non_ws = pos; + int last_non_ws; + while (pos < size()) + { + switch (data()[pos++]) + { + case '\r': + last_non_ws = pos - 2; + if (pos < size() && data()[pos] == '\n') + pos++; + return string(data() + first_non_ws, last_non_ws - first_non_ws + 1); + case '\n': + last_non_ws = pos - 2; + return string(data() + first_non_ws, last_non_ws - first_non_ws + 1); + } + } + last_non_ws = size() - 1; + return string(data() + first_non_ws, last_non_ws - first_non_ws + 1); +} + +string Cvirtual_tfile::read_line(bool remove_ws) +{ + if (!remove_ws) + return read_line(); + assert(data()); + int first_non_ws; + int last_non_ws; + while (pos < size()) + { + switch (data()[pos++]) + { + case '\r': + if (pos < size() && data()[pos] == '\n') + pos++; + case '\n': + return ""; + case '\t': + case ' ': + break; + default: + first_non_ws = pos - 1; + last_non_ws = pos - 2; + while (pos < size()) + { + switch (data()[pos++]) + { + case '\r': + if (pos < size() && data()[pos] == '\n') + pos++; + case '\n': + return string(data() + first_non_ws, last_non_ws - first_non_ws + 1); + case '\t': + case ' ': + break; + default: + last_non_ws = pos - 1; + } + } + return string(data() + first_non_ws, last_non_ws - first_non_ws + 1); + } + } + return ""; +} \ No newline at end of file diff --git a/3rdParty/xcc/misc/virtual_tfile.h b/3rdParty/xcc/misc/virtual_tfile.h new file mode 100644 index 0000000..418be44 --- /dev/null +++ b/3rdParty/xcc/misc/virtual_tfile.h @@ -0,0 +1,53 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include +#include + +class Cvirtual_tfile +{ +private: + Cvirtual_binary m_data; + int pos; + + const char* data() const + { + return reinterpret_cast(m_data.data()); + } + + int size() const + { + return m_data.size(); + } +public: + string read_line(); + string read_line(bool remove_ws); + void load_data(const Cvirtual_binary s); + + bool eof() const + { + return pos >= size(); + } + + void seek(int ipos) + { + pos = ipos; + } +}; diff --git a/3rdParty/xcc/misc/vxl_file.cpp b/3rdParty/xcc/misc/vxl_file.cpp new file mode 100644 index 0000000..a629aa1 --- /dev/null +++ b/3rdParty/xcc/misc/vxl_file.cpp @@ -0,0 +1,676 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "vxl_file.h" + +#include "file32.h" +#include "image_file.h" +#ifndef XCC_MINIMAL_BUILD +#include "multi_line.h" +#include "pcx_decode.h" +#include "pcx_file_write.h" +#endif +#include "string_conversion.h" + +bool Cvxl_file::is_valid() const +{ + int size = get_size(); + const t_vxl_header& h = header(); + if (sizeof(t_vxl_header) > size || + strcmp(h.id, vxl_id) || + h.one != 1 || + h.c_section_headers != h.c_section_tailers || + h.size != size - sizeof(t_vxl_header) - h.c_section_headers * sizeof(t_vxl_section_header) - h.c_section_tailers * sizeof(t_vxl_section_tailer) || + h.unknown != 0x1f10) + return false; + /* + for (int i = 0; i < header.c_section_headers; i++) + { + const t_vxl_section_header& section_header = *get_section_header(i); + const t_vxl_section_tailer& section_tailer = *get_section_tailer(i); + if (section_header.one != 1 || + section_header.zero || + section_tailer.span_end_ofs - section_tailer.span_start_ofs != section_tailer.span_data_ofs - section_tailer.span_end_ofs) + return false; + } + */ + return true; +} + +#ifndef XCC_MINIMAL_BUILD +int Cvxl_file::extract_as_pcx(const Cfname& name, t_file_type ft, const t_palet _palet) const +{ + t_palet palet; + memcpy(palet, _palet, sizeof(t_palet)); + convert_palet_18_to_24(palet); + const t_vxl_section_tailer& section_tailer = *get_section_tailer(0); + const int cx = section_tailer.cx; + const int cy = section_tailer.cy; + const int cz = section_tailer.cz; + Cvirtual_binary s; + for (int i = 0; i < cz; i++) + { + memset(s.write_start(cx * cy), 0, cx * cy); + int j = 0; + for (int y = 0; y < cy; y++) + { + for (int x = 0; x < cx; x++) + { + const byte* r = get_span_data(0, j); + if (r) + { + int z = 0; + while (z < cz) + { + z += *r++; + int c = *r++; + while (c--) + { + if (i == z) + s.data_edit()[x + cx * y] = *r; + r += 2; + z++; + } + r++; + } + } + j++; + } + } + Cfname t = name; + t.set_title(name.get_ftitle() + " " + nwzl(4, i)); + int error = image_file_write(t, ft, s.data(), palet, cx, cy); + if (error) + return error; + } + return 0; +} +#endif + +ostream& Cvxl_file::extract_as_text(ostream& os) const +{ + for (int i = 0; i < get_c_section_headers(); i++) + { + const t_vxl_section_tailer& section_tailer = *get_section_tailer(i); + const int cx = section_tailer.cx; + const int cy = section_tailer.cy; + const int cz = section_tailer.cz; + int j = 0; + for (int y = 0; y < cy; y++) + { + for (int x = 0; x < cx; x++) + { + const byte* r = get_span_data(i, j); + if (r) + { + int z = 0; + while (z < cz) + { + z += *r++; + int c = *r++; + while (c--) + { + os << i << ',' << x << ',' << y << ',' << z << ',' << static_cast(*r++) << ',' << static_cast(*r++) << endl; + z++; + } + r++; + } + } + j++; + } + } + } + return os; +} + +enum +{ + vi_header, + vi_body, + vi_tailer, + vi_palet, + vi_color, + vi_surface_normal, + + vi_x, + vi_y, + vi_z, + vi_cx, + vi_cy, + vi_cz, + vi_id, + vi_red, + vi_green, + vi_blue, + vi_x_min, + vi_y_min, + vi_z_min, + vi_x_max, + vi_y_max, + vi_z_max +}; + +#ifndef XCC_MINIMAL_BUILD +int Cvxl_file::extract_as_xif(const string& name) const +{ + Cxif_key k; + Cxif_key& header = k.open_key_write(vi_header); + Cxif_key& palet = header.open_key_write(vi_palet); + int i; + for (i = 0; i < 256; i++) + { + Cxif_key& palet_entry = palet.open_key_write(i); + palet_entry.set_value_int(vi_red, get_palet()[i].r); + palet_entry.set_value_int(vi_green, get_palet()[i].g); + palet_entry.set_value_int(vi_blue, get_palet()[i].b); + } + Cxif_key& body = k.open_key_write(vi_body); + for (i = 0; i < get_c_section_headers(); i++) + { + const t_vxl_section_header& section_header = *get_section_header(i); + const t_vxl_section_tailer& section_tailer = *get_section_tailer(i); + const int cx = section_tailer.cx; + const int cy = section_tailer.cy; + const int cz = section_tailer.cz; + Cxif_key& section = body.open_key_write(i); + Cxif_key& header = section.open_key_write(vi_header); + header.set_value_string(vi_id, section_header.id); + Cxif_key& body = section.open_key_write(vi_body); + int j = 0; + for (int y = 0; y < cy; y++) + { + Cxif_key& yi = body.open_key_write(y); + for (int x = 0; x < cx; x++) + { + Cxif_key& xi = yi.open_key_write(x); + const byte* r = get_span_data(i, j); + if (r) + { + int z = 0; + while (z < cz) + { + z += *r++; + int c = *r++; + while (c--) + { + Cxif_key& zi = xi.open_key_write(z); + zi.set_value_int(vi_color, *r++); + zi.set_value_int(vi_surface_normal, *r++); + z++; + } + r++; + } + } + j++; + } + } + Cxif_key& tailer = section.open_key_write(vi_tailer); + tailer.set_value_int(vi_x_min, section_tailer.x_min_scale * 1000000); + tailer.set_value_int(vi_y_min, section_tailer.y_min_scale * 1000000); + tailer.set_value_int(vi_z_min, section_tailer.z_min_scale * 1000000); + tailer.set_value_int(vi_x_max, section_tailer.x_max_scale * 1000000); + tailer.set_value_int(vi_y_max, section_tailer.y_max_scale * 1000000); + tailer.set_value_int(vi_z_max, section_tailer.z_max_scale * 1000000); + tailer.set_value_int(vi_cx, cx); + tailer.set_value_int(vi_cy, cy); + tailer.set_value_int(vi_cz, cz); + } + return k.vdata().save(name); +} + +Cvirtual_binary vxl_file_write(const Cxif_key& s) +{ + Cvirtual_binary d; + byte* w = d.write_start(1 << 20); + const Cxif_key& header_key = s.open_key_read(vi_header); + const Cxif_key& body_key = s.open_key_read(vi_body); + int c_sections = body_key.c_keys(); + int* span_start_list_ofs = new int[c_sections]; + int* span_end_list_ofs = new int[c_sections]; + int* span_data_ofs = new int[c_sections]; + t_vxl_header& header = *reinterpret_cast(w); + strcpy(header.id, vxl_id); + header.one = 1; + header.c_section_headers = c_sections; + header.c_section_tailers = c_sections; + header.unknown = 0x1f10; + const Cxif_key& palet_key = header_key.open_key_read(vi_palet); + int i; + for (i = 0; i < 256; i++) + { + const Cxif_key& palet_entry_key = palet_key.open_key_read(i); + header.palet[i].r = palet_entry_key.get_value_int(vi_red); + header.palet[i].g = palet_entry_key.get_value_int(vi_green); + header.palet[i].b = palet_entry_key.get_value_int(vi_blue); + } + w += sizeof(t_vxl_header); + for (i = 0; i < c_sections; i++) + { + const Cxif_key& section_key = body_key.open_key_read(i); + const Cxif_key& section_header_key = section_key.open_key_read(vi_header); + t_vxl_section_header& section_header = *reinterpret_cast(w); + strcpy(section_header.id, section_header_key.get_value_string(vi_id).c_str()); + section_header.section_i = i; + section_header.one = 1; + section_header.zero = 0; + w += sizeof(t_vxl_section_header); + } + byte* body_start = w; + for (i = 0; i < c_sections; i++) + { + const Cxif_key& section_key = body_key.open_key_read(i); + const Cxif_key& section_body_key = section_key.open_key_read(vi_body); + const Cxif_key& section_tailer_key = section_key.open_key_read(vi_tailer); + const int cx = section_tailer_key.get_value_int(vi_cx); + const int cy = section_tailer_key.get_value_int(vi_cy); + const int cz = section_tailer_key.get_value_int(vi_cz); + __int32* span_start_list = reinterpret_cast<__int32*>(w); + span_start_list_ofs[i] = w - body_start; + w += 4 * cx * cy; + __int32* span_end_list = reinterpret_cast<__int32*>(w); + span_end_list_ofs[i] = w - body_start; + w += 4 * cx * cy; + byte* span_data_start = w; + span_data_ofs[i] = w - body_start; + int span_i = 0; + for (int y = 0; y < cy; y++) + { + const Cxif_key& yi = section_body_key.open_key_read(y); + for (int x = 0; x < cx; x++) + { + byte* span_start = w; + const Cxif_key& xi = yi.open_key_read(x); + int z = 0; + for (auto& i : xi.m_keys) + { + int z_inc = i.first - z; + z = i.first + 1; + *w++ = z_inc; + *w++ = 1; + *w++ = i.second.get_value_int(vi_color); + *w++ = i.second.get_value_int(vi_surface_normal); + *w++ = 1; + } + if (span_start == w) + { + span_start_list[span_i] = -1; + span_end_list[span_i] = -1; + } + else + { + if (z != cz) + { + *w++ = cz - z; + *w++ = 0; + *w++ = 0; + } + span_start_list[span_i] = span_start - span_data_start; + span_end_list[span_i] = w - span_data_start - 1; + } + span_i++; + } + } + } + header.size = w - body_start; + for (i = 0; i < c_sections; i++) + { + const Cxif_key& section_key = body_key.open_key_read(i); + const Cxif_key& section_tailer_key = section_key.open_key_read(vi_tailer); + t_vxl_section_tailer& section_tailer = *reinterpret_cast(w); + + section_tailer.span_start_ofs = span_start_list_ofs[i]; + section_tailer.span_end_ofs = span_end_list_ofs[i]; + section_tailer.span_data_ofs = span_data_ofs[i]; + section_tailer.scale = 0; + for (int ty = 0; ty < 3; ty++) + { + for (int tx = 0; tx < 4; tx++) + section_tailer.transform[ty][tx] = 0; + } + section_tailer.x_min_scale = section_tailer_key.get_value_int(vi_x_min) / 1000000.0; + section_tailer.y_min_scale = section_tailer_key.get_value_int(vi_y_min) / 1000000.0; + section_tailer.z_min_scale = section_tailer_key.get_value_int(vi_z_min) / 1000000.0; + section_tailer.x_max_scale = section_tailer_key.get_value_int(vi_x_max) / 1000000.0; + section_tailer.y_max_scale = section_tailer_key.get_value_int(vi_y_max) / 1000000.0; + section_tailer.z_max_scale = section_tailer_key.get_value_int(vi_z_max) / 1000000.0; + section_tailer.cx = section_tailer_key.get_value_int(vi_cx); + section_tailer.cy = section_tailer_key.get_value_int(vi_cy); + section_tailer.cz = section_tailer_key.get_value_int(vi_cz); + section_tailer.unknown = 2; + w += sizeof(t_vxl_section_tailer); + } + delete[] span_data_ofs; + delete[] span_end_list_ofs; + delete[] span_start_list_ofs; + d.set_size(w - d.data()); + return d; +} + +Cvirtual_binary vxl_file_write(const byte* s, const byte* s_normals, int cx, int cy, int cz) +{ + Cxif_key k; + Cxif_key& header = k.open_key_write(vi_header); + Cxif_key& palet = header.open_key_write(vi_palet); + for (int i = 0; i < 256; i++) + { + Cxif_key& palet_entry = palet.open_key_write(i); + palet_entry.set_value_int(vi_red, i); + palet_entry.set_value_int(vi_green, i); + palet_entry.set_value_int(vi_blue, i); + } + Cxif_key& body = k.open_key_write(vi_body); + { + Cxif_key& section = body.open_key_write(0); + Cxif_key& header = section.open_key_write(vi_header); + header.set_value_string(vi_id, "NONE"); + Cxif_key& body = section.open_key_write(vi_body); + for (int y = 0; y < cy; y++) + { + Cxif_key& yi = body.open_key_write(y); + for (int x = 0; x < cx; x++) + { + Cxif_key& xi = yi.open_key_write(x); + const byte* r = s + x + cx * y; + for (int z = 0; z < cz; z++) + { + int v = *r; + if (v) + { + Cxif_key& zi = xi.open_key_write(z); + zi.set_value_int(vi_color, v); + zi.set_value_int(vi_surface_normal, s_normals ? s_normals[r - s]: -1); + } + r += cx * cy; + } + } + } + Cxif_key& tailer = section.open_key_write(vi_tailer); + tailer.set_value_int(vi_x_min, cx * -1000000 / 2); + tailer.set_value_int(vi_y_min, cy * -1000000 / 2); + tailer.set_value_int(vi_z_min, cz * -1000000 / 2); + tailer.set_value_int(vi_x_max, cx * +1000000 / 2); + tailer.set_value_int(vi_y_max, cy * +1000000 / 2); + tailer.set_value_int(vi_z_max, cz * +1000000 / 2); + tailer.set_value_int(vi_cx, cx); + tailer.set_value_int(vi_cy, cy); + tailer.set_value_int(vi_cz, cz); + } + return vxl_file_write(k); +} + +struct t_voxel +{ + int x; + int y; + int z; + int color; + int normal; +}; + +Cvirtual_binary vxl_file_write(Cvirtual_tfile s) +{ + using t_list = list; + + t_list list; + + int cs = 0; + int cx = 0; + int cy = 0; + int cz = 0; + while (!s.eof()) + { + Cmulti_line l = s.read_line(); + t_voxel e; + int s = l.get_next_int(','); + e.x = l.get_next_int(','); + e.y = l.get_next_int(','); + e.z = l.get_next_int(','); + e.normal = l.get_next_int(','); + e.color = l.get_next_int(','); + if (!s) + list.push_back(e); + cs = max(cs, s + 1); + cx = max(cx, e.x + 1); + cy = max(cy, e.y + 1); + cz = max(cz, e.z + 1); + } + Cvirtual_binary colors(NULL, cx * cy * cz); + Cvirtual_binary normals(NULL, cx * cy * cz); + colors.memset(0); + normals.memset(0); + for (auto& e : list) + { + int o = e.x + cx * (e.y + cy * e.z); + colors.data_edit()[o] = e.color; + normals.data_edit()[o] = e.normal; + } + return vxl_file_write(colors.data(), normals.data(), cx, cy, cz); +} + +#endif + +struct t_vxl4_header +{ + unsigned __int32 c_sections; +}; + +struct t_vxl4_section_header +{ + char id[16]; + __int32 section_i; + float scale; + float x_min_scale; + float y_min_scale; + float z_min_scale; + float x_max_scale; + float y_max_scale; + float z_max_scale; + unsigned __int8 cx; + unsigned __int8 cy; + unsigned __int8 cz; + __int8 unknown; +}; + +int vxl_encode4(const Cvxl_file& f, byte* d) +{ + const int c_sections = f.get_c_section_headers(); + + byte* w = d; + t_vxl4_header& header = *reinterpret_cast(w); + header.c_sections = c_sections; + w += sizeof(t_vxl4_header); + + for (int i = 0; i < c_sections; i++) + { + const t_vxl_section_header& s_section_header = *f.get_section_header(i); + const t_vxl_section_tailer& section_tailer = *f.get_section_tailer(i); + const int cx = section_tailer.cx; + const int cy = section_tailer.cy; + const int cz = section_tailer.cz; + + t_vxl4_section_header& section_header = *reinterpret_cast(w); + strcpy(section_header.id, s_section_header.id); + section_header.section_i = s_section_header.section_i; + assert(s_section_header.section_i == i); + section_header.scale = section_tailer.scale; + section_header.x_min_scale = section_tailer.x_min_scale; + section_header.y_min_scale = section_tailer.y_min_scale; + section_header.z_min_scale = section_tailer.z_min_scale; + section_header.x_max_scale = section_tailer.x_max_scale; + section_header.y_max_scale = section_tailer.y_max_scale; + section_header.z_max_scale = section_tailer.z_max_scale; + section_header.cx = section_tailer.cx; + section_header.cy = section_tailer.cy; + section_header.cz = section_tailer.cz; + section_header.unknown = section_tailer.unknown; + w += sizeof(t_vxl4_section_header); + for (int j = 0; j < f.get_c_spans(i); j++) + { + const byte* r = f.get_span_data(i, j); + if (r) + { + int z = 0; + while (z < cz) + { + int z_inc = *w++ = *r++; + if (z_inc == cz) + break; + z += z_inc; + int c = *w++ = *r++; + while (c--) + { + *w++ = *r++; + *w++ = *r++; + z++; + } + r++; + } + } + else + *w++ = cz; + } + } + return w - d; +} + +int vxl_decode4_size(const byte* s) +{ + const byte* r = s; + const t_vxl4_header& s_header = *reinterpret_cast(r); + const int c_sections = s_header.c_sections; + r += sizeof(t_vxl4_header); + int w = 0; + for (int i = 0; i < c_sections; i++) + { + const t_vxl4_section_header& section_header = *reinterpret_cast(r); + const int cx = section_header.cx; + const int cy = section_header.cy; + const int cz = section_header.cz; + w += 8 * cx * cy; + r += sizeof(t_vxl4_section_header); + for (int j = 0; j < cx * cy; j++) + { + int z = 0; + while (z < cz) + { + int z_inc = *r++; + if (z_inc == cz) + break; + z += z_inc; + int count = *r++; + r += 2 * count; + w += 2 * count + 3; + z += count; + } + } + } + return w + + sizeof(t_vxl_header) + + (sizeof(t_vxl_section_header) + sizeof(t_vxl_section_tailer)) * c_sections; +} + +Cvirtual_binary vxl_decode4(const byte* s, int cb_d) +{ + Cvirtual_binary d; + const byte* r = s; + const t_vxl4_header& s_header = *reinterpret_cast(r); + const int c_sections = s_header.c_sections; + r += sizeof(t_vxl4_header); + byte* w = d.write_start(cb_d ? cb_d : 1 << 20); + t_vxl_header& header = *reinterpret_cast(w); + strcpy(header.id, vxl_id); + header.one = 1; + header.c_section_headers = c_sections; + header.c_section_tailers = c_sections; + header.unknown = 0x1f10; + w += sizeof(t_vxl_header); + t_vxl_section_header* d_section_header = reinterpret_cast(w); + t_vxl_section_tailer* section_tailer = new t_vxl_section_tailer[c_sections]; + w += sizeof(t_vxl_section_header) * c_sections; + byte* body_start = w; + for (int i = 0; i < c_sections; i++) + { + const t_vxl4_section_header& section_header = *reinterpret_cast(r); + const int cx = section_header.cx; + const int cy = section_header.cy; + const int cz = section_header.cz; + strcpy(d_section_header->id, section_header.id); + d_section_header->section_i = section_header.section_i; + d_section_header->one = 1; + d_section_header->zero = 0; + d_section_header++; + __int32* span_start_list = reinterpret_cast<__int32*>(w); + section_tailer[i].span_start_ofs = w - body_start; + w += 4 * cx * cy; + __int32* span_end_list = reinterpret_cast<__int32*>(w); + section_tailer[i].span_end_ofs = w - body_start; + w += 4 * cx * cy; + section_tailer[i].span_data_ofs = w - body_start; + section_tailer[i].scale = section_header.scale; + section_tailer[i].x_min_scale = section_header.x_min_scale; + section_tailer[i].y_min_scale = section_header.y_min_scale; + section_tailer[i].z_min_scale = section_header.z_min_scale; + section_tailer[i].x_max_scale = section_header.x_max_scale; + section_tailer[i].y_max_scale = section_header.y_max_scale; + section_tailer[i].z_max_scale = section_header.z_max_scale; + section_tailer[i].cx = section_header.cx; + section_tailer[i].cy = section_header.cy; + section_tailer[i].cz = section_header.cz; + section_tailer[i].unknown = section_header.unknown; + r += sizeof(t_vxl4_section_header); + byte* span_data_start = w; + for (int j = 0; j < cx * cy; j++) + { + byte* span_start = w; + int z = 0; + while (z < cz) + { + int z_inc = *r++; + if (z_inc == cz) + break; + z += *w++ = z_inc; + int count = *w++ = *r++; + int c = count; + while (c--) + { + *w++ = *r++; + *w++ = *r++; + z++; + } + *w++ = count; + } + if (span_start == w) + { + span_start_list[j] = -1; + span_end_list[j] = -1; + } + else + { + span_start_list[j] = span_start - span_data_start; + span_end_list[j] = w - span_data_start - 1; + } + } + } + header.size = w - body_start; + memcpy(w, section_tailer, sizeof(t_vxl_section_tailer) * c_sections); + delete[] section_tailer; + w += sizeof(t_vxl_section_tailer) * c_sections; + assert(!cb_d || d.size() == w - d.data()); + return cb_d ? d : Cvirtual_binary(d.data(), w - d.data()); +} diff --git a/3rdParty/xcc/misc/vxl_file.h b/3rdParty/xcc/misc/vxl_file.h new file mode 100644 index 0000000..5dd1857 --- /dev/null +++ b/3rdParty/xcc/misc/vxl_file.h @@ -0,0 +1,106 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "cc_file_sh.h" +#include "cc_structures.h" +#include "fname.h" +#include "virtual_tfile.h" +#ifndef XCC_MINIMAL_BUILD +#include "xif_key.h" +#endif + +class Cvxl_file : public Ccc_file_sh +{ +public: +#ifndef XCC_MINIMAL_BUILD + int extract_as_pcx(const Cfname& name, t_file_type ft, const t_palet _palet) const; +#endif + ostream& extract_as_text(ostream& os) const; +#ifndef XCC_MINIMAL_BUILD + int extract_as_xif(const string& name) const; +#endif + bool is_valid() const; + + int get_c_section_headers() const + { + return header().c_section_headers; + } + + int get_c_spans(int i) const + { + return get_section_tailer(i)->span_end_ofs - get_section_tailer(i)->span_start_ofs >> 2; + } + + int get_c_section_tailers() const + { + return header().c_section_tailers; + } + + const t_palet_entry* get_palet() const + { + return header().palet; + } + + const byte* get_section_body() const + { + return data() + sizeof(t_vxl_header) + sizeof(t_vxl_section_header) * get_c_section_tailers(); + } + + const t_vxl_section_header* get_section_header(int i) const + { + return reinterpret_cast(data() + sizeof(t_vxl_header) + sizeof(t_vxl_section_header) * i); + } + + const t_vxl_section_tailer* get_section_tailer(int i) const + { + return reinterpret_cast(data() + get_size() + sizeof(t_vxl_section_tailer) * (i - get_c_section_tailers())); + } + + const byte* get_span_data(int i, int j) const + { + if (get_span_start_list(i)[j] == -1) + return NULL; + return get_section_body() + get_section_tailer(i)->span_data_ofs + get_span_start_list(i)[j]; + } + + int get_span_size(int i, int j) const + { + return get_span_end_list(i)[j] - get_span_start_list(i)[j] + 1; + } + + const int* get_span_start_list(int i) const + { + return reinterpret_cast(get_section_body() + get_section_tailer(i)->span_start_ofs); + } + + const int* get_span_end_list(int i) const + { + return reinterpret_cast(get_section_body() + get_section_tailer(i)->span_end_ofs); + } +}; + +int vxl_decode4_size(const byte* s); +Cvirtual_binary vxl_decode4(const byte* s, int cb_d); +int vxl_encode4(const Cvxl_file& f, byte* d); +#ifndef XCC_MINIMAL_BUILD +Cvirtual_binary vxl_file_write(const Cxif_key& s); +Cvirtual_binary vxl_file_write(const byte* s, const byte* s_normals, int cx, int cy, int cz); +Cvirtual_binary vxl_file_write(Cvirtual_tfile s); +#endif diff --git a/3rdParty/xcc/misc/win_handle.cpp b/3rdParty/xcc/misc/win_handle.cpp new file mode 100644 index 0000000..ce6f97d --- /dev/null +++ b/3rdParty/xcc/misc/win_handle.cpp @@ -0,0 +1,36 @@ +/* + XCC Utilities and Library + Copyright (C) 2002 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "win_handle.h" + +int create_process(const std::string& exe_name, const std::string& _cmd_line, bool wait) +{ + char cmd_line[256]; + strcpy(cmd_line, ("\"" + exe_name + "\" " + _cmd_line).c_str()); + STARTUPINFO si; + memset(&si, 0, sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + PROCESS_INFORMATION pi; + int error = !CreateProcess(exe_name.c_str(), cmd_line, NULL, NULL, false, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &si, &pi); + if (!error && wait) + WaitForSingleObject(pi.hProcess, INFINITE); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return error; +} diff --git a/3rdParty/xcc/misc/win_handle.h b/3rdParty/xcc/misc/win_handle.h new file mode 100644 index 0000000..9d49d92 --- /dev/null +++ b/3rdParty/xcc/misc/win_handle.h @@ -0,0 +1,50 @@ +/* + XCC Utilities and Library + Copyright (C) 2002 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include +#include +#include + +template +class Cwin_handle_base +{ +public: + Cwin_handle_base() = default; + + explicit Cwin_handle_base(T h) : m_source(h == INVALID_HANDLE_VALUE ? NULL : h, CloseHandle) + { + } + + void clear() + { + m_source.reset(); + } + + operator T() const + { + return static_cast(m_source.get()); + } +private: + std::shared_ptr m_source; +}; + +using Cwin_handle = Cwin_handle_base; + +int create_process(const std::string& exe_name, const std::string& _cmd_line = "", bool wait = false); diff --git a/3rdParty/xcc/misc/xcc/data_ref.h b/3rdParty/xcc/misc/xcc/data_ref.h new file mode 100644 index 0000000..685d4b5 --- /dev/null +++ b/3rdParty/xcc/misc/xcc/data_ref.h @@ -0,0 +1,66 @@ +/* + XCC Utilities and Library + Copyright (C) 2021 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include + +template +class data_ref_base : public std::span +{ +private: + using base_t = std::span; +public: + data_ref_base() = default; + + template + data_ref_base(const V& v, typename std::enable_if_t::value>* = 0) + { + if (v.end() != v.begin()) + assign(&*v.begin(), v.end() - v.begin() + &*v.begin()); + } + + template + data_ref_base(V& v, typename std::enable_if::value>* = 0) + { + if (v.end() != v.begin()) + assign(&*v.begin(), v.end() - v.begin() + &*v.begin()); + } + + data_ref_base(U begin, U end) + { + assign(begin, end); + } + + data_ref_base(U begin, size_t size) + { + assign(begin, size); + } + + void assign(U begin, U end) + { + static_cast(*this) = base_t(reinterpret_cast(begin), reinterpret_cast(end)); + } + + void assign(U begin, size_t size) + { + assign(begin, reinterpret_cast(begin) + size); + } +}; + +using data_ref = data_ref_base; diff --git a/3rdParty/xcc/misc/xcc/find_ptr.h b/3rdParty/xcc/misc/xcc/find_ptr.h new file mode 100644 index 0000000..0ec2a11 --- /dev/null +++ b/3rdParty/xcc/misc/xcc/find_ptr.h @@ -0,0 +1,86 @@ +/* + XCC Utilities and Library + Copyright (C) 2021 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +template +const typename T::value_type::second_type* find_ptr(const T& c, const U& v) +{ + typename T::const_iterator i = c.find(v); + return i == c.end() ? NULL : &i->second; +} + +template +typename T::value_type::second_type* find_ptr(T& c, const U& v) +{ + typename T::iterator i = c.find(v); + return i == c.end() ? NULL : &i->second; +} + +template +const typename T::value_type::second_type& find_ptr2(const T& c, const U& v) +{ + static typename T::value_type::second_type z = typename T::value_type::second_type(); + typename T::const_iterator i = c.find(v); + return i == c.end() ? z : i->second; +} + +template +typename T::value_type::second_type& find_ptr2(T& c, const U& v) +{ + static typename T::value_type::second_type z = typename T::value_type::second_type(); + typename T::iterator i = c.find(v); + return i == c.end() ? z : i->second; +} + +template +const typename T::value_type* find_ptr0(const T& c, const U& v) +{ + typename T::const_iterator i = c.find(v); + return i == c.end() ? NULL : &*i; +} + +template +typename T::value_type::second_type& find_ref(T& c, const U& v) +{ + typename T::iterator i = c.find(v); + assert(i != c.end()); + return i->second; +} + +template +const typename T::value_type::second_type& find_ref(const T& c, const U& v) +{ + typename T::const_iterator i = c.find(v); + assert(i != c.end()); + return i->second; +} + +template +const typename T::value_type::second_type& find_ref(const T& c, const U& v, const typename T::value_type::second_type& z) +{ + typename T::const_iterator i = c.find(v); + return i == c.end() ? z : i->second; +} + +template +typename T::value_type::second_type& find_ref(T& c, const U& v, typename T::value_type::second_type& z) +{ + typename T::iterator i = c.find(v); + return i == c.end() ? z : i->second; +} diff --git a/3rdParty/xcc/misc/xcc/string_view.h b/3rdParty/xcc/misc/xcc/string_view.h new file mode 100644 index 0000000..6b6484f --- /dev/null +++ b/3rdParty/xcc/misc/xcc/string_view.h @@ -0,0 +1,68 @@ +/* + XCC Utilities and Library + Copyright (C) 2021 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include +#include +#include + +inline std::string& operator<<(std::string& a, std::string_view b) +{ + return a += b; +} + +template +inline std::enable_if_t::value, std::string&> operator<<(std::string& a, T b) +{ + return a += std::to_string(b); +} + +inline float to_float(std::string_view s) +{ + float v; + auto res = std::from_chars(s.data(), s.data() + s.size(), v); + return res.ec == std::errc() && res.ptr == s.data() + s.size() ? v : 0; +} + +inline long long to_int(std::string_view s) +{ + long long v; + auto res = std::from_chars(s.data(), s.data() + s.size(), v); + return res.ec == std::errc() && res.ptr == s.data() + s.size() ? v : 0; +} + +template +std::string_view to_string_view(const std::array& v) +{ + return std::string_view(v.data(), v.size()); +} + +template +std::string_view to_string_view(const std::array& v) +{ + return std::string_view(reinterpret_cast(v.data()), v.size()); +} + +inline std::string_view read_until(std::string_view& v, char sep, bool keep_sep = false) +{ + size_t i = v.find(sep); + std::string_view ret = v.substr(0, i); + v.remove_prefix(i == std::string_view::npos ? v.size() : keep_sep ? i : i + 1); + return ret; +} diff --git a/3rdParty/xcc/misc/xcc_dirs.cpp b/3rdParty/xcc/misc/xcc_dirs.cpp new file mode 100644 index 0000000..a8cb29a --- /dev/null +++ b/3rdParty/xcc/misc/xcc_dirs.cpp @@ -0,0 +1,417 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "xcc_dirs.h" + +#include +#include +#include +#include "reg_key.h" +#include "string_conversion.h" +#include "xcc_registry.h" + +bool g_enable_log = false; +static string dune2_dir; +static string td_primary_dir; +static string td_secondary_dir; +static string cd_dir; +static string data_dir; +static string ra_dir; +static string dune2000_dir; +static string ts_dir; +static string ra2_dir; +static string nox_dir; +static string rg_dir; +static string gr_dir; +static string gr_zh_dir; +static string ebfd_dir; +static string bfme_dir; +static string tw_dir; + +bool xcc_dirs::enable_log() +{ + return g_enable_log; +} + +string xcc_dirs::get_dir(t_game game) +{ + switch (game) + { + case game_td: + return td_primary_dir; + case game_ra: + return ra_dir; + case game_ts: + case game_ts_fs: + return ts_dir; + case game_dune2: + return dune2_dir; + case game_dune2000: + return dune2000_dir; + case game_ra2: + case game_ra2_yr: + return ra2_dir; + case game_nox: + return nox_dir; + case game_rg: + return rg_dir; + case game_gr: + return gr_dir; + case game_gr_zh: + return gr_zh_dir; + case game_ebfd: + return ebfd_dir; + case game_bfme: + return bfme_dir; + case game_tw: + return tw_dir; + } + assert(false); + return ""; +} + +string xcc_dirs::get_exe(t_game game) +{ + switch (game) + { + case game_td: + return td_primary_dir + "c&c95.exe"; + case game_ra: + return ra_dir + "ra95.exe"; + case game_ts: + return ts_dir + "sun.exe"; + case game_dune2: + return dune2_dir + "dune2.exe"; + case game_dune2000: + return dune2000_dir + "dune2000.exe"; + case game_ra2: + return ra2_dir + "ra2.exe"; + case game_nox: + return nox_dir + "nox.exe"; + case game_ra2_yr: + return ra2_dir + "ra2md.exe"; + case game_gr: + return gr_dir + "generals.exe"; + case game_bfme: + return bfme_dir + "lotrbfme.exe"; + } + assert(false); + return ""; +} + +string xcc_dirs::get_audio_mix(t_game game) +{ + switch (game) + { + case game_ra2: + return "audio.mix"; + case game_ra2_yr: + return "audiomd.mix"; + } + assert(false); + return ""; +} + +string xcc_dirs::get_csf_fname(t_game game) +{ + switch (game) + { + case game_ra2: + return "ra2.csf"; + case game_ra2_yr: + return "ra2md.csf"; + case game_gr: + case game_gr_zh: + return "data/english/generals.csf"; + } + assert(false); + return ""; +} + +static string get_suffix(t_game game) +{ + return game == game_ra2_yr ? "md" : ""; +} + +string xcc_dirs::get_ecache_mix(t_game game, bool dir, int i) +{ + return get_ecache_mix(game, dir, nwzl(2, i)); +} + +string xcc_dirs::get_ecache_mix(t_game game, bool dir, const string& s) +{ + string r = "ecache" + get_suffix(game) + s + ".mix"; + if (dir) + r = get_dir(game) + r; + return r; +} + +string xcc_dirs::get_expand_mix(t_game game, int i) +{ + return get_expand_mix(game, nwzl(2, i)); +} + +string xcc_dirs::get_expand_mix(t_game game, const string& s) +{ + return get_dir(game) + "expand" + get_suffix(game) + s + ".mix"; +} + +string xcc_dirs::get_language_mix(t_game game) +{ + switch (game) + { + case game_ra2: + return ra2_dir + "language.mix"; + case game_ra2_yr: + return ra2_dir + "langmd.mix"; + case game_gr: + return gr_dir + "english.big"; + case game_gr_zh: + return gr_zh_dir + "englishzh.big"; + } + assert(false); + return ""; +} + +string xcc_dirs::get_local_mix(t_game game) +{ + switch (game) + { + case game_ts: + case game_ra2: + return "local.mix"; + case game_ra2_yr: + return "localmd.mix"; + } + assert(false); + return ""; +} + +string xcc_dirs::get_main_mix(t_game game) +{ + switch (game) + { + case game_ra: + return ra_dir + "redalert.mix"; + case game_ts: + return ts_dir + "tibsun.mix"; + case game_ra2: + return ra2_dir + "ra2.mix"; + case game_ra2_yr: + return ra2_dir + "ra2md.mix"; + } + assert(false); + return ""; +} + +static void set_path(string s, string& path) +{ + boost::to_lower(s); + if (!s.empty() && s.back() != '\\') + s += '\\'; + path = s; +} + +void xcc_dirs::set_dir(t_game game, const string &s) +{ + switch (game) + { + case game_td: + set_path(s, td_primary_dir); + break; + case game_ra: + set_path(s, ra_dir); + break; + case game_ts: + set_path(s, ts_dir); + break; + case game_dune2: + set_path(s, dune2_dir); + break; + case game_dune2000: + set_path(s, dune2000_dir); + break; + case game_ra2: + set_path(s, ra2_dir); + break; + case game_nox: + set_path(s, nox_dir); + break; + case game_rg: + set_path(s, rg_dir); + break; + case game_gr: + set_path(s, gr_dir); + break; + case game_gr_zh: + set_path(s, gr_zh_dir); + break; + case game_ebfd: + set_path(s, ebfd_dir); + break; + case game_bfme: + set_path(s, bfme_dir); + break; + case game_tw: + set_path(s, tw_dir); + break; + default: + assert(false); + } +} + +void xcc_dirs::set_td_secondary_dir(const string& s) +{ + set_path(s, td_secondary_dir); +} + +void xcc_dirs::set_cd_dir(const string& s) +{ + set_path(s, cd_dir); +} + +void xcc_dirs::set_data_dir(const string& s) +{ + set_path(s, data_dir); +} + +void xcc_dirs::reset_cd_dir() +{ + int drive_map = GetLogicalDrives(); + char drive_root[] = "a:\\"; + for (int i = 0; i < 26; i++) + { + if (drive_map >> i & 1 && GetDriveTypeA(drive_root) == DRIVE_CDROM) + { + set_cd_dir(drive_root); + break; + } + drive_root[0]++; + } +} + +void xcc_dirs::reset_data_dir() +{ + set_data_dir(GetModuleFileName().get_path()); +} + +static void read_dir(const string& key, const string& value, t_game game) +{ + Creg_key h; + string s; + if (xcc_dirs::get_dir(game).empty() + && ERROR_SUCCESS == h.open(HKEY_LOCAL_MACHINE, key, KEY_QUERY_VALUE) + && ERROR_SUCCESS == h.query_value(value, s)) + xcc_dirs::set_dir(game, Cfname(s).get_path()); +} + +void xcc_dirs::load_from_registry() +{ + Creg_key kh_base; + if (!Cxcc_registry::get_base_key(kh_base)) + { + string s; + if (ERROR_SUCCESS == kh_base.query_value("dune2_dir", s)) + set_dir(game_dune2, s); + if (ERROR_SUCCESS == kh_base.query_value("dir1", s)) + set_dir(game_td, s); + if (ERROR_SUCCESS == kh_base.query_value("dir2", s)) + set_td_secondary_dir(s); + if (ERROR_SUCCESS == kh_base.query_value("ra_dir", s)) + set_dir(game_ra, s); + if (ERROR_SUCCESS == kh_base.query_value("cd_dir", s)) + set_cd_dir(s); + if (ERROR_SUCCESS == kh_base.query_value("data_dir", s)) + set_data_dir(s); + if (ERROR_SUCCESS == kh_base.query_value("enable_log", s)) + g_enable_log = true; + } + if (cd_dir.empty()) + reset_cd_dir(); + if (data_dir.empty()) + reset_data_dir(); + read_dir("Software\\Westwood\\Dune 2", "InstallPath", game_dune2); + read_dir("Software\\Westwood\\Command & Conquer Windows 95 Edition", "InstallPath", game_td); + read_dir("Software\\Westwood\\Red Alert Windows 95 Edition", "InstallPath", game_ra); + read_dir("Software\\Westwood\\Dune 2000", "InstallPath", game_dune2000); + read_dir("Software\\Westwood\\Tiberian Sun", "InstallPath", game_ts); + read_dir("Software\\Westwood\\Red Alert 2", "InstallPath", game_ra2); + read_dir("Software\\Westwood\\Nox", "InstallPath", game_nox); + read_dir("Software\\Westwood\\Renegade", "InstallPath", game_rg); + read_dir("Software\\Westwood\\Emperor", "InstallPath", game_ebfd); + /* + read_dir("Software\\Electronic Arts\\EA Games\\Generals", "InstallPath", game_gr); + read_dir("Software\\Electronic Arts\\EA Games\\Command and Conquer Generals Zero Hour", "InstallPath", game_gr_zh); + read_dir("Software\\Electronic Arts\\EA Games\\The Battle for Middle-earth", "InstallPath", game_bfme); + read_dir("Software\\Electronic Arts\\Electronic Arts\\Command and Conquer 3", "InstallPath", game_tw); + */ +} + +void xcc_dirs::save_to_registry() +{ + Creg_key kh_base; + if (Cxcc_registry::get_base_key(kh_base)) + return; + kh_base.set_value("dune2_dir", dune2_dir); + kh_base.set_value("dir1", td_primary_dir); + kh_base.set_value("dir2", td_secondary_dir); + kh_base.set_value("ra_dir", ra_dir); +}; + +string xcc_dirs::find_file(Cfname s) +{ + if (!s.get_path().empty() || s.exists()) + return s; + s.set_path(td_primary_dir); + if (s.exists()) + return s; + s.set_path(td_secondary_dir); + if (s.exists()) + return s; + s.set_path(ra_dir); + if (s.exists()) + return s; + s.set_path(ts_dir); + if (s.exists()) + return s; + s.set_path(ra2_dir); + if (s.exists()) + return s; + s.set_path(cd_dir); + return s; +} + +bool xcc_dirs::is_available(t_game game) +{ + return Cfname(get_exe(game)).exists(); +} + +const string& xcc_dirs::get_td_secondary_dir() +{ + return td_secondary_dir; +} + +const string& xcc_dirs::get_cd_dir() +{ + return cd_dir; +} + +const string& xcc_dirs::get_data_dir() +{ + return data_dir; +} diff --git a/3rdParty/xcc/misc/xcc_dirs.h b/3rdParty/xcc/misc/xcc_dirs.h new file mode 100644 index 0000000..8f374d1 --- /dev/null +++ b/3rdParty/xcc/misc/xcc_dirs.h @@ -0,0 +1,52 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "cc_structures.h" +#include "fname.h" + +class xcc_dirs +{ +public: + static bool enable_log(); + static void load_from_registry(); + static void save_to_registry(); + static string find_file(Cfname s); + static bool is_available(t_game game); + static string get_audio_mix(t_game game); + static string get_csf_fname(t_game game); + static string get_dir(t_game game); + static string get_exe(t_game game); + static string get_ecache_mix(t_game game, bool dir, int i); + static string get_ecache_mix(t_game game, bool dir, const string& s); + static string get_expand_mix(t_game game, int i); + static string get_expand_mix(t_game game, const string& s); + static string get_language_mix(t_game game); + static string get_local_mix(t_game game); + static string get_main_mix(t_game game); + static void set_td_secondary_dir(const string& s); + static void set_cd_dir(const string &s); + static void set_data_dir(const string &s); + static void set_dir(t_game game, const string& s); + static void reset_cd_dir(); + static void reset_data_dir(); + static const string& get_td_secondary_dir(); + static const string& get_cd_dir(); + static const string& get_data_dir(); +}; diff --git a/3rdParty/xcc/misc/xcc_file.h b/3rdParty/xcc/misc/xcc_file.h new file mode 100644 index 0000000..d063e38 --- /dev/null +++ b/3rdParty/xcc/misc/xcc_file.h @@ -0,0 +1,48 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include +#include + +enum t_xcc_ft +{ + xcc_ft_lmd, xcc_ft_xif, xcc_ft_unknown +}; + +const char* xcc_ft_name[]; + +class Cxcc_file : public Ccc_file_sh +{ +public: + bool is_valid() const + { + const t_xcc_header& h = header(); + int size = get_size(); + return !(sizeof(t_xcc_header) > size || + strcmp(h.id, xcc_id) || + h.size != size || + h.version); + } + + t_xcc_ft get_ft() const + { + return static_cast(header().type); + } +}; diff --git a/3rdParty/xcc/misc/xcc_file_sh.h b/3rdParty/xcc/misc/xcc_file_sh.h new file mode 100644 index 0000000..f2fbf69 --- /dev/null +++ b/3rdParty/xcc/misc/xcc_file_sh.h @@ -0,0 +1,31 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "xcc_file.h" + +template +class Cxcc_file_sh : public Cxcc_file +{ +public: + const T& header() const + { + return *reinterpret_cast(data() + sizeof(t_xcc_header)); + } +}; diff --git a/3rdParty/xcc/misc/xcc_lmd_file.h b/3rdParty/xcc/misc/xcc_lmd_file.h new file mode 100644 index 0000000..b5bde8f --- /dev/null +++ b/3rdParty/xcc/misc/xcc_lmd_file.h @@ -0,0 +1,45 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "xcc_file_sh.h" + +class Cxcc_lmd_file : public Cxcc_file_sh +{ +public: + bool is_valid() const + { + return Cxcc_file_sh::is_valid() && get_ft() == xcc_ft_lmd; + } + + t_game get_game() const + { + return static_cast(header().game); + } + + int get_c_fnames() const + { + return header().c_fnames; + } + + const char* get_fnames() const + { + return reinterpret_cast(data() + sizeof(t_xcc_header) + sizeof(t_xcc_lmd_header)); + } +}; diff --git a/3rdParty/xcc/misc/xcc_lmd_file_write.cpp b/3rdParty/xcc/misc/xcc_lmd_file_write.cpp new file mode 100644 index 0000000..23fda02 --- /dev/null +++ b/3rdParty/xcc/misc/xcc_lmd_file_write.cpp @@ -0,0 +1,53 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "xcc_lmd_file_write.h" + +#include "cc_structures.h" +#include "xcc_file.h" + +void Cxcc_lmd_file_write::add_fname(const string& fname) +{ + m_index.push_back(to_lower_copy(fname)); +} + +Cvirtual_binary Cxcc_lmd_file_write::write(t_game game) const +{ + int size = sizeof(t_xcc_header) + sizeof(t_xcc_lmd_header); + for (auto& i : m_index) + size += i.length() + 1; + Cvirtual_binary data; + byte* w = data.write_start(size); + t_xcc_header& header = *reinterpret_cast(w); + strcpy(header.id, xcc_id); + header.size = size; + header.type = xcc_ft_lmd; + header.version = 0; + w += sizeof(t_xcc_header); + t_xcc_lmd_header& lmd_header = *reinterpret_cast(w); + lmd_header.c_fnames = m_index.size(); + lmd_header.game = game; + w += sizeof(t_xcc_lmd_header); + for (auto& i : m_index) + { + strcpy(reinterpret_cast(w), i.c_str()); + w += i.length() + 1; + } + return data; +} \ No newline at end of file diff --git a/3rdParty/xcc/misc/xcc_lmd_file_write.h b/3rdParty/xcc/misc/xcc_lmd_file_write.h new file mode 100644 index 0000000..4e02a8e --- /dev/null +++ b/3rdParty/xcc/misc/xcc_lmd_file_write.h @@ -0,0 +1,35 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include +#include "cc_structures.h" +#include + +using namespace std; + +class Cxcc_lmd_file_write +{ +public: + void add_fname(const string& fname); + Cvirtual_binary write(t_game game) const; +private: + using t_index = vector; + t_index m_index; +}; diff --git a/3rdParty/xcc/misc/xcc_registry.cpp b/3rdParty/xcc/misc/xcc_registry.cpp new file mode 100644 index 0000000..e14c965 --- /dev/null +++ b/3rdParty/xcc/misc/xcc_registry.cpp @@ -0,0 +1,25 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "xcc_registry.h" + +int Cxcc_registry::get_base_key(Creg_key& kh_base) +{ + return ERROR_SUCCESS != kh_base.create(HKEY_CURRENT_USER, "Software\\XCC"); +} diff --git a/3rdParty/xcc/misc/xcc_registry.h b/3rdParty/xcc/misc/xcc_registry.h new file mode 100644 index 0000000..48890e6 --- /dev/null +++ b/3rdParty/xcc/misc/xcc_registry.h @@ -0,0 +1,27 @@ +/* + XCC Utilities and Library + Copyright (C) 2000 Olaf van der Spek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "reg_key.h" + +class Cxcc_registry +{ +public: + static int get_base_key(Creg_key&); +}; diff --git a/3rdParty/xcc/patch.70358b46858973426c1ecf204485cb2a88716217.diff b/3rdParty/xcc/patch.70358b46858973426c1ecf204485cb2a88716217.diff new file mode 100644 index 0000000..497958a --- /dev/null +++ b/3rdParty/xcc/patch.70358b46858973426c1ecf204485cb2a88716217.diff @@ -0,0 +1,769 @@ +diff --git a/Library/StdAfx.h b/Library/StdAfx.h +index f688f65..ce37391 100644 +--- a/Library/StdAfx.h ++++ b/Library/StdAfx.h +@@ -35,7 +35,9 @@ + #include + #include + #include ++#ifndef XCC_MINIMAL_BUILD + #include ++#endif + + using namespace std; + using boost::iequals; +diff --git a/Library/XCC Library.vcxproj b/Library/XCC Library.vcxproj +index 0481daf..857d3f8 100644 +--- a/Library/XCC Library.vcxproj ++++ b/Library/XCC Library.vcxproj +@@ -1,10 +1,18 @@ +  + + ++ ++ DebugMinimal ++ Win32 ++ + + Debug + Win32 + ++ ++ ReleaseMinimal ++ Win32 ++ + + Release + Win32 +@@ -18,18 +26,59 @@ + + + ++ $(SolutionDir)\build\output\$(Configuration)-$(Platform)\lib\ ++ $(SolutionDir)\build\intermediate\$(Configuration)-$(Platform)\$(ProjectName)\ + StaticLibrary +- Static ++ Dynamic ++ MultiByte ++ true ++ v143 ++ ++ ++ $(SolutionDir)\build\output\$(Configuration)-$(Platform)\lib\ ++ $(SolutionDir)\build\intermediate\$(Configuration)-$(Platform)\$(ProjectName)\ ++ StaticLibrary ++ Dynamic + MultiByte + true + v143 + + ++ $(SolutionDir)\build\output\$(Configuration)-$(Platform)\lib\ ++ $(SolutionDir)\build\intermediate\$(Configuration)-$(Platform)\$(ProjectName)\ ++ StaticLibrary ++ Dynamic ++ MultiByte ++ v143 ++ ++ ++ $(SolutionDir)\build\output\$(Configuration)-$(Platform)\lib\ ++ $(SolutionDir)\build\intermediate\$(Configuration)-$(Platform)\$(ProjectName)\ + StaticLibrary + Dynamic + MultiByte + v143 + ++ ++ ++ ++ ++ ++ ++ ++ XCC_MINIMAL_BUILD ++ NO_FT_SUPPORT ++ ++ ++ ++ ++ ++ ++ ++ ++ XCC_MINIMAL_BUILD ++ NO_FT_SUPPORT ++ + + + +@@ -37,10 +86,18 @@ + + + ++ ++ ++ ++ + + + + ++ ++ ++ ++ + + + <_ProjectFileVersion>10.0.30319.1 +@@ -51,7 +108,22 @@ + + + Disabled +- _DEBUG;WIN32;_LIB;JPEG_SUPPORT;OGG_SUPPORT;PNG_SUPPORT;%(PreprocessorDefinitions) ++ _DEBUG;WIN32;_LIB;$(XCC_MINIMAL_BUILD);$(NO_FT_SUPPORT);%(PreprocessorDefinitions) ++ EnableFastChecks ++ MultiThreadedDebugDLL ++ Use ++ stdafx.h ++ stdcpplatest ++ ++ ++ _DEBUG;%(PreprocessorDefinitions) ++ 0x0413 ++ ++ ++ ++ ++ Disabled ++ _DEBUG;WIN32;_LIB;$(XCC_MINIMAL_BUILD);$(NO_FT_SUPPORT);%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + Use +@@ -65,7 +137,7 @@ + + + +- NDEBUG;WIN32;_LIB;JPEG_SUPPORT;OGG_SUPPORT;PNG_SUPPORT;%(PreprocessorDefinitions) ++ NDEBUG;WIN32;_LIB;$(XCC_MINIMAL_BUILD);$(NO_FT_SUPPORT);%(PreprocessorDefinitions) + true + MultiThreaded + true +@@ -78,204 +150,293 @@ + 0x0413 + + ++ ++ ++ NDEBUG;WIN32;_LIB;$(XCC_MINIMAL_BUILD);$(NO_FT_SUPPORT);%(PreprocessorDefinitions) ++ true ++ MultiThreadedDLL ++ true ++ Use ++ stdafx.h ++ stdcpplatest ++ ++ ++ NDEBUG;%(PreprocessorDefinitions) ++ 0x0413 ++ ++ + + ++ true + + ++ true + + ++ true + + ++ true + + ++ true + + ++ true + + ++ true + + ++ true + + + + ++ true + + ++ false + + ++ false + + ++ true + + ++ true + + + + ++ true + + + + + + ++ true + + ++ true + + + + ++ true + + ++ true + + ++ true + + ++ true + + ++ true ++ ++ ++ true + +- + ++ true + + ++ true + + ++ true + + ++ true + + ++ true + + + + ++ true + + + + + + ++ true + + ++ true + + ++ true + + ++ true + + ++ true + + ++ true + + ++ true + + ++ true + + ++ true + + ++ true + + ++ true + + ++ true + + + + ++ true + + ++ true + + ++ true + + ++ true + +- +- ++ ++ true + ++ + ++ true + + ++ true + + + + ++ true + + ++ true + + ++ true + + + + ++ true + + ++ true + + ++ true + + + Create ++ Create + Create ++ Create + + + + ++ true + + ++ true + + ++ true + + ++ true + + + + + + ++ true + +- +- ++ + ++ true + +- +- ++ + ++ true + + ++ true + + ++ true + + ++ true + + + + ++ true + + ++ true + + + + ++ true + + ++ true + + ++ true + +- +- ++ + ++ true + +- +- ++ + ++ true + + ++ true + +- +- ++ + ++ true + + ++ true + + ++ true + + ++ true + + ++ true + + + +@@ -301,7 +462,6 @@ + + + +- + + + +@@ -413,4 +573,13 @@ + + + ++ ++ $(VcpkgRoot) ++ ++ ++ ++ ++ ++ ++ + +\ No newline at end of file +diff --git a/XCC.props b/XCC.props +index f813cc4..5970828 100644 +--- a/XCC.props ++++ b/XCC.props +@@ -15,4 +15,5 @@ + dsound.lib;gdiplus.lib;%(AdditionalDependencies) + + ++ + +diff --git a/misc/cc_file.cpp b/misc/cc_file.cpp +index 13e4976..d9e9e11 100644 +--- a/misc/cc_file.cpp ++++ b/misc/cc_file.cpp +@@ -19,6 +19,7 @@ + #include "stdafx.h" + #include "cc_file.h" + ++#ifndef XCC_MINIMAL_BUILD + #include "aud_file.h" + #include "avi_file.h" + #include "big_file.h" +@@ -70,6 +71,11 @@ + #include "xcc_file.h" + #include "xcc_lmd_file.h" + #include "xif_file.h" ++#else ++#include "mix_file.h" ++#include "xcc_dirs.h" ++#endif ++ + + const char* ft_name[] = + { +diff --git a/misc/image_file.h b/misc/image_file.h +index e107843..b9e9fb5 100644 +--- a/misc/image_file.h ++++ b/misc/image_file.h +@@ -30,12 +30,14 @@ class Cimage_file : public Cvideo_file + public: + virtual void decode(void*) const = 0; + ++#ifndef XCC_MINIMAL_BUILD + virtual Cvirtual_image vimage() const + { + Cvirtual_binary image; + decode(image.write_start(this->cb_image())); + return Cvirtual_image(image, this->cx(), this->cy(), this->cb_pixel(), this->palet()); + } ++#endif + + int cf() const override + { +@@ -43,6 +45,8 @@ public: + } + }; + ++#ifndef XCC_MINIMAL_BUILD + int image_file_write(Cvirtual_file&, t_file_type, const byte* image, const t_palet_entry*, int cx, int cy); + Cvirtual_file image_file_write(t_file_type, const byte* image, const t_palet_entry*, int cx, int cy); + int image_file_write(const string& name, t_file_type, const byte* image, const t_palet_entry*, int cx, int cy); ++#endif +diff --git a/misc/mix_file.cpp b/misc/mix_file.cpp +index 8354059..874ff31 100644 +--- a/misc/mix_file.cpp ++++ b/misc/mix_file.cpp +@@ -19,14 +19,20 @@ + #include + #include "mix_file.h" + ++#ifndef NO_FT_SUPPORT + #include "big_file.h" ++#endif + #include "blowfish.h" + #include "crc.h" + #include "id_log.h" ++#ifndef NO_FT_SUPPORT + #include "mix_cache.h" ++#endif + #include "mix_decode.h" ++#ifndef NO_FT_SUPPORT + #include "mix_rg_file.h" + #include "pak_file.h" ++#endif + #include "string_conversion.h" + #include "xcc_lmd_file.h" + +diff --git a/misc/shp_ts_file.cpp b/misc/shp_ts_file.cpp +index 4950213..db60a92 100644 +--- a/misc/shp_ts_file.cpp ++++ b/misc/shp_ts_file.cpp +@@ -22,7 +22,9 @@ + #include "image_file.h" + #include "shp_decode.h" + #include "string_conversion.h" ++#ifndef XCC_MINIMAL_BUILD + #include "xcc_log.h" ++#endif + + class Cshp_ts_decoder : public Cvideo_decoder + { +@@ -141,6 +143,7 @@ int get_ofs(int x, int y, int cx, int cy) + return x + cx * y; + } + ++#ifndef XCC_MINIMAL_BUILD + int Cshp_ts_file::extract_as_pcx(const Cfname& name, t_file_type ft, const t_palet _palet, bool combine_shadows) const + { + t_palet palet; +@@ -378,6 +381,7 @@ void shp_split_shadows(Cvirtual_image& image) + image.load(d, cx, cy << 1, image.cb_pixel(), image.palet()); + delete[] d; + } ++#endif + + /* + void shp_xor_decode_frames(Cvirtual_image& image, int c_frames) +diff --git a/misc/shp_ts_file.h b/misc/shp_ts_file.h +index b38a053..76261cd 100644 +--- a/misc/shp_ts_file.h ++++ b/misc/shp_ts_file.h +@@ -28,8 +28,10 @@ class Cshp_ts_file : public Cvideo_file + { + public: + Cvideo_decoder* decoder(const t_palet_entry*); ++#ifndef XCC_MINIMAL_BUILD + int extract_as_pcx(const Cfname& name, t_file_type ft, const t_palet palet, bool combine_shadows = false) const; + Cvirtual_image extract_as_pcx_single(const t_palet _palet, bool combine_shadows = false) const; ++#endif + bool is_valid() const; + + int cb_pixel() const +@@ -106,7 +108,10 @@ public: + int shp_decode4_size(const byte* s); + Cvirtual_binary shp_decode4(const byte* s, int cb_d); + int shp_encode4(const Cshp_ts_file& f, byte* d); ++ ++#ifndef XCC_MINIMAL_BUILD + void shp_split_frames(Cvirtual_image& image, int cblocks_x, int cblocks_y); + void shp_split_shadows(Cvirtual_image& image); + void shp_xor_decode_frames(Cvirtual_image& image, int c_frames); + void shp_xor_encode_frames(Cvirtual_image& image, int c_frames); ++#endif +diff --git a/misc/virtual_image.cpp b/misc/virtual_image.cpp +index 5dfc3e2..456ea2d 100644 +--- a/misc/virtual_image.cpp ++++ b/misc/virtual_image.cpp +@@ -21,6 +21,8 @@ + #include + #include + #include ++ ++#ifndef XCC_MINIMAL_BUILD + #include "dds_file.h" + #include "image_file.h" + #include "jpeg_file.h" +@@ -28,6 +30,7 @@ + #include "pcx_file_write.h" + #include "png_file.h" + #include "tga_file.h" ++#endif + #include "virtual_image.h" + + using namespace Gdiplus; +@@ -80,6 +83,8 @@ void Cvirtual_image::load(const void* image, int cx, int cy, int cb_pixel, const + palet(p, inflate); + } + ++#ifndef XCC_MINIMAL_BUILD ++ + int Cvirtual_image::load(const Cvirtual_binary& s) + { + Cdds_file dds_f; +@@ -323,3 +328,5 @@ void Cvirtual_image::increase_palet_depth() + d[i].b = (s[i].b & 63) * 255 / 63; + } + } ++ ++#endif +diff --git a/misc/virtual_image.h b/misc/virtual_image.h +index 2396af8..0a2a2d6 100644 +--- a/misc/virtual_image.h ++++ b/misc/virtual_image.h +@@ -121,3 +121,4 @@ private: + int m_cy = 0; + int mcb_pixel = 0; + }; ++ +diff --git a/misc/vxl_file.cpp b/misc/vxl_file.cpp +index 3132cdf..a629aa1 100644 +--- a/misc/vxl_file.cpp ++++ b/misc/vxl_file.cpp +@@ -21,9 +21,11 @@ + + #include "file32.h" + #include "image_file.h" ++#ifndef XCC_MINIMAL_BUILD + #include "multi_line.h" + #include "pcx_decode.h" + #include "pcx_file_write.h" ++#endif + #include "string_conversion.h" + + bool Cvxl_file::is_valid() const +@@ -51,6 +53,7 @@ bool Cvxl_file::is_valid() const + return true; + } + ++#ifndef XCC_MINIMAL_BUILD + int Cvxl_file::extract_as_pcx(const Cfname& name, t_file_type ft, const t_palet _palet) const + { + t_palet palet; +@@ -98,6 +101,7 @@ int Cvxl_file::extract_as_pcx(const Cfname& name, t_file_type ft, const t_palet + } + return 0; + } ++#endif + + ostream& Cvxl_file::extract_as_text(ostream& os) const + { +@@ -162,6 +166,7 @@ enum + vi_z_max + }; + ++#ifndef XCC_MINIMAL_BUILD + int Cvxl_file::extract_as_xif(const string& name) const + { + Cxif_key k; +@@ -458,6 +463,8 @@ Cvirtual_binary vxl_file_write(Cvirtual_tfile s) + return vxl_file_write(colors.data(), normals.data(), cx, cy, cz); + } + ++#endif ++ + struct t_vxl4_header + { + unsigned __int32 c_sections; +diff --git a/misc/vxl_file.h b/misc/vxl_file.h +index 395f5ac..5dd1857 100644 +--- a/misc/vxl_file.h ++++ b/misc/vxl_file.h +@@ -22,14 +22,20 @@ + #include "cc_structures.h" + #include "fname.h" + #include "virtual_tfile.h" ++#ifndef XCC_MINIMAL_BUILD + #include "xif_key.h" ++#endif + + class Cvxl_file : public Ccc_file_sh + { + public: ++#ifndef XCC_MINIMAL_BUILD + int extract_as_pcx(const Cfname& name, t_file_type ft, const t_palet _palet) const; ++#endif + ostream& extract_as_text(ostream& os) const; ++#ifndef XCC_MINIMAL_BUILD + int extract_as_xif(const string& name) const; ++#endif + bool is_valid() const; + + int get_c_section_headers() const +@@ -93,6 +99,8 @@ public: + int vxl_decode4_size(const byte* s); + Cvirtual_binary vxl_decode4(const byte* s, int cb_d); + int vxl_encode4(const Cvxl_file& f, byte* d); ++#ifndef XCC_MINIMAL_BUILD + Cvirtual_binary vxl_file_write(const Cxif_key& s); + Cvirtual_binary vxl_file_write(const byte* s, const byte* s_normals, int cx, int cy, int cz); + Cvirtual_binary vxl_file_write(Cvirtual_tfile s); ++#endif +diff --git a/vcpkg.json b/vcpkg.json +index e0669e6..92d46dd 100644 +--- a/vcpkg.json ++++ b/vcpkg.json +@@ -5,9 +5,8 @@ + "boost-algorithm", + "boost-crc", + "bzip2", +- "libjpeg-turbo", +- "libpng", +- "libvorbis", +- "lzo" +- ] ++ "lzo", ++ "zlib" ++ ], ++ "builtin-baseline": "45c8b198b7647b6a68235353a00839082c910914" + } diff --git a/3rdParty/xcc/vcpkg.json b/3rdParty/xcc/vcpkg.json new file mode 100644 index 0000000..92d46dd --- /dev/null +++ b/3rdParty/xcc/vcpkg.json @@ -0,0 +1,12 @@ +{ + "name": "xcc", + "version-string": "0", + "dependencies": [ + "boost-algorithm", + "boost-crc", + "bzip2", + "lzo", + "zlib" + ], + "builtin-baseline": "45c8b198b7647b6a68235353a00839082c910914" +} diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,674 @@ + 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 + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/MissionEditor/AITriggerAddDlg.cpp b/MissionEditor/AITriggerAddDlg.cpp new file mode 100644 index 0000000..5f1b6e8 --- /dev/null +++ b/MissionEditor/AITriggerAddDlg.cpp @@ -0,0 +1,81 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// AITriggerAddDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "AITriggerAddDlg.h" +#include "Variables.h" +#include "inlines.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CAITriggerAddDlg + + +CAITriggerAddDlg::CAITriggerAddDlg(CWnd* pParent /*=NULL*/) + : CDialog(CAITriggerAddDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CAITriggerAddDlg) + m_AITrigger = _T(""); + //}}AFX_DATA_INIT +} + + +void CAITriggerAddDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAITriggerAddDlg) + DDX_LBString(pDX, IDC_AITRIGGERS, m_AITrigger); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CAITriggerAddDlg, CDialog) + //{{AFX_MSG_MAP(CAITriggerAddDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CAITriggerAddDlg + +BOOL CAITriggerAddDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CListBox* lb=(CListBox*)GetDlgItem(IDC_AITRIGGERS); + + int i; + for(i=0;iAddString(*ai.sections["AITriggerTypes"].GetValueName(i)+ (CString)" " +GetParam(*ai.sections["AITriggerTypes"].GetValue(i), 0)); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} diff --git a/MissionEditor/AITriggerAddDlg.h b/MissionEditor/AITriggerAddDlg.h new file mode 100644 index 0000000..110e65f --- /dev/null +++ b/MissionEditor/AITriggerAddDlg.h @@ -0,0 +1,66 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_AITRIGGERADDDLG_H__19C60CA1_25D1_11D5_89B2_444553540000__INCLUDED_) +#define AFX_AITRIGGERADDDLG_H__19C60CA1_25D1_11D5_89B2_444553540000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// AITriggerAddDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CAITriggerAddDlg + +class CAITriggerAddDlg : public CDialog +{ +// Konstruktion +public: + CAITriggerAddDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CAITriggerAddDlg) + enum { IDD = IDD_AITRIGGERADD }; + CString m_AITrigger; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CAITriggerAddDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CAITriggerAddDlg) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_AITRIGGERADDDLG_H__19C60CA1_25D1_11D5_89B2_444553540000__INCLUDED_ diff --git a/MissionEditor/AITriggerTypes.cpp b/MissionEditor/AITriggerTypes.cpp new file mode 100644 index 0000000..27fc459 --- /dev/null +++ b/MissionEditor/AITriggerTypes.cpp @@ -0,0 +1,827 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// AITriggerTypes.cpp: implementation file +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "AITriggerTypes.h" +#include "Mapdata.h" +#include "structs.h" +#include "variables.h" +#include "functions.h" +#include "inlines.h" + + +// AI trigger type enumeration +enum AITriggerEnum { + AIT_NONE = -1, + AIT_ENEMY_OWNS_X_COND_N = 0, + AIT_HOUSE_OWNS_X_COND_N, + AIT_POWER_YELLOW, + AIT_POWER_RED, + AIT_ENEMY_MONEY_COND_N, + AIT_CURTAIN_NEAR_READY, + AIT_SPHERE_NEAR_READY, + AIT_NEUTRAL_OWNS_X_COND_N, +}; + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// property page CAITriggerTypes + +IMPLEMENT_DYNCREATE(CAITriggerTypes, CDialog) + +CAITriggerTypes::CAITriggerTypes() : CDialog(CAITriggerTypes::IDD) +{ + //{{AFX_DATA_INIT(CAITriggerTypes) + m_Flag3 = _T(""); + m_Flag4 = _T(""); + m_Name = _T(""); + m_Flag6 = _T(""); + m_Flag7 = _T(""); + m_Flag8 = _T(""); + m_Flag9 = _T(""); + m_Enabled = FALSE; + m_Condition = -1; + m_Number = 0; + m_Easy = FALSE; + m_Medium = FALSE; + m_Hard = FALSE; + m_BaseDefense = FALSE; + m_Skirmish = FALSE; + m_Flag5 = _T(""); + m_MultiSide = _T(""); + //}}AFX_DATA_INIT +} + +CAITriggerTypes::~CAITriggerTypes() +{ +} + +void CAITriggerTypes::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAITriggerTypes) + DDX_Control(pDX, IDC_TEAMTYPE1, m_TeamType1); + DDX_Control(pDX, IDC_UNITTYPE, m_UnitType); + DDX_Control(pDX, IDC_TEAMTYPE2, m_TeamType2); + DDX_Control(pDX, IDC_FLAG2, m_Flag2); + DDX_Control(pDX, IDC_FLAG1, m_Flag1); + DDX_Control(pDX, IDC_DATA, m_Data); + DDX_Control(pDX, IDC_OWNER, m_Owner); + DDX_Control(pDX, IDC_FLOAT3, m_Float3); + DDX_Control(pDX, IDC_FLOAT2, m_Float2); + DDX_Control(pDX, IDC_FLOAT1, m_Float1); + DDX_Control(pDX, IDC_AITRIGGERTYPE, m_AITriggerType); + DDX_Text(pDX, IDC_FLAG4, m_Flag4); + DDX_Text(pDX, IDC_NAME, m_Name); + DDX_Check(pDX, IDC_ENABLED, m_Enabled); + DDX_CBIndex(pDX, IDC_CONDITION, m_Condition); + DDX_Text(pDX, IDC_NUMBER, m_Number); + DDV_MinMaxInt(pDX, m_Number, 0, 256); + DDX_Check(pDX, IDC_EASY, m_Easy); + DDX_Check(pDX, IDC_MEDIUM, m_Medium); + DDX_Check(pDX, IDC_HARD, m_Hard); + DDX_Check(pDX, IDC_BASEDEFENSE, m_BaseDefense); + DDX_Check(pDX, IDC_SKIRMISH, m_Skirmish); + DDX_CBString(pDX, IDC_MULTISIDE, m_MultiSide); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CAITriggerTypes, CDialog) + //{{AFX_MSG_MAP(CAITriggerTypes) + ON_CBN_SELCHANGE(IDC_AITRIGGERTYPE, OnSelchangeAitriggertype) + ON_EN_CHANGE(IDC_NAME, OnChangeName) + ON_CBN_EDITCHANGE(IDC_OWNER, OnEditchangeOwner) + ON_CBN_EDITCHANGE(IDC_TEAMTYPE1, OnEditchangeTeamtype1) + ON_CBN_EDITCHANGE(IDC_TEAMTYPE2, OnEditchangeTeamtype2) + ON_CBN_EDITCHANGE(IDC_FLAG1, OnEditchangeFlag1) + ON_CBN_EDITCHANGE(IDC_FLAG2, OnEditchangeFlag2) + ON_CBN_EDITCHANGE(IDC_UNITTYPE, OnEditchangeUnittype) + ON_CBN_EDITCHANGE(IDC_DATA, OnEditchangeData) + ON_EN_CHANGE(IDC_FLOAT1, OnChangeFloat1) + ON_EN_CHANGE(IDC_FLOAT2, OnChangeFloat2) + ON_EN_CHANGE(IDC_FLOAT3, OnChangeFloat3) + ON_EN_CHANGE(IDC_FLAG4, OnChangeFlag4) + + ON_BN_CLICKED(IDC_ENABLED, OnEnabled) + ON_BN_CLICKED(IDC_ADD, OnAdd) + ON_BN_CLICKED(IDC_DELETE, OnDelete) + ON_CBN_EDITCHANGE(IDC_AITRIGGERTYPE, OnEditchangeAitriggertype) + ON_CBN_SELCHANGE(IDC_CONDITION, OnSelchangeCondition) + ON_EN_CHANGE(IDC_NUMBER, OnChangeNumber) + ON_BN_CLICKED(IDC_EASY, OnEasy) + ON_BN_CLICKED(IDC_MEDIUM, OnMedium) + ON_BN_CLICKED(IDC_HARD, OnHard) + ON_BN_CLICKED(IDC_BASEDEFENSE, OnBasedefense) + ON_BN_CLICKED(IDC_SKIRMISH, OnSkirmish) + ON_CBN_EDITCHANGE(IDC_MULTISIDE, OnEditchangeMultiside) + ON_CBN_SELCHANGE(IDC_MULTISIDE, OnSelchangeMultiside) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// message handlers CAITriggerTypes + +void ListObjects(CComboBox& cb) +{ + CComboBox& m_UnitType=cb; + CIniFile& ini=Map->GetIniFile(); + + int i; + + CString ss="InfantryTypes"; + for(i=0;iGetUnitName((char*)(LPCTSTR)type); + + s+=")"; + m_UnitType.AddString(s); + } + for(i=0;iGetUnitName((char*)(LPCTSTR)type); + + s+=")"; + m_UnitType.AddString(s); + } + + ss="VehicleTypes"; + for(i=0;iGetUnitName((char*)(LPCTSTR)type); + + s+=")"; + m_UnitType.AddString(s); + } + for(i=0;iGetUnitName((char*)(LPCTSTR)type); + + s+=")"; + m_UnitType.AddString(s); + } + + ss="AircraftTypes"; + for(i=0;iGetUnitName((char*)(LPCTSTR)type); + + s+=")"; + m_UnitType.AddString(s); + } + for(i=0;iGetUnitName((char*)(LPCTSTR)type); + + s+=")"; + m_UnitType.AddString(s); + } + + ss="BuildingTypes"; + for(i=0;iGetUnitName((char*)(LPCTSTR)type); + + s+=")"; + m_UnitType.AddString(s); + } + for(i=0;iGetUnitName((char*)(LPCTSTR)type); + + s+=")"; + m_UnitType.AddString(s); + } +} + +void CAITriggerTypes::UpdateDialog() +{ + int sel=m_AITriggerType.GetCurSel(); + m_AITriggerType.SetRedraw(FALSE); + + while(m_AITriggerType.DeleteString(0)!=CB_ERR); + + ListHouses(m_Owner,FALSE,TRUE); + m_Owner.AddString(""); + ListTeamTypes(m_TeamType1, TRUE); + ListTeamTypes(m_TeamType2, TRUE); + + int i; + for(i=0;iGetAITriggerTypeCount();i++) + { + AITRIGGERTYPE aitt; + Map->GetAITriggerType(i, &aitt); + CString s=aitt.ID; + s+=" ("; + s+=aitt.name; + s+=")"; + m_AITriggerType.AddString(s); + } + + m_AITriggerType.SetCurSel(0); + if(sel!=-1) + m_AITriggerType.SetCurSel(sel); + + + + + + + OnSelchangeAitriggertype(); + + m_AITriggerType.SetRedraw(TRUE); + m_AITriggerType.RedrawWindow(); +} + + +void CAITriggerTypes::OnSelchangeAitriggertype() +{ + int sel=m_AITriggerType.GetCurSel(); + if(sel<0) return; + + CString aitrigger; + m_AITriggerType.GetLBText(sel,aitrigger); + TruncSpace(aitrigger); + + + AITRIGGERTYPE aitt; + Map->GetAITriggerType(Map->GetAITriggerTypeIndex(aitrigger), &aitt); + + m_Name=aitt.name; + m_TeamType1.SetWindowText(aitt.teamtype1); + m_Owner.SetWindowText(TranslateHouse(aitt.owner, TRUE)); + m_Flag1.SetWindowText(aitt.techlevel); + //m_Flag2.SetWindowText(aitt.type); + int type=atoi(aitt.type)+1; + m_Flag2.SetCurSel(type); + m_UnitType.SetWindowText(aitt.unittype); + m_Data.SetWindowText(aitt.data); + m_Float1.SetWindowText(aitt.float1); + m_Float2.SetWindowText(aitt.float2); + m_Float3.SetWindowText(aitt.float3); + //m_Flag3=aitt.skirmish; + m_Skirmish=isTrue(aitt.skirmish); + m_Flag4=aitt.flag4; + //m_Flag5=aitt.multihouse; + m_MultiSide=aitt.multihouse; + m_BaseDefense=isTrue(aitt.basedefense); + m_TeamType2.SetWindowText(aitt.teamtype2); + m_Easy=isTrue(aitt.easy); + m_Medium=isTrue(aitt.medium); + m_Hard=isTrue(aitt.hard); + + m_Enabled=FALSE; + CIniFile& ini=Map->GetIniFile(); + if(ini.sections["AITriggerTypesEnable"].values.find((LPCTSTR)aitrigger)!=ini.sections["AITriggerTypesEnable"].values.end()) + if(stricmp(ini.sections["AITriggerTypesEnable"].values[(LPCTSTR)aitrigger], "yes")==NULL) + m_Enabled=TRUE; + + AITrigInfo info; + info=ConvertToAITrigInfoFromHex((char*)(LPCSTR)aitt.data); + m_Condition=info.Condition; + m_Number=info.Number; + + ListObjects(m_UnitType); + + UpdateData(FALSE); +} + +void CAITriggerTypes::OnChangeName() +{ + UpdateData(); + + CString value; + value=m_Name; + + if(value.GetLength()==0) value=" "; + + SetAITriggerParam(value, 0); + + UpdateDialog(); +} + +void CAITriggerTypes::OnEditchangeOwner() +{ + CString value; + m_Owner.GetWindowText(value); + + value=TranslateHouse(value); + + SetAITriggerParam(value, 2); +} + +void CAITriggerTypes::OnEditchangeTeamtype1() +{ + CString value; + m_TeamType1.GetWindowText(value); + TruncSpace(value); + + SetAITriggerParam(value, 1); +} + +void CAITriggerTypes::OnEditchangeTeamtype2() +{ + CString value; + m_TeamType2.GetWindowText(value); + TruncSpace(value); + + SetAITriggerParam(value, 14); +} + +void CAITriggerTypes::OnEditchangeFlag1() +{ + CString value; + m_Flag1.GetWindowText(value); + + SetAITriggerParam(value, 3); +} + +void CAITriggerTypes::OnEditchangeFlag2() +{ + CString value; + m_Flag2.GetWindowText(value); + + TruncSpace(value); + + SetAITriggerParam(value, 4); +} + +void CAITriggerTypes::OnEditchangeUnittype() +{ + CString value; + m_UnitType.GetWindowText(value); + TruncSpace(value); + + SetAITriggerParam(value, 5); +} + +void CAITriggerTypes::OnEditchangeData() +{ + /* + This function should also valid the data! + */ + + CString value; + m_Data.GetWindowText(value); + TruncSpace(value); + + // max 64 chars... min 64 chars too... + ((char*)(LPCTSTR)value)[64]=0; + + int ToInsert=64-value.GetLength(); + CString nulls('0',ToInsert); + + value.Insert(value.GetLength()-ToInsert, nulls); + + + SetAITriggerParam(value, 6); + + + int editsel=m_Data.GetEditSel(); + UpdateDialog(); + m_Data.SetEditSel(editsel,editsel+1); +} + +void CAITriggerTypes::OnChangeFloat1() +{ + CString value; + m_Float1.GetWindowText(value); + + SetAITriggerParam(value, 7); +} + +void CAITriggerTypes::OnChangeFloat2() +{ + CString value; + m_Float2.GetWindowText(value); + + SetAITriggerParam(value, 8); +} + +void CAITriggerTypes::OnChangeFloat3() +{ + CString value; + m_Float3.GetWindowText(value); + + SetAITriggerParam(value, 9); +} + +void CAITriggerTypes::OnChangeFlag3() +{ + + +} + +void CAITriggerTypes::OnChangeFlag4() +{ + UpdateData(); + + CString value; + value=m_Flag4; + + SetAITriggerParam(value, 11); + +} + +void CAITriggerTypes::OnChangeFlag5() +{ + + +} + +void CAITriggerTypes::OnChangeFlag6() +{ + +} + +void CAITriggerTypes::OnChangeFlag7() +{ + +} + +void CAITriggerTypes::OnChangeFlag8() +{ + UpdateData(); + + CString value; + value=m_Flag8; + + SetAITriggerParam(value, 16); +} + +void CAITriggerTypes::OnChangeFlag9() +{ + UpdateData(); + + CString value; + value=m_Flag9; + + SetAITriggerParam(value, 17); +} + +void CAITriggerTypes::OnEnabled() +{ + // enable or disable trigger + + UpdateData(); + + int sel=m_AITriggerType.GetCurSel(); + if(sel<0) return; + + CString aitrigger; + m_AITriggerType.GetLBText(sel,aitrigger); + TruncSpace(aitrigger); + + CIniFile& ini=Map->GetIniFile(); + + if(m_Enabled) + { + // enable it + ini.sections["AITriggerTypesEnable"].values[(LPCTSTR)aitrigger]="yes"; + } + else + ini.sections["AITriggerTypesEnable"].values.erase((LPCTSTR)aitrigger); +} + +void CAITriggerTypes::SetAITriggerParam(const char *value, int param) +{ + int sel=m_AITriggerType.GetCurSel(); + if(sel<0) return; + + CString aitrigger; + m_AITriggerType.GetLBText(sel,aitrigger); + TruncSpace(aitrigger); + + CIniFile& ini=Map->GetIniFile(); + ini.sections["AITriggerTypes"].values[aitrigger]=SetParam(ini.sections["AITriggerTypes"].values[aitrigger],param,value); +} + +void CAITriggerTypes::OnAdd() +{ + CString ID=GetFreeID(); + CIniFile& ini=Map->GetIniFile(); + CString data="New AI Trigger,"; + + // now try to set a teamtype + if(ini.sections["TeamTypes"].values.size()>0) + { + data+=*ini.sections["TeamTypes"].GetValue(0); + } + else + { + data+=""; + } + + data+=",,"; + + // the flag here... i first thought it´s an ID, but it more seems to be an value specifying the importance of the trigger + data+="1,"; + + // the flag 2 seems to be the type of the trigger. -1 seems to be pool + data+="0,"; + + // now stuff + data+=",0000000000000000000000000000000000000000000000000000000000000000,50.000000,30.000000,50.000000,1,0,1,1,"; + + // a pool seems to need both teamtypes the same + if(ini.sections["TeamTypes"].values.size()>0) + { + data+="";//*ini.sections["TeamTypes"].GetValue(0); + } + else + { + data+=""; + } + + data+=",1,1,1"; + + ini.sections["AITriggerTypes"].values[ID]=data; + + UpdateDialog(); + + // now make current id visible + int i; + for(i=0;iGetIniFile(); + + ini.sections["AITriggerTypes"].values.erase(aitrigger); + ini.sections["AITriggerTypesEnable"].values.erase(aitrigger); + + UpdateDialog(); +} + +void CAITriggerTypes::OnEditchangeAitriggertype() +{ + OnSelchangeAitriggertype(); +} + +AITrigInfo CAITriggerTypes::ConvertToAITrigInfoFromHex(char *aitinfo) +{ + int index=0; + AITrigInfo info; + char* rawdata=(char*)&info; + char hexbuff[3]="00"; + char* dummy=NULL; + + while(*aitinfo!='\0') + { + while(isspace((int)*aitinfo)) aitinfo++; + + hexbuff[0]=*aitinfo++; + ASSERT(*aitinfo!='\0'); + if(*aitinfo!='\0'){ + hexbuff[1]=*aitinfo++; + } else { + hexbuff[1]='\0'; + } + + ASSERT(index=sizeof(AITrigInfo)) break; + + *rawdata++=strtol(hexbuff, &dummy, 16); + index++; + } + + return info; +} + +char* CAITriggerTypes::ConvertToHexFromAITrigInfo(AITrigInfo info, char* buffer) +{ + unsigned char* aitinfobuffer=(unsigned char*)buffer; + /* + ** Convert the AITrigInfo union data structure to ASCII format string + */ + { + + int index = 0; + unsigned char *rawdata = (unsigned char *)&info; + unsigned char *aitinfobuffptr = &aitinfobuffer[0]; + + for (; index < sizeof(AITrigInfo); index++, rawdata++, aitinfobuffptr += 2) { + sprintf((char *)aitinfobuffptr, "%02x", *rawdata); + } + + *aitinfobuffptr = '\0'; + } + + return (char*)aitinfobuffer; +} + +void CAITriggerTypes::OnSelchangeCondition() +{ + int sel=m_AITriggerType.GetCurSel(); + if(sel<0) return; + + UpdateData(TRUE); + + AITrigInfo info; + info.Condition=(ConditionEnum)m_Condition; + info.Number=m_Number; + + char buffer[65]; + ConvertToHexFromAITrigInfo(info, buffer); + + + SetAITriggerParam(buffer, 6); + + UpdateDialog(); +} + +void CAITriggerTypes::OnChangeNumber() +{ + int sel=m_AITriggerType.GetCurSel(); + if(sel<0) return; + + UpdateData(TRUE); + + AITrigInfo info; + memset(&info, 0, sizeof(AITrigInfo)); + info.Condition=(ConditionEnum)m_Condition; + info.Number=m_Number; + + char buffer[65]; + ConvertToHexFromAITrigInfo(info, buffer); + + //MessageBox(buffer); + + //m_Data.SetWindowText(buffer); + + SetAITriggerParam(buffer, 6); + + UpdateDialog(); + +} + +void CAITriggerTypes::OnEasy() +{ + UpdateData(); + + CString value; + value="1"; + if(!m_Easy) value="0"; + + SetAITriggerParam(value, 15); +} + +void CAITriggerTypes::OnMedium() +{ + UpdateData(); + + CString value; + value="1"; + if(!m_Medium) value="0"; + + SetAITriggerParam(value, 16); +} + +void CAITriggerTypes::OnHard() +{ + UpdateData(); + + CString value; + value="1"; + if(!m_Hard) value="0"; + + SetAITriggerParam(value, 17); +} + +void CAITriggerTypes::OnBasedefense() +{ + UpdateData(); + + CString value; + value="1"; + if(!m_BaseDefense) value="0"; + + SetAITriggerParam(value, 13); +} + +void CAITriggerTypes::OnSkirmish() +{ + UpdateData(); + + CString value; + value="1"; + if(!m_Skirmish) value="0"; + + SetAITriggerParam(value, 10); +} + +void CAITriggerTypes::OnEditchangeMultiside() +{ + UpdateData(); + + CString value; + value=m_MultiSide; + + TruncSpace(value); + + SetAITriggerParam(value, 12); +} + +void CAITriggerTypes::OnSelchangeMultiside() +{ + CString s; + CComboBox& box=*(CComboBox*)GetDlgItem(IDC_MULTISIDE); + box.GetLBText(box.GetCurSel(), s); + box.SetWindowText(s); + + OnEditchangeMultiside(); +} diff --git a/MissionEditor/AITriggerTypes.h b/MissionEditor/AITriggerTypes.h new file mode 100644 index 0000000..027a4ef --- /dev/null +++ b/MissionEditor/AITriggerTypes.h @@ -0,0 +1,132 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_AITRIGGERTYPES_H__47F0A0E0_A8DC_11D3_B63B_B4F5BEE55940__INCLUDED_) +#define AFX_AITRIGGERTYPES_H__47F0A0E0_A8DC_11D3_B63B_B4F5BEE55940__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// AITriggerTypes.h : Header file +// + +#include "structs.h" + +///////////////////////////////////////////////////////////////////////////// +// dialog field CAITriggerTypes + +class CAITriggerTypes : public CDialog +{ + DECLARE_DYNCREATE(CAITriggerTypes) + +// construction +public: + char* ConvertToHexFromAITrigInfo(AITrigInfo info, char* buffer); + void SetAITriggerParam(const char* value, int param); + void UpdateDialog(); + CAITriggerTypes(); + ~CAITriggerTypes(); + +// dialog field data + //{{AFX_DATA(CAITriggerTypes) + enum { IDD = IDD_AITRIGGERTYPES }; + CMyComboBox m_TeamType1; + CMyComboBox m_UnitType; + CMyComboBox m_TeamType2; + CMyComboBox m_Flag2; + CMyComboBox m_Flag1; + CMyComboBox m_Data; + CMyComboBox m_Owner; + CFloatEdit m_Float3; + CFloatEdit m_Float2; + CFloatEdit m_Float1; + CMyComboBox m_AITriggerType; + CString m_Flag3; + CString m_Flag4; + CString m_Name; + CString m_Flag6; + CString m_Flag7; + CString m_Flag8; + CString m_Flag9; + BOOL m_Enabled; + int m_Condition; + int m_Number; + BOOL m_Easy; + BOOL m_Medium; + BOOL m_Hard; + BOOL m_BaseDefense; + BOOL m_Skirmish; + CString m_Flag5; + CString m_MultiSide; + //}}AFX_DATA + + +// overwriteables + // generated virtual overwriteables + //{{AFX_VIRTUAL(CAITriggerTypes) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// implementation +protected: + AITrigInfo ConvertToAITrigInfoFromHex(char* aitinfo); + // generated message maps + //{{AFX_MSG(CAITriggerTypes) + afx_msg void OnSelchangeAitriggertype(); + afx_msg void OnChangeName(); + afx_msg void OnEditchangeOwner(); + afx_msg void OnEditchangeTeamtype1(); + afx_msg void OnEditchangeTeamtype2(); + afx_msg void OnEditchangeFlag1(); + afx_msg void OnEditchangeFlag2(); + afx_msg void OnEditchangeUnittype(); + afx_msg void OnEditchangeData(); + afx_msg void OnChangeFloat1(); + afx_msg void OnChangeFloat2(); + afx_msg void OnChangeFloat3(); + afx_msg void OnChangeFlag3(); + afx_msg void OnChangeFlag4(); + afx_msg void OnChangeFlag5(); + afx_msg void OnChangeFlag6(); + afx_msg void OnChangeFlag7(); + afx_msg void OnChangeFlag8(); + afx_msg void OnChangeFlag9(); + afx_msg void OnEnabled(); + afx_msg void OnAdd(); + afx_msg void OnDelete(); + afx_msg void OnEditchangeAitriggertype(); + afx_msg void OnSelchangeCondition(); + afx_msg void OnChangeNumber(); + afx_msg void OnEasy(); + afx_msg void OnMedium(); + afx_msg void OnHard(); + afx_msg void OnBasedefense(); + afx_msg void OnSkirmish(); + afx_msg void OnEditchangeMultiside(); + afx_msg void OnSelchangeMultiside(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} + +#endif // AFX_AITRIGGERTYPES_H__47F0A0E0_A8DC_11D3_B63B_B4F5BEE55940__INCLUDED_ diff --git a/MissionEditor/AiTriggerTypesEnable.cpp b/MissionEditor/AiTriggerTypesEnable.cpp new file mode 100644 index 0000000..f534b8b --- /dev/null +++ b/MissionEditor/AiTriggerTypesEnable.cpp @@ -0,0 +1,170 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// AiTriggerTypesEnable.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "AiTriggerTypesEnable.h" +#include "mapdata.h" +#include "variables.h" +#include "inlines.h" +#include "aitriggeradddlg.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Eigenschaftenseite CAiTriggerTypesEnable + +IMPLEMENT_DYNCREATE(CAiTriggerTypesEnable, CDialog) + +CAiTriggerTypesEnable::CAiTriggerTypesEnable() : CDialog(CAiTriggerTypesEnable::IDD) +{ + //{{AFX_DATA_INIT(CAiTriggerTypesEnable) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Elementinitialisierung ein + //}}AFX_DATA_INIT +} + +CAiTriggerTypesEnable::~CAiTriggerTypesEnable() +{ +} + +void CAiTriggerTypesEnable::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAiTriggerTypesEnable) + DDX_Control(pDX, IDC_AITRIGGERTYPE, m_AITriggerType); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CAiTriggerTypesEnable, CDialog) + //{{AFX_MSG_MAP(CAiTriggerTypesEnable) + ON_BN_CLICKED(IDC_ENABLEALL, OnEnableall) + ON_CBN_SELCHANGE(IDC_AITRIGGERTYPE, OnSelchangeAitriggertype) + ON_BN_CLICKED(IDC_DELETE, OnDelete) + ON_BN_CLICKED(IDC_ADD, OnAdd) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CAiTriggerTypesEnable + +void CAiTriggerTypesEnable::UpdateDialog() +{ + int sel=m_AITriggerType.GetCurSel(); + if(sel<0) sel=0; + + while(m_AITriggerType.DeleteString(0)!=CB_ERR); + + CIniFile& ini=Map->GetIniFile(); + + int i; + for(i=0;iGetIniFile(); + int i; + for(i=0;i=0) aitrigger.SetAt(aitrigger.Find(" "), 0); + + CIniFile& ini=Map->GetIniFile(); + + ini.sections["AITriggerTypesEnable"].values.erase((LPCTSTR)aitrigger); + UpdateDialog(); +} + +void CAiTriggerTypesEnable::OnAdd() +{ + + + //CString p=InputBox("Please enter the ID of the AITriggerType (for a list of all AITriggerType-IDs use the All-Section)","Enable AITriggerType"); + CAITriggerAddDlg dlg; + if(dlg.DoModal()==IDCANCEL) return; + + CString p=dlg.m_AITrigger; + TruncSpace(p); + if(p.GetLength()==0) return; + + CIniFile& ini=Map->GetIniFile(); + + ini.sections["AITriggerTypesEnable"].values[p]="yes"; + UpdateDialog(); +} diff --git a/MissionEditor/AiTriggerTypesEnable.h b/MissionEditor/AiTriggerTypesEnable.h new file mode 100644 index 0000000..0cfcfb7 --- /dev/null +++ b/MissionEditor/AiTriggerTypesEnable.h @@ -0,0 +1,73 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_AITRIGGERTYPESENABLE_H__5CA6D080_A4D2_11D3_B63B_808EC7AC6440__INCLUDED_) +#define AFX_AITRIGGERTYPESENABLE_H__5CA6D080_A4D2_11D3_B63B_808EC7AC6440__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// AiTriggerTypesEnable.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CAiTriggerTypesEnable + +class CAiTriggerTypesEnable : public CDialog +{ + DECLARE_DYNCREATE(CAiTriggerTypesEnable) + +// Konstruktion +public: + void UpdateDialog(); + CAiTriggerTypesEnable(); + ~CAiTriggerTypesEnable(); + +// Dialogfelddaten + //{{AFX_DATA(CAiTriggerTypesEnable) + enum { IDD = IDD_AITRIGGERTYPESENABLE }; + CComboBox m_AITriggerType; + //}}AFX_DATA + + +// Ăœberschreibungen + // Der Klassen-Assistent generiert virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CAiTriggerTypesEnable) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CAiTriggerTypesEnable) + afx_msg void OnEnableall(); + afx_msg void OnSelchangeAitriggertype(); + afx_msg void OnDelete(); + afx_msg void OnAdd(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_AITRIGGERTYPESENABLE_H__5CA6D080_A4D2_11D3_B63B_808EC7AC6440__INCLUDED_ diff --git a/MissionEditor/Aircraft.cpp b/MissionEditor/Aircraft.cpp new file mode 100644 index 0000000..7da02a8 --- /dev/null +++ b/MissionEditor/Aircraft.cpp @@ -0,0 +1,166 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Aircraft.cpp: implementation file +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "Aircraft.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// dialog field CAircraft + + +CAircraft::CAircraft(CWnd* pParent /*=NULL*/) + : CDialog(CAircraft::IDD, pParent) +{ + //{{AFX_DATA_INIT(CAircraft) + m_direction = _T(""); + m_house = _T(""); + m_flag1 = _T(""); + m_flag2 = _T(""); + m_flag3 = _T(""); + m_flag4 = _T(""); + m_action = _T(""); + m_tag = _T(""); + //}}AFX_DATA_INIT +} + + +void CAircraft::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAircraft) + DDX_Control(pDX, IDC_STRENGTH, m_strength_ctrl); + DDX_CBString(pDX, IDC_DIRECTION, m_direction); + DDX_CBString(pDX, IDC_HOUSE, m_house); + DDX_Text(pDX, IDC_P1, m_flag1); + DDX_Text(pDX, IDC_P2, m_flag2); + DDX_Text(pDX, IDC_P3, m_flag3); + DDX_Text(pDX, IDC_P4, m_flag4); + DDX_CBString(pDX, IDC_STATE, m_action); + DDX_CBString(pDX, IDC_TAG, m_tag); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CAircraft, CDialog) + //{{AFX_MSG_MAP(CAircraft) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// handlers for messages CAircraft + +void CAircraft::Init(CString house, CString strength, CString direction, CString action, CString tag, CString flag1, CString flag2, CString flag3, CString flag4) +{ + if(house.GetLength()==0) + { + m_house=TranslateHouse(Map->GetHouseID(0), TRUE); + } + else + m_house=TranslateHouse(house, TRUE); + + + + m_flag1=flag1; + m_flag2=flag2; + m_flag3=flag3; + m_flag4=flag4; + + m_action=action; + m_strength=strength; + + m_tag=tag; + m_direction=direction; + +} + +BOOL CAircraft::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // init the common (!) dialog things + int i; + CComboBox* house, *tag; + + house=(CComboBox*)GetDlgItem(IDC_HOUSE); + + tag=(CComboBox*)GetDlgItem(IDC_TAG); + + ListHouses(*house, FALSE); + ListTags(*tag, TRUE); + + ListYesNo(*(CComboBox*)GetDlgItem(IDC_P3)); + + UpdateData(FALSE); + m_strength_ctrl.SetRange(0,256); + m_strength_ctrl.SetPos(atoi(m_strength)); + + UpdateStrings(); + + return TRUE; +} + +void CAircraft::OnOK() +{ + CDialog::OnOK(); + m_strength=GetText(&m_strength_ctrl); + + + + UpdateData(); + m_house=TranslateHouse(m_house, FALSE); + TruncSpace(m_tag); + TruncSpace(m_flag1); + TruncSpace(m_flag2); + TruncSpace(m_flag3); + TruncSpace(m_flag4); + +} + +void CAircraft::UpdateStrings() +{ + SetWindowText(GetLanguageStringACP("AirCap")); + GetDlgItem(IDC_LHOUSE)->SetWindowText(GetLanguageStringACP("AirHouse")); + GetDlgItem(IDC_LDESC)->SetWindowText(GetLanguageStringACP("AirDesc")); + GetDlgItem(IDC_LSTRENGTH)->SetWindowText(GetLanguageStringACP("AirStrength")); + GetDlgItem(IDC_LSTATE)->SetWindowText(GetLanguageStringACP("AirState")); + GetDlgItem(IDC_LDIRECTION)->SetWindowText(GetLanguageStringACP("AirDirection")); + GetDlgItem(IDC_LTAG)->SetWindowText(GetLanguageStringACP("AirTag")); + GetDlgItem(IDC_LP1)->SetWindowText(GetLanguageStringACP("AirP1")); + GetDlgItem(IDC_LP2)->SetWindowText(GetLanguageStringACP("AirP2")); + GetDlgItem(IDC_LP3)->SetWindowText(GetLanguageStringACP("AirP3")); + GetDlgItem(IDC_LP4)->SetWindowText(GetLanguageStringACP("AirP4")); + + SetDlgItemText(IDOK, GetLanguageStringACP("OK")); + SetDlgItemText(IDCANCEL, GetLanguageStringACP("Cancel")); +} diff --git a/MissionEditor/Aircraft.h b/MissionEditor/Aircraft.h new file mode 100644 index 0000000..48a9160 --- /dev/null +++ b/MissionEditor/Aircraft.h @@ -0,0 +1,75 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_AIRCRAFT_H__15BD6160_8953_11D3_B63B_A583BFBD8C41__INCLUDED_) +#define AFX_AIRCRAFT_H__15BD6160_8953_11D3_B63B_A583BFBD8C41__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Aircraft.h : Header-Datei +// + + +class CAircraft : public CDialog +{ +// construction +public: + void UpdateStrings(); + CString m_strength; + void Init(CString house="", CString strength="256", CString direction="64", CString action="Guard", CString tag="None", CString flag1="0", CString flag2="0", CString flag3="0", CString flag4="0"); + CAircraft(CWnd* pParent = NULL); // standard constructor + +// dialog field data + //{{AFX_DATA(CAircraft) + enum { IDD = IDD_AIRCRAFT }; + CSliderCtrl m_strength_ctrl; + CString m_direction; + CString m_house; + CString m_flag1; + CString m_flag2; + CString m_flag3; + CString m_flag4; + CString m_action; + CString m_tag; + //}}AFX_DATA + + +// overwriteables + // generated from class assistant + //{{AFX_VIRTUAL(CAircraft) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// implementation +protected: + + // generated message maps + //{{AFX_MSG(CAircraft) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} + +#endif // AFX_AIRCRAFT_H__15BD6160_8953_11D3_B63B_A583BFBD8C41__INCLUDED_ diff --git a/MissionEditor/All.cpp b/MissionEditor/All.cpp new file mode 100644 index 0000000..a95ce2c --- /dev/null +++ b/MissionEditor/All.cpp @@ -0,0 +1,285 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// All1.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "All.h" +#include "mapdata.h" +#include "variables.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern CFinalSunApp theApp; +#include "ImportIni.h" + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CAll + + +CAll::CAll(CWnd* pParent /*=NULL*/) + : CDialog(CAll::IDD, pParent) +{ + //{{AFX_DATA_INIT(CAll) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Elementinitialisierung ein + //}}AFX_DATA_INIT +} + + +void CAll::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAll) + DDX_Control(pDX, IDC_VALUE, m_Value); + DDX_Control(pDX, IDC_KEYS, m_Keys); + DDX_Control(pDX, IDC_INISECTION, m_IniSection); + DDX_Control(pDX, IDC_DELETESECTION, m_DeleteSection); + DDX_Control(pDX, IDC_DELETEKEY, m_DeleteKey); + DDX_Control(pDX, IDC_ADDSECTION, m_AddSection); + DDX_Control(pDX, IDC_ADDKEY, m_AddKey); + DDX_Control(pDX, IDC_SECTIONS, m_Sections); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CAll, CDialog) + //{{AFX_MSG_MAP(CAll) + ON_CBN_SELCHANGE(IDC_SECTIONS, OnSelchangeSections) + ON_EN_CHANGE(IDC_VALUE, OnChangeValue) + ON_LBN_SELCHANGE(IDC_KEYS, OnSelchangeKeys) + ON_EN_UPDATE(IDC_VALUE, OnUpdateValue) + ON_BN_CLICKED(IDC_ADDSECTION, OnAddsection) + ON_BN_CLICKED(IDC_DELETESECTION, OnDeletesection) + ON_BN_CLICKED(IDC_DELETEKEY, OnDeletekey) + ON_BN_CLICKED(IDC_ADDKEY, OnAddkey) + ON_BN_CLICKED(IDC_INISECTION, OnInisection) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CAll + +void CAll::UpdateDialog() +{ + //m_Sections.Clear(); + + while(m_Sections.DeleteString(0)!=-1); + while(m_Keys.DeleteString(0)!=-1); + CIniFile& ini=Map->GetIniFile(); + + + m_Value.SetWindowText(""); + + int i; + for(i=ini.sections.size()-1;i>=0;i--) + { + const CString* name=ini.GetSectionName(i); + if(!Map->IsMapSection(*name)) + m_Sections.InsertString(0, *name); + } + + m_Sections.SetCurSel(1); + OnSelchangeSections(); +} + +void CAll::OnSelchangeSections() +{ + while(m_Keys.DeleteString(0)!=CB_ERR); + CIniFile& ini=Map->GetIniFile(); + + CString cuSection; + m_Sections.GetWindowText(cuSection); + + if(cuSection.GetLength()) + { + int i; + m_Keys.SetRedraw(FALSE); + SetCursor(LoadCursor(0,IDC_WAIT)); + for(i=0;iGetIniFile(); + + CString t; + m_Value.GetWindowText(t); + + CString cuSection; + m_Sections.GetWindowText(cuSection); + + + CString cuKey; + if(m_Keys.GetCurSel()>=0)m_Keys.GetText(m_Keys.GetCurSel(), cuKey) ; + + + + ini.sections[cuSection].values[cuKey]=t; + +} + +void CAll::OnSelchangeKeys() +{ + CIniFile& ini=Map->GetIniFile(); + + CString cuSection; + m_Sections.GetWindowText(cuSection); + + CString cuKey; + m_Keys.GetText(m_Keys.GetCurSel(), cuKey) ; + + m_Value.SetWindowText(ini.sections[cuSection].values[cuKey]); +} + +void CAll::OnUpdateValue() +{ + +} + +void CAll::OnAddsection() +{ + CString name=InputBox("Please set the name of the new section (the section may already exist)", "Insert Section"); + + CIniFile& ini=Map->GetIniFile(); + + CIniFileSection stub=ini.sections[(LPCTSTR)name]; + + UpdateDialog(); +} + +void CAll::OnDeletesection() +{ + CIniFile& ini=Map->GetIniFile(); + + int cusection; + cusection=m_Sections.GetCurSel(); + if(cusection==-1) { + MessageBox("You cannot delete a section without choosing one."); + return; + } + + CString str; + m_Sections.GetLBText(cusection, str); + + if(MessageBox(CString((CString)"Are you sure you want to delete " + str + "? You should be really careful, you may not be able to use the map afterwards."), "Delete section", MB_YESNO)==IDNO) return; + + ini.sections.erase(str); + + UpdateDialog(); +} + +void CAll::OnDeletekey() +{ + CIniFile& ini=Map->GetIniFile(); + + int cukey; + if(m_Sections.GetCurSel()<0) return; + cukey=m_Keys.GetCurSel(); + if(cukey==-1) { + MessageBox("You cannot delete a key without choosing one."); + return; + } + + CString str; + CString sec; + int cuSection=m_Sections.GetCurSel(); + m_Sections.GetLBText(cuSection, sec); + m_Keys.GetText(cukey, str); + + if(MessageBox(CString((CString)"Are you sure you want to delete " + str + "? You should be really careful, you may not be able to use the map afterwards."), "Delete key", MB_YESNO)==IDNO) return; + + ini.sections[sec].values.erase(str); + + UpdateDialog(); + + m_Sections.SetCurSel(cuSection); + OnSelchangeSections(); +} + +void CAll::OnAddkey() +{ + CIniFile& ini=Map->GetIniFile(); + int cusection; + cusection=m_Sections.GetCurSel(); + if(cusection==-1) { + MessageBox("You need to specify a section first."); + return; + } + + CString sec; + m_Sections.GetLBText(cusection, sec); + + CString key, value; + key=InputBox("Please set the name and value for the current key here: (for example, setting a new key ""Strength"" with the value 200 can be written as ""Strength=200"". You don´t need to specify a value.)", "Create key"); + + if(key.Find("=")!=-1) + { + // value specified + // MW BUGFIX + value=key.Right(key.GetLength()-key.Find("=")-1); + key=key.Left(key.Find("=")); + } + + ini.sections[sec].values[key]=value; + + UpdateDialog(); + m_Sections.SetCurSel(cusection); + OnSelchangeSections(); +} + +void CAll::OnInisection() +{ + CFileDialog dlg(FALSE, ".ini", "*.ini", OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, "INI files|*.ini|"); + + char cuPath[MAX_PATH]; + BOOL hidePreview=FALSE; + BOOL previewPrinted=FALSE; + GetCurrentDirectory(MAX_PATH, cuPath); + dlg.m_ofn.lpstrInitialDir=cuPath; + + if(theApp.m_Options.TSExe.GetLength()) dlg.m_ofn.lpstrInitialDir=(char*)(LPCTSTR)theApp.m_Options.TSExe; + + if(dlg.DoModal()!=IDCANCEL) + { + CImportINI impini; + impini.m_FileName=dlg.GetPathName(); + if(impini.DoModal()!=IDCANCEL) + { + UpdateDialog(); + } + } +} diff --git a/MissionEditor/All.h b/MissionEditor/All.h new file mode 100644 index 0000000..e5b43e9 --- /dev/null +++ b/MissionEditor/All.h @@ -0,0 +1,82 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_ALL1_H__B5D522E4_69CE_11D3_99E1_C138647F2A00__INCLUDED_) +#define AFX_ALL1_H__B5D522E4_69CE_11D3_99E1_C138647F2A00__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// All1.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CAll + +class CAll : public CDialog +{ +// Konstruktion +public: + void UpdateDialog(); + CAll(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CAll) + enum { IDD = IDD_ALL }; + CEdit m_Value; + CListBox m_Keys; + CButton m_IniSection; + CButton m_DeleteSection; + CButton m_DeleteKey; + CButton m_AddSection; + CButton m_AddKey; + CComboBox m_Sections; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CAll) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CAll) + afx_msg void OnSelchangeSections(); + afx_msg void OnChangeValue(); + afx_msg void OnSelchangeKeys(); + afx_msg void OnUpdateValue(); + afx_msg void OnAddsection(); + afx_msg void OnDeletesection(); + afx_msg void OnDeletekey(); + afx_msg void OnAddkey(); + afx_msg void OnInisection(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_ALL1_H__B5D522E4_69CE_11D3_99E1_C138647F2A00__INCLUDED_ diff --git a/MissionEditor/BackCliffModifier.cpp b/MissionEditor/BackCliffModifier.cpp new file mode 100644 index 0000000..f9a1499 --- /dev/null +++ b/MissionEditor/BackCliffModifier.cpp @@ -0,0 +1,100 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// BackCliffModifier.cpp: Implementierung der Klasse CBackCliffModifier. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "stdafx.h" +#include "BackCliffModifier.h" +#include +#include "variables.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +////////////////////////////////////////////////////////////////////// +// Konstruktion/Destruktion +////////////////////////////////////////////////////////////////////// + +CBackCliffModifier::CBackCliffModifier() +{ + +} + +CBackCliffModifier::~CBackCliffModifier() +{ + +} + + + +void CBackCliffModifier::ModifyCurrentPos(DWORD *dwPos, BOOL bBeforePlacing, BOOL bSmall) +{ + if(!bBeforePlacing) + { + if(m_direction==cd_verticdiag_top) (*dwPos)+=2+0*Map->GetIsoSize(); + if(m_direction==cd_verticdiag_bottom) (*dwPos)+=-2+0*Map->GetIsoSize(); + } +} + +void CBackCliffModifier::ModifyStartPos(DWORD *dwPos, BOOL bSmall) +{ + if(m_direction==cd_verticdiag_top) (*dwPos)+=1+1*Map->GetIsoSize(); + if(m_direction==cd_verticdiag_bottom) (*dwPos)+=-1+0*Map->GetIsoSize(); + + if(m_direction==cd_horiz_right) (*dwPos)+=0+0*Map->GetIsoSize(); + if(m_direction==cd_horiz_left) + { + + int ground=Map->GetFielddataAt(*dwPos)->wGround; + (*dwPos)+=0+Map->GetIsoSize(); + if(ground==0xFFFF) ground=0; + if((*tiledata)[ground].wTileSet==cliffset) + { + (*dwPos)-=Map->GetIsoSize(); + //ModifyStartPos(dwPos, bSmall); + } + } + + if(m_direction==cd_vertic_top) + { + int ground=Map->GetFielddataAt(*dwPos)->wGround; + + (*dwPos)+=1; + if(ground==0xFFFF) ground=0; + if((*tiledata)[ground].wTileSet==cliffset) + { + (*dwPos)-=1; + //ModifyStartPos(dwPos, bSmall); + } + } + +} + +CString CBackCliffModifier::GetDataSection() +{ + if(m_bAlternative) return ("CliffBackDataAlt"); + return("CliffBackData"); +} diff --git a/MissionEditor/BackCliffModifier.h b/MissionEditor/BackCliffModifier.h new file mode 100644 index 0000000..114c95b --- /dev/null +++ b/MissionEditor/BackCliffModifier.h @@ -0,0 +1,46 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// BackCliffModifier.h: Schnittstelle fĂ¼r die Klasse CBackCliffModifier. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_BACKCLIFFMODIFIER_H__3853D325_CD37_11D4_9C87_F2DC6A2E6849__INCLUDED_) +#define AFX_BACKCLIFFMODIFIER_H__3853D325_CD37_11D4_9C87_F2DC6A2E6849__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "CliffModifier.h" + +class CBackCliffModifier : public CCliffModifier +{ +public: + CBackCliffModifier(); + virtual ~CBackCliffModifier(); + +protected: + virtual CString GetDataSection(); + virtual void ModifyStartPos(DWORD* dwPos, BOOL bSmall); + virtual void ModifyCurrentPos(DWORD* dwPos, BOOL bBeforePlacing, BOOL bSmall); +}; + +#endif // !defined(AFX_BACKCLIFFMODIFIER_H__3853D325_CD37_11D4_9C87_F2DC6A2E6849__INCLUDED_) diff --git a/MissionEditor/Basic.cpp b/MissionEditor/Basic.cpp new file mode 100644 index 0000000..a9e84e9 --- /dev/null +++ b/MissionEditor/Basic.cpp @@ -0,0 +1,346 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Basic.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "Basic.h" +#include "resource.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Eigenschaftenseite CBasic + +IMPLEMENT_DYNCREATE(CBasic, CPropertyPage) + +CBasic::CBasic() : CDialog(CBasic::IDD) +{ + //{{AFX_DATA_INIT(CBasic) + //}}AFX_DATA_INIT +} + +CBasic::~CBasic() +{ +} + +void CBasic::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBasic) + DDX_Control(pDX, IDC_REQUIREDADDON, m_RequiredAddOn); + DDX_Control(pDX, IDC_VEINGROWTHENABLED, m_VeinGrowthEnabled); + DDX_Control(pDX, IDC_TRUCKCRATE, m_TruckCrate); + DDX_Control(pDX, IDC_TRAINCRATE, m_TrainCrate); + DDX_Control(pDX, IDC_TIBERIUMGROWTHENABLED, m_TiberiumGrowthEnabled); + DDX_Control(pDX, IDC_TIBERIUMDEATHTOVISCEROID, m_TiberiumDeathToVisceroid); + DDX_Control(pDX, IDC_SKIPSCORE, m_SkipScore); + DDX_Control(pDX, IDC_SKIPMAPSELECT, m_SkipMapSelect); + DDX_Control(pDX, IDC_ONETIMEONLY, m_OneTimeOnly); + DDX_Control(pDX, IDC_OFFICIAL, m_Official); + DDX_Control(pDX, IDC_NEXTSCENARIO, m_NextScenario); + DDX_Control(pDX, IDC_PERCENT, m_Percent); + DDX_Control(pDX, IDC_NEWINIFORMAT, m_NewINIFormat); + DDX_Control(pDX, IDC_NAME, m_Name); + DDX_Control(pDX, IDC_MULTIPLAYERONLY, m_MultiplayerOnly); + DDX_Control(pDX, IDC_INITTIME, m_InitTime); + DDX_Control(pDX, IDC_IGNOREGLOBALAITRIGGERS, m_IgnoreGlobalAITriggers); + DDX_Control(pDX, IDC_ICEGROWTHENABLED, m_IceGrowthEnabled); + DDX_Control(pDX, IDC_FREERADAR, m_FreeRadar); + DDX_Control(pDX, IDC_ENDOFGAME, m_EndOfGame); + DDX_Control(pDX, IDC_CARRYOVERCAP, m_CarryOverCap); + DDX_Control(pDX, IDC_ALTNEXTSCENARIO, m_AltNextScenario); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CBasic, CDialog) + //{{AFX_MSG_MAP(CBasic) + ON_EN_CHANGE(IDC_NAME, OnChangeName) + ON_CBN_EDITCHANGE(IDC_NEXTSCENARIO, OnEditchangeNextscenario) + ON_CBN_EDITCHANGE(IDC_ALTNEXTSCENARIO, OnEditchangeAltnextscenario) + ON_EN_CHANGE(IDC_NEWINIFORMAT, OnChangeNewiniformat) + ON_EN_CHANGE(IDC_CARRYOVERCAP, OnChangeCarryovercap) + ON_CBN_EDITCHANGE(IDC_ENDOFGAME, OnEditchangeEndofgame) + ON_CBN_EDITCHANGE(IDC_SKIPSCORE, OnEditchangeSkipscore) + ON_CBN_EDITCHANGE(IDC_ONETIMEONLY, OnEditchangeOnetimeonly) + ON_CBN_EDITCHANGE(IDC_SKIPMAPSELECT, OnEditchangeSkipmapselect) + ON_CBN_EDITCHANGE(IDC_OFFICIAL, OnEditchangeOfficial) + ON_CBN_EDITCHANGE(IDC_IGNOREGLOBALAITRIGGERS, OnEditchangeIgnoreglobalaitriggers) + ON_CBN_EDITCHANGE(IDC_TRUCKCRATE, OnEditchangeTruckcrate) + ON_CBN_EDITCHANGE(IDC_TRAINCRATE, OnEditchangeTraincrate) + ON_EN_CHANGE(IDC_PERCENT, OnChangePercent) + ON_EN_CHANGE(IDC_MULTIPLAYERONLY, OnChangeMultiplayeronly) + ON_CBN_EDITCHANGE(IDC_TIBERIUMGROWTHENABLED, OnEditchangeTiberiumgrowthenabled) + ON_CBN_EDITCHANGE(IDC_VEINGROWTHENABLED, OnEditchangeVeingrowthenabled) + ON_CBN_EDITCHANGE(IDC_ICEGROWTHENABLED, OnEditchangeIcegrowthenabled) + ON_CBN_EDITCHANGE(IDC_TIBERIUMDEATHTOVISCEROID, OnEditchangeTiberiumdeathtovisceroid) + ON_CBN_EDITCHANGE(IDC_FREERADAR, OnEditchangeFreeradar) + ON_EN_CHANGE(IDC_INITTIME, OnChangeInittime) + ON_CBN_EDITCHANGE(IDC_REQUIREDADDON, OnEditchangeRequiredaddon) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CBasic + +//DEL void CBasic::OnOK() +//DEL { +//DEL // TODO: Zusätzliche PrĂ¼fung hier einfĂ¼gen +//DEL +//DEL CPropertyPage::OnOK(); +//DEL } + +void CBasic::UpdateDialog() +{ + CIniFile& ini=Map->GetIniFile(); + + m_AltNextScenario.SetWindowText(ini.sections["Basic"].values["AltNextScenario"]); + m_Name.SetWindowText(ini.sections["Basic"].values["Name"]); + m_CarryOverCap.SetWindowText(ini.sections["Basic"].values["CarryOverCap"]); + m_EndOfGame.SetWindowText(ini.sections["Basic"].values["EndOfGame"]); + m_FreeRadar.SetWindowText(ini.sections["Basic"].values["FreeRadar"]); + m_IceGrowthEnabled.SetWindowText(ini.sections["Basic"].values["IceGrowthEnabled"]); + m_IgnoreGlobalAITriggers.SetWindowText(ini.sections["Basic"].values["IgnoreGlobalAITriggers"]); + m_InitTime.SetWindowText(ini.sections["Basic"].values["InitTime"]); + m_MultiplayerOnly.SetWindowText(ini.sections["Basic"].values["MultiplayerOnly"]); + m_NewINIFormat.SetWindowText(ini.sections["Basic"].values["NewINIFormat"]); + m_NextScenario.SetWindowText(ini.sections["Basic"].values["NextScenario"]); + m_Official.SetWindowText(ini.sections["Basic"].values["Official"]); + m_OneTimeOnly.SetWindowText(ini.sections["Basic"].values["OneTimeOnly"]); + m_Percent.SetWindowText(ini.sections["Basic"].values["Percent"]); + m_SkipMapSelect.SetWindowText(ini.sections["Basic"].values["SkipMapSelect"]); + m_SkipScore.SetWindowText(ini.sections["Basic"].values["SkipScore"]); + m_TiberiumDeathToVisceroid.SetWindowText(ini.sections["Basic"].values["TiberiumDeathToVisceroid"]); + m_TiberiumGrowthEnabled.SetWindowText(ini.sections["Basic"].values["TiberiumGrowthEnabled"]); + m_TrainCrate.SetWindowText(ini.sections["Basic"].values["TrainCrate"]); + m_TruckCrate.SetWindowText(ini.sections["Basic"].values["TruckCrate"]); + m_VeinGrowthEnabled.SetWindowText(ini.sections["Basic"].values["VeinGrowthEnabled"]); + + if(ini.sections["Basic"].values.find("RequiredAddOn")!=ini.sections["Basic"].values.end()) + { + m_RequiredAddOn.SetWindowText(ini.sections["Basic"].values["RequiredAddOn"]); + } + else + m_RequiredAddOn.SetWindowText("0"); + +} + +void CBasic::OnChangeName() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["Name"]=GetText(&m_Name); +} + +void CBasic::UpdateData() +{ + // MessageBox("This function ( UpdateData() ) should not be called here... please report to the author."); + errstream << "CBasic::UpdateData() called - should not be called" << endl; + errstream.flush(); +} + + +void CBasic::OnEditchangeNextscenario() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["NextScenario"]=GetText(&m_NextScenario); +} + +void CBasic::OnEditchangeAltnextscenario() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["AltNextScenario"]=GetText(&m_AltNextScenario); +} + +void CBasic::OnChangeNewiniformat() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["NewINIFormat"]=GetText(&m_NewINIFormat); +} + +void CBasic::OnChangeCarryovercap() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["CarryOverCap"]=GetText(&m_CarryOverCap); +} + +void CBasic::OnEditchangeEndofgame() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["EndOfGame"]=GetText(&m_EndOfGame); +} + +void CBasic::OnEditchangeSkipscore() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["SkipScore"]=GetText(&m_SkipScore); +} + +void CBasic::OnEditchangeOnetimeonly() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["OneTimeOnly"]=GetText(&m_OneTimeOnly); +} + +void CBasic::OnEditchangeSkipmapselect() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["SkipMapSelect"]=GetText(&m_SkipMapSelect); +} + +void CBasic::OnEditchangeOfficial() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["Official"]=GetText(&m_Official); +} + +void CBasic::OnEditchangeIgnoreglobalaitriggers() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["IgnoreGlobalAITriggers"]=GetText(&m_IgnoreGlobalAITriggers); +} + +void CBasic::OnEditchangeTruckcrate() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["TruckCrate"]=GetText(&m_TruckCrate); +} + +void CBasic::OnEditchangeTraincrate() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["TrainCrate"]=GetText(&m_TrainCrate); +} + +void CBasic::OnChangePercent() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["Percent"]=GetText(&m_Percent); +} + +void CBasic::OnChangeMultiplayeronly() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["MultiplayerOnly"]=GetText(&m_MultiplayerOnly); +} + +void CBasic::OnEditchangeTiberiumgrowthenabled() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["TiberiumGrowthEnabled"]=GetText(&m_TiberiumGrowthEnabled); +} + +void CBasic::OnEditchangeVeingrowthenabled() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["VeinGrowthEnabled"]=GetText(&m_VeinGrowthEnabled); +} + +void CBasic::OnEditchangeIcegrowthenabled() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["IceGrowthEnabled"]=GetText(&m_IceGrowthEnabled); +} + +void CBasic::OnEditchangeTiberiumdeathtovisceroid() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["TiberiumDeathToVisceroid"]=GetText(&m_TiberiumDeathToVisceroid); +} + +void CBasic::OnEditchangeFreeradar() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["FreeRadar"]=GetText(&m_FreeRadar); +} + +void CBasic::OnChangeInittime() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["InitTime"]=GetText(&m_InitTime); +} + +void CBasic::UpdateStrings() +{ + SetDlgItemText(IDC_LDESC, GetLanguageStringACP("BasicDesc")); + SetDlgItemText(IDC_LNAME, GetLanguageStringACP("BasicName")); + SetDlgItemText(IDC_LNEXTSCENARIO, GetLanguageStringACP("BasicNextScenario")); + SetDlgItemText(IDC_LALTNEXTSCENARIO, GetLanguageStringACP("BasicAltNextScenario")); + SetDlgItemText(IDC_LNEWINIFORMAT, GetLanguageStringACP("BasicNewIniFormat")); + SetDlgItemText(IDC_LCARRYOVERCAP, GetLanguageStringACP("BasicCarryOverCap")); + SetDlgItemText(IDC_LENDOFGAME, GetLanguageStringACP("BasicEndOfGame")); + SetDlgItemText(IDC_LSKIPSCORE, GetLanguageStringACP("BasicSkipScore")); + SetDlgItemText(IDC_LONETIMEONLY, GetLanguageStringACP("BasicOneTimeOnly")); + SetDlgItemText(IDC_LSKIPMAPSELECT, GetLanguageStringACP("BasicSkipMapSelect")); + SetDlgItemText(IDC_LOFFICIAL, GetLanguageStringACP("BasicOfficial")); + SetDlgItemText(IDC_LIGNOREGLOBALAITRIGGERS, GetLanguageStringACP("BasicIgnoreGlobalAITriggers")); + SetDlgItemText(IDC_LTRUCKCRATE, GetLanguageStringACP("BasicTruckCrate")); + SetDlgItemText(IDC_LTRAINCRATE, GetLanguageStringACP("BasicTrainCrate")); + SetDlgItemText(IDC_LPERCENT, GetLanguageStringACP("BasicPercent")); + SetDlgItemText(IDC_LMULTIPLAYERONLY, GetLanguageStringACP("BasicMultiplayerOnly")); + SetDlgItemText(IDC_LTIBERIUMGROWTHENABLED, GetLanguageStringACP("BasicTiberiumGrowthEnabled")); + SetDlgItemText(IDC_LVEINGROWTHENABLED, GetLanguageStringACP("BasicVeinGrowthEnabled")); + SetDlgItemText(IDC_LICEGROWTHENABLED, GetLanguageStringACP("BasicIceGrowthEnabled")); + SetDlgItemText(IDC_LTIBERIUMDEATHTOVISCEROID, GetLanguageStringACP("BasicTiberiumDeathToVisceroid")); + SetDlgItemText(IDC_LFREERADAR, GetLanguageStringACP("BasicFreeRadar")); + SetDlgItemText(IDC_LINITIME, GetLanguageStringACP("BasicInitTime")); + SetDlgItemText(IDC_LADDONNEEDED, GetLanguageStringACP("BasicAddOnNeeded")); + + + +#ifdef RA2_MODE + GetDlgItem(IDC_LVEINGROWTHENABLED)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_VEINGROWTHENABLED)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_LTRAINCRATE)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_TRAINCRATE)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_ICEGROWTHENABLED)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_LICEGROWTHENABLED)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_TIBERIUMDEATHTOVISCEROID)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_LTIBERIUMDEATHTOVISCEROID)->ShowWindow(SW_HIDE); + + +#endif + + SetWindowText(TranslateStringACP("Basic")); +} + +void CBasic::OnEditchangeRequiredaddon() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["RequiredAddOn"]=GetText(&m_RequiredAddOn); + if(ini.sections["Basic"].values["RequiredAddOn"]=="0") ini.sections["Basic"].values.erase("RequiredAddOn"); + +} + +void CBasic::PostNcDestroy() +{ + // do not call PostNcDestroy as this is a member of FinalSunDlg + //CPropertyPage::PostNcDestroy(); +} diff --git a/MissionEditor/Basic.h b/MissionEditor/Basic.h new file mode 100644 index 0000000..7687b58 --- /dev/null +++ b/MissionEditor/Basic.h @@ -0,0 +1,115 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_BASIC_H__C350C7AC_63C3_11D3_99E0_C30F10710B17__INCLUDED_) +#define AFX_BASIC_H__C350C7AC_63C3_11D3_99E0_C30F10710B17__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Basic.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CBasic + +class CBasic : public CDialog +{ + DECLARE_DYNCREATE(CBasic) + +// Konstruktion +public: + void UpdateStrings(); + void UpdateData(); + void UpdateDialog(); + CBasic(); + ~CBasic(); + +// Dialogfelddaten + //{{AFX_DATA(CBasic) + enum { IDD = IDD_BASIC }; + CMyComboBox m_RequiredAddOn; + CMyComboBox m_VeinGrowthEnabled; + CMyComboBox m_TruckCrate; + CMyComboBox m_TrainCrate; + CMyComboBox m_TiberiumGrowthEnabled; + CMyComboBox m_TiberiumDeathToVisceroid; + CMyComboBox m_SkipScore; + CMyComboBox m_SkipMapSelect; + CMyComboBox m_OneTimeOnly; + CMyComboBox m_Official; + CMyComboBox m_NextScenario; + CEdit m_Percent; + CEdit m_NewINIFormat; + CEdit m_Name; + CEdit m_MultiplayerOnly; + CEdit m_InitTime; + CMyComboBox m_IgnoreGlobalAITriggers; + CMyComboBox m_IceGrowthEnabled; + CMyComboBox m_FreeRadar; + CMyComboBox m_EndOfGame; + CEdit m_CarryOverCap; + CMyComboBox m_AltNextScenario; + //}}AFX_DATA + + +// Ăœberschreibungen + // Der Klassen-Assistent generiert virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CBasic) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// Implementierung +protected: + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CBasic) + afx_msg void OnChangeName(); + afx_msg void OnEditchangeNextscenario(); + afx_msg void OnEditchangeAltnextscenario(); + afx_msg void OnChangeNewiniformat(); + afx_msg void OnChangeCarryovercap(); + afx_msg void OnEditchangeEndofgame(); + afx_msg void OnEditchangeSkipscore(); + afx_msg void OnEditchangeOnetimeonly(); + afx_msg void OnEditchangeSkipmapselect(); + afx_msg void OnEditchangeOfficial(); + afx_msg void OnEditchangeIgnoreglobalaitriggers(); + afx_msg void OnEditchangeTruckcrate(); + afx_msg void OnEditchangeTraincrate(); + afx_msg void OnChangePercent(); + afx_msg void OnChangeMultiplayeronly(); + afx_msg void OnEditchangeTiberiumgrowthenabled(); + afx_msg void OnEditchangeVeingrowthenabled(); + afx_msg void OnEditchangeIcegrowthenabled(); + afx_msg void OnEditchangeTiberiumdeathtovisceroid(); + afx_msg void OnEditchangeFreeradar(); + afx_msg void OnChangeInittime(); + afx_msg void OnEditchangeRequiredaddon(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_BASIC_H__C350C7AC_63C3_11D3_99E0_C30F10710B17__INCLUDED_ diff --git a/MissionEditor/Bitmap2MapConverter.cpp b/MissionEditor/Bitmap2MapConverter.cpp new file mode 100644 index 0000000..6dfa91b --- /dev/null +++ b/MissionEditor/Bitmap2MapConverter.cpp @@ -0,0 +1,206 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Bitmap2MapConverter.cpp: Implementierung der Klasse CBitmap2MapConverter. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "stdafx.h" +#include "Bitmap2MapConverter.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +////////////////////////////////////////////////////////////////////// +// Konstruktion/Destruktion +////////////////////////////////////////////////////////////////////// + +CBitmap2MapConverter::CBitmap2MapConverter() +{ + +} + +CBitmap2MapConverter::~CBitmap2MapConverter() +{ + +} + +/* +I originally intended this tool to support different theaters, +but currently it does only support temperate. People can use +copy/paste to convert those maps though! +*/ +BOOL CBitmap2MapConverter::Convert(HBITMAP hBitmap, CMapData & mapdata) +{ + BITMAP bm; + + GetObject(hBitmap, sizeof(BITMAP), &bm); + + HBITMAP hUsed=hBitmap; + + + if(bm.bmWidth+bm.bmHeight>255) + { + float scalex=(float)bm.bmWidth/(float)bm.bmHeight; + int neededheight, neededwidth; + neededheight=255.0f/(scalex+1.0f); + neededwidth=255-neededheight; + + hUsed=CreateCompatibleBitmap(GetDC(NULL), neededwidth, neededheight); + HDC hDC=CreateCompatibleDC(GetDC(NULL)); + SelectObject(hDC, hUsed); + HDC hSrcDC=CreateCompatibleDC(GetDC(NULL)); + SelectObject(hSrcDC, hBitmap); + + StretchBlt(hDC, 0,0,neededwidth,neededheight, hSrcDC, 0,0,bm.bmWidth, bm.bmHeight, SRCCOPY); + + DeleteDC(hDC); + DeleteDC(hSrcDC); + + GetObject(hUsed, sizeof(BITMAP), &bm); + } + + HDC hDC; + hDC=CreateCompatibleDC(GetDC(NULL)); + SelectObject(hDC, hUsed); + + + srand(GetTickCount()); + + int i; + int e; + int theater=0; + mapdata.CreateMap(bm.bmWidth, bm.bmHeight, "TEMPERATE", 0); + + int isosize=mapdata.GetIsoSize(); + + + for(i=0;i<(*tiledata_count);i++) + if((*tiledata)[i].wTileSet==waterset) break; + + int water_start=i+8; // to 12 + + + int sandset=atoi((*tiles).sections["General"].values["SandTile"]); + int greenset=atoi((*tiles).sections["General"].values["GreenTile"]); + +#ifdef RA2_MODE + sandset=atoi((*tiles).sections["General"].values["GreenTile"]); + greenset=atoi((*tiles).sections["General"].values["RoughTile"]); +#endif + + for(i=0;i<(*tiledata_count);i++) + if((*tiledata)[i].wTileSet==sandset) break; + + int sand_start=i; + + for(i=0;i<(*tiledata_count);i++) + if((*tiledata)[i].wTileSet==greenset) break; + + int green_start=i; + + + for(i=0;iisosize*isosize) continue; + + FIELDDATA* fd=mapdata.GetFielddataAt(dwPos); + + int r=GetRValue(col); + int g=GetGValue(col); + int b=GetBValue(col); + + if(g>r && g>b) + { + if(theater!=1) + { + fd->wGround=0; + fd->bSubTile=0; + } + } + if(b>g && b>r) + { + int p=rand()*4/RAND_MAX; + fd->wGround=water_start+p; + fd->bSubTile=0; + } + if(g>b+25 && r>b+25 && g>120 && r>120) + { + if(theater!=1) + { + fd->wGround=sand_start; + fd->bSubTile=0; + } + } + if(b<20 && r<20 && g>20) + { +#ifdef RA2_MODE + if(g<140) // dark only +#endif + { + fd->wGround=green_start; + fd->bSubTile=0; + } + + } + + } + } + } + } + + mapdata.CreateShore(0,0,isosize, isosize); + + for(i=0;i. +*/ + +// Bitmap2MapConverter.h: Schnittstelle fĂ¼r die Klasse CBitmap2MapConverter. +// +////////////////////////////////////////////////////////////////////// + +#include "mapdata.h" + +#if !defined(AFX_BITMAP2MAPCONVERTER_H__42E61B61_E18A_11D4_9C88_816E6DEF4C47__INCLUDED_) +#define AFX_BITMAP2MAPCONVERTER_H__42E61B61_E18A_11D4_9C88_816E6DEF4C47__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CBitmap2MapConverter +{ +public: + BOOL Convert(HBITMAP hBitmap, CMapData& mapdata); + CBitmap2MapConverter(); + virtual ~CBitmap2MapConverter(); + +}; + +#endif // !defined(AFX_BITMAP2MAPCONVERTER_H__42E61B61_E18A_11D4_9C88_816E6DEF4C47__INCLUDED_) diff --git a/MissionEditor/Building.cpp b/MissionEditor/Building.cpp new file mode 100644 index 0000000..63e72a2 --- /dev/null +++ b/MissionEditor/Building.cpp @@ -0,0 +1,317 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Building.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "Building.h" +#include "mapdata.h" +#include "variables.h" +#include "inlines.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CBuilding + + +CBuilding::CBuilding(CWnd* pParent /*=NULL*/) + : CDialog(CBuilding::IDD, pParent) +{ + //{{AFX_DATA_INIT(CBuilding) + m_direction = _T(""); + m_house = _T(""); + m_flag1 = _T(""); + m_flag2 = _T(""); + m_energy = _T(""); + m_upgradecount = _T(""); + m_spotlight = _T(""); + m_upgrade1 = _T(""); + m_upgrade2 = _T(""); + m_upgrade3 = _T(""); + m_flag3 = _T(""); + m_flag4 = _T(""); + m_tag = _T(""); + //}}AFX_DATA_INIT + Init(); +} + + +void CBuilding::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBuilding) + DDX_Control(pDX, IDC_STRENGTH, m_strength_ctrl); + DDX_CBString(pDX, IDC_DIRECTION, m_direction); + DDX_CBString(pDX, IDC_HOUSE, m_house); + DDX_Text(pDX, IDC_P1, m_flag1); + DDX_Text(pDX, IDC_P2, m_flag2); + DDX_Text(pDX, IDC_P3, m_energy); + DDX_Text(pDX, IDC_P4, m_upgradecount); + DDX_Text(pDX, IDC_P5, m_spotlight); + DDX_CBString(pDX, IDC_P6, m_upgrade1); + DDX_CBString(pDX, IDC_P7, m_upgrade2); + DDX_CBString(pDX, IDC_P8, m_upgrade3); + DDX_Text(pDX, IDC_P9, m_flag3); + DDX_Text(pDX, IDC_P10, m_flag4); + DDX_CBString(pDX, IDC_TAG, m_tag); + //}}AFX_DATA_MAP + + +} + + +BEGIN_MESSAGE_MAP(CBuilding, CDialog) + //{{AFX_MSG_MAP(CBuilding) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CBuilding + +CString GetName(CString id) +{ + CIniFile& ini=Map->GetIniFile(); + if(ini.sections.find(id)!=ini.sections.end()) + { + if(ini.sections[id].values.find("Name")!=ini.sections[id].values.end()) + return ini.sections[id].values["Name"]; + + } + return rules.sections[id].values["Name"]; +} + +void CBuilding::OnOK() +{ + CDialog::OnOK(); + + m_strength=GetText(&m_strength_ctrl); + UpdateData(); + + char d[50]; + TruncSpace(m_spotlight); + itoa(atoi(m_spotlight), d, 10); + m_spotlight=d; + + m_house=TranslateHouse(m_house); + TruncSpace(m_upgrade1); + TruncSpace(m_upgrade2); + TruncSpace(m_upgrade3); + TruncSpace(m_tag); + TruncSpace(m_flag1); + TruncSpace(m_flag2); + TruncSpace(m_flag3); + TruncSpace(m_flag4); + + // +} + +BOOL CBuilding::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CIniFile& ini=Map->GetIniFile(); + + int i; + CComboBox* chouse, *ctag; + chouse=(CComboBox*)GetDlgItem(IDC_HOUSE); + ctag=(CComboBox*)GetDlgItem(IDC_TAG); + + ListHouses(*chouse, FALSE); + ListTags(*ctag, TRUE); + + + + m_strength_ctrl.SetRange(0,256); + m_strength_ctrl.SetPos(atoi(m_strength)); + + UpdateData(FALSE); + + int upgradecount=0; + if(strcmp(m_type,"GACTWR")==NULL) + upgradecount=1; + + + if(ini.sections.find(m_type)!=ini.sections.end()) + { + if(ini.sections[m_type].values.find("Upgrades")!=ini.sections[m_type].values.end()) + { + // ok we have our upgrade + upgradecount=atoi(ini.sections[m_type].values["Upgrades"]); + } + else + { + if(rules.sections[m_type].values.find("Upgrades")!=rules.sections[m_type].values.end()) + upgradecount=atoi(rules.sections[m_type].values["Upgrades"]); + } + } + else + { + if(rules.sections[m_type].values.find("Upgrades")!=rules.sections[m_type].values.end()) + upgradecount=atoi(rules.sections[m_type].values["Upgrades"]); + } + + + GetDlgItem(IDC_P5)->SendMessage(CB_SETCURSEL, atoi(m_spotlight), 0); + + if(upgradecount>0) + { + for(i=0;iAddString(((CString)unitname+" ("+GetName(unitname)+")")); + ((CComboBox*)GetDlgItem(IDC_P7))->AddString(((CString)unitname+" ("+GetName(unitname)+")")); + ((CComboBox*)GetDlgItem(IDC_P8))->AddString(((CString)unitname+" ("+GetName(unitname)+")")); + } + } + } + else + { + // ini did not specify thing specified + if(rules.sections[unitname].values.find("PowersUpBuilding")!=rules.sections[unitname].values.end()) + { + // rules file specified new PowersUpBuilding + if(_stricmp(rules.sections[unitname].values["PowersUpBuilding"], m_type)==NULL) + { + ((CComboBox*)GetDlgItem(IDC_P6))->AddString(((CString)unitname+" ("+GetName(unitname)+")")); + ((CComboBox*)GetDlgItem(IDC_P7))->AddString(((CString)unitname+" ("+GetName(unitname)+")")); + ((CComboBox*)GetDlgItem(IDC_P8))->AddString(((CString)unitname+" ("+GetName(unitname)+")")); + } + } + } + } + if(ini.sections.find("BuildingTypes")!=ini.sections.end()) + { + for(i=0;iAddString(((CString)unitname+" ("+GetName(unitname)+")")); + ((CComboBox*)GetDlgItem(IDC_P7))->AddString(((CString)unitname+" ("+GetName(unitname)+")")); + ((CComboBox*)GetDlgItem(IDC_P8))->AddString(((CString)unitname+" ("+GetName(unitname)+")")); + } + } + } + + } + } + } + + GetDlgItem(IDC_P8)->EnableWindow(TRUE); + GetDlgItem(IDC_P7)->EnableWindow(TRUE); + GetDlgItem(IDC_P6)->EnableWindow(TRUE); + GetDlgItem(IDC_P4)->EnableWindow(TRUE); + + if(upgradecount<3) + GetDlgItem(IDC_P8)->EnableWindow(FALSE); + if(upgradecount<2) + GetDlgItem(IDC_P7)->EnableWindow(FALSE); + if(upgradecount<1) + { + GetDlgItem(IDC_P6)->EnableWindow(FALSE); + GetDlgItem(IDC_P4)->EnableWindow(FALSE); + } + + + UpdateStrings(); + + return TRUE; +} + +void CBuilding::Init(CString house, CString strength, CString direction, CString tag, CString flag1, CString flag2, CString energy, CString upgradecount, CString spotlight, CString upgrade1, CString upgrade2, CString upgrade3, CString flag3, CString flag4) +{ + CIniFile& ini=Map->GetIniFile(); + + if(house=="") + { + house=TranslateHouse(Map->GetHouseID(0), TRUE); + } + else + m_house=TranslateHouse(house, TRUE); + + + + + m_house=TranslateHouse(house, TRUE); + m_flag1=flag1; + m_flag2=flag2; + m_flag3=flag3; + m_flag4=flag4; + m_spotlight=spotlight; + m_energy=energy; + m_upgrade1=upgrade1; + m_upgrade2=upgrade2; + m_upgrade3=upgrade3; + m_upgradecount=upgradecount; + m_strength=strength; + m_tag=tag; + m_direction=direction; + +} + +void CBuilding::UpdateStrings() +{ + SetWindowText(GetLanguageStringACP("StructCap")); + GetDlgItem(IDC_LHOUSE)->SetWindowText(GetLanguageStringACP("StructHouse")); + GetDlgItem(IDC_LDESC)->SetWindowText(GetLanguageStringACP("StructDesc")); + GetDlgItem(IDC_LSTRENGTH)->SetWindowText(GetLanguageStringACP("StructStrength")); + GetDlgItem(IDC_LDIRECTION)->SetWindowText(GetLanguageStringACP("StructDirection")); + GetDlgItem(IDC_LTAG)->SetWindowText(GetLanguageStringACP("StructTag")); + GetDlgItem(IDC_LAIREPAIRS)->SetWindowText(GetLanguageStringACP("StructAIRepairs")); + GetDlgItem(IDC_LENERGY)->SetWindowText(GetLanguageStringACP("StructEnergy")); + GetDlgItem(IDC_LUPGRADECOUNT)->SetWindowText(GetLanguageStringACP("StructUpgradeCount")); + GetDlgItem(IDC_LSPOTLIGHT)->SetWindowText(GetLanguageStringACP("StructSpotlight")); + GetDlgItem(IDC_LUPGRADE1)->SetWindowText(GetLanguageStringACP("StructUpgrade1")); + GetDlgItem(IDC_LUPGRADE2)->SetWindowText(GetLanguageStringACP("StructUpgrade2")); + GetDlgItem(IDC_LUPGRADE3)->SetWindowText(GetLanguageStringACP("StructUpgrade3")); + GetDlgItem(IDC_LP1)->SetWindowText(GetLanguageStringACP("StructP1")); + GetDlgItem(IDC_LP2)->SetWindowText(GetLanguageStringACP("StructP2")); + GetDlgItem(IDC_LP3)->SetWindowText(GetLanguageStringACP("StructP3")); + + SetDlgItemText(IDOK, GetLanguageStringACP("OK")); + SetDlgItemText(IDCANCEL, GetLanguageStringACP("Cancel")); +} diff --git a/MissionEditor/Building.h b/MissionEditor/Building.h new file mode 100644 index 0000000..739450d --- /dev/null +++ b/MissionEditor/Building.h @@ -0,0 +1,84 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_BUILDING_H__44A11CC0_84B6_11D3_B63B_F881F458F743__INCLUDED_) +#define AFX_BUILDING_H__44A11CC0_84B6_11D3_B63B_F881F458F743__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Building.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CBuilding + +class CBuilding : public CDialog +{ +// Konstruktion +public: + void UpdateStrings(); + CString m_type; + CString m_strength; + void Init(CString house="", CString strength="256", CString direction="0", CString tag="None", CString flag1="0", CString flag2="0", CString energy="1", CString upgradecount="0", CString spotlight="0", CString upgrade1="None", CString upgrade2="None", CString upgrade3="None", CString flag3="0", CString flag4="0"); + CBuilding(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CBuilding) + enum { IDD = IDD_BUILDING }; + CSliderCtrl m_strength_ctrl; + CString m_direction; + CString m_house; + CString m_flag1; + CString m_flag2; + CString m_energy; + CString m_upgradecount; + CString m_spotlight; + CString m_upgrade1; + CString m_upgrade2; + CString m_upgrade3; + CString m_flag3; + CString m_flag4; + CString m_tag; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CBuilding) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CBuilding) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_BUILDING_H__44A11CC0_84B6_11D3_B63B_F881F458F743__INCLUDED_ diff --git a/MissionEditor/CellTag.cpp b/MissionEditor/CellTag.cpp new file mode 100644 index 0000000..c310168 --- /dev/null +++ b/MissionEditor/CellTag.cpp @@ -0,0 +1,108 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// CellTag.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "CellTag.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CCellTag + + +CCellTag::CCellTag(CWnd* pParent /*=NULL*/) + : CDialog(CCellTag::IDD, pParent) +{ + //{{AFX_DATA_INIT(CCellTag) + m_tag = _T(""); + //}}AFX_DATA_INIT +} + + +void CCellTag::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CCellTag) + DDX_CBString(pDX, IDC_TAG, m_tag); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CCellTag, CDialog) + //{{AFX_MSG_MAP(CCellTag) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CCellTag + +string GetParam(string data, int pos); + +BOOL CCellTag::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CIniFile& ini=Map->GetIniFile(); + + CComboBox& m_Tag=*((CComboBox*)GetDlgItem(IDC_TAG)); + + if(ini.sections.find("Tags")==ini.sections.end()) + { + MessageBox("No tags are specified."); + OnCancel(); + } + else + { + ListTags(m_Tag, FALSE); + if(m_tag=="") m_Tag.SetCurSel(0); + } + + UpdateStrings(); + + return TRUE; +} + +void CCellTag::OnOK() +{ + UpdateData(); + + CDialog::OnOK(); + + TruncSpace(m_tag); +} + +void CCellTag::UpdateStrings() +{ + SetWindowText(GetLanguageStringACP("CellTagCap")); + GetDlgItem(IDC_LTAG)->SetWindowText(GetLanguageStringACP("CellTagTag")); + GetDlgItem(IDC_LDESC)->SetWindowText(GetLanguageStringACP("CellTagDesc")); + +} diff --git a/MissionEditor/CellTag.h b/MissionEditor/CellTag.h new file mode 100644 index 0000000..7b54107 --- /dev/null +++ b/MissionEditor/CellTag.h @@ -0,0 +1,68 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_CELLTAG_H__F41D5900_9133_11D3_B63B_D010F279DC93__INCLUDED_) +#define AFX_CELLTAG_H__F41D5900_9133_11D3_B63B_D010F279DC93__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// CellTag.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CCellTag + +class CCellTag : public CDialog +{ +// Konstruktion +public: + void UpdateStrings(); + CCellTag(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CCellTag) + enum { IDD = IDD_CELLTAG }; + CString m_tag; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CCellTag) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CCellTag) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_CELLTAG_H__F41D5900_9133_11D3_B63B_D010F279DC93__INCLUDED_ diff --git a/MissionEditor/ChangeSizeDlg.cpp b/MissionEditor/ChangeSizeDlg.cpp new file mode 100644 index 0000000..bbcd9da --- /dev/null +++ b/MissionEditor/ChangeSizeDlg.cpp @@ -0,0 +1,93 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// ChangeSizeDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "ChangeSizeDlg.h" +#include "variables.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CChangeSizeDlg + + +CChangeSizeDlg::CChangeSizeDlg(CWnd* pParent /*=NULL*/) + : CDialog(CChangeSizeDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CChangeSizeDlg) + m_Left = 0; + m_Height = 0; + m_Top = 0; + m_Width = 0; + //}}AFX_DATA_INIT + m_Width=Map->GetWidth(); + m_Height=Map->GetHeight(); +} + + +void CChangeSizeDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CChangeSizeDlg) + DDX_Text(pDX, IDC_LEFT, m_Left); + DDX_Text(pDX, IDC_HEIGHT, m_Height); + DDV_MinMaxInt(pDX, m_Height, 0, 400); + DDX_Text(pDX, IDC_TOP, m_Top); + DDX_Text(pDX, IDC_WIDTH, m_Width); + DDV_MinMaxInt(pDX, m_Width, 0, 400); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CChangeSizeDlg, CDialog) + //{{AFX_MSG_MAP(CChangeSizeDlg) + ON_EN_CHANGE(IDC_WIDTH, OnChangeWidth) + ON_EN_CHANGE(IDC_HEIGHT, OnChangeHeight) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CChangeSizeDlg + +void CChangeSizeDlg::OnChangeWidth() +{ + if(UpdateData(TRUE)) + { + m_Left=(m_Width-Map->GetWidth())/2; + UpdateData(FALSE); + } +} + +void CChangeSizeDlg::OnChangeHeight() +{ + if(UpdateData(TRUE)) + { + m_Top=(m_Height-Map->GetHeight())/2; + UpdateData(FALSE); + } +} diff --git a/MissionEditor/ChangeSizeDlg.h b/MissionEditor/ChangeSizeDlg.h new file mode 100644 index 0000000..51f254d --- /dev/null +++ b/MissionEditor/ChangeSizeDlg.h @@ -0,0 +1,70 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_CHANGESIZEDLG_H__60391D80_1E15_11D5_89B2_444553540000__INCLUDED_) +#define AFX_CHANGESIZEDLG_H__60391D80_1E15_11D5_89B2_444553540000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ChangeSizeDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CChangeSizeDlg + +class CChangeSizeDlg : public CDialog +{ +// Konstruktion +public: + CChangeSizeDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CChangeSizeDlg) + enum { IDD = IDD_CHANGESIZE }; + int m_Left; + int m_Height; + int m_Top; + int m_Width; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CChangeSizeDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CChangeSizeDlg) + afx_msg void OnChangeWidth(); + afx_msg void OnChangeHeight(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_CHANGESIZEDLG_H__60391D80_1E15_11D5_89B2_444553540000__INCLUDED_ diff --git a/MissionEditor/CliffModifier.cpp b/MissionEditor/CliffModifier.cpp new file mode 100644 index 0000000..bfa86d8 --- /dev/null +++ b/MissionEditor/CliffModifier.cpp @@ -0,0 +1,488 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// CliffModifier.cpp: Implementierung der Klasse CCliffModifier. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "stdafx.h" +#include "CliffModifier.h" +#include "variables.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +////////////////////////////////////////////////////////////////////// +// Konstruktion/Destruktion +////////////////////////////////////////////////////////////////////// + +CCliffModifier::CCliffModifier() +{ + +} + +CCliffModifier::~CCliffModifier() +{ + +} + +BOOL CCliffModifier::PlaceCliff(DWORD dwXFrom, DWORD dwYFrom, DWORD dwXDest, DWORD dwYDest, BOOL bAlternative) +{ + m_bAlternative=bAlternative; + + int x_diff, y_diff; + + x_diff=dwXDest-dwXFrom; + y_diff=dwYDest-dwYFrom; + + if(x_diff>0 && y_diff>0 && ((float)y_diff)/((float)x_diff) > 1.33f) + { + x_diff=0; + dwXDest=dwXFrom; + } + if(x_diff<0 && y_diff>0 && ((float)y_diff)/(-(float)x_diff) > 1.33f) + { + x_diff=0; + dwXDest=dwXFrom; + } + if(x_diff>0 && y_diff<0 && ((float)-y_diff)/((float)x_diff) > 1.33f) + { + x_diff=0; + dwXDest=dwXFrom; + } + if(x_diff<0 && y_diff<0 && (-(float)y_diff)/(-(float)x_diff) > 1.33f) + { + x_diff=0; + dwXDest=dwXFrom; + } + if(y_diff>0 && x_diff>0 && ((float)x_diff)/((float)y_diff) > 2) + { + y_diff=0; + dwYDest=dwYFrom; + } + if(y_diff<0 && x_diff>0 && ((float)x_diff)/(-(float)y_diff) > 2) + { + y_diff=0; + dwYDest=dwYFrom; + } + if(y_diff>0 && x_diff<0 && ((float)-x_diff)/((float)y_diff) > 2) + { + y_diff=0; + dwYDest=dwYFrom; + } + if(y_diff<0 && x_diff<0 && (-(float)x_diff)/(-(float)y_diff) > 2) + { + y_diff=0; + dwYDest=dwYFrom; + } + + m_dwFrom=dwXFrom + dwYFrom*Map->GetIsoSize(); + m_dwTo=dwXDest + dwYDest*Map->GetIsoSize(); + + if(!x_diff && !y_diff) return FALSE; + + if(x_diff && y_diff) + { + if((x_diff>0 && y_diff>0)) + { + m_direction=cd_verticdiag_bottom; + } + else if((x_diff<0 && y_diff<0)) + { + m_direction=cd_verticdiag_top; + } + else if((x_diff<0 && y_diff>0) ) + { + m_direction=cd_horizdiag_right; + } + else if(x_diff>0 && y_diff<0) + { + m_direction=cd_horizdiag_left; + } + + } + else if(y_diff<0) + { + m_direction=cd_horiz_left; + } + else if(y_diff>0) + { + m_direction=cd_horiz_right; + } + else if(x_diff<0) + { + m_direction=cd_vertic_top; + } + else if(x_diff>0) + { + m_direction=cd_vertic_bottom; + } + + switch(m_direction) + { + case cd_horiz_left: + m_addx=0; + m_addy=-1; + break; + case cd_horiz_right: + m_addx=0; + m_addy=1; + break; + case cd_horizdiag_left: + m_addx=1; + m_addy=-1; + break; + case cd_horizdiag_right: + m_addx=-1; + m_addy=1; + break; + case cd_vertic_top: + m_addx=-1; + m_addy=0; + break; + case cd_vertic_bottom: + m_addx=1; + m_addy=0; + break; + case cd_verticdiag_top: + m_addx=-1; + m_addy=-1; + break; + case cd_verticdiag_bottom: + m_addx=1; + m_addy=1; + break; + } + + int i,e; + DWORD dwCurPos=m_dwFrom; + int startheight=Map->GetHeightAt(dwCurPos); + + + + DWORD dwLastTile=-1; + + FIELDDATA* fd=Map->GetFielddataAt(dwCurPos); + int ground=fd->wGround; + int subtile=fd->bSubTile; + if(ground==0xFFFF) ground=0; + startheight-=(*tiledata)[ground].tiles[subtile].bZHeight; + + ModifyStartPos(&dwCurPos, FALSE); + + BOOL bSmall=FALSE; + DWORD dwFirstStartPos=dwCurPos; + DWORD dwTile=GetTileToPlace(dwCurPos, &bSmall); + + + + BOOL bFirstPos=TRUE; + + while(dwCurPos!=m_dwTo) + { + ModifyCurrentPos(&dwCurPos, TRUE, bSmall); + + if(!bFirstPos) + { + dwTile=GetTileToPlace(dwCurPos, &bSmall); + dwLastTile=dwTile; + } + else + bFirstPos=FALSE; + if(dwTile==-1) break; + + TILEDATA* t=&(*tiledata)[dwTile]; + + if(m_addx<0) dwCurPos+=t->cx*m_addx; + if(m_addy<0) dwCurPos+=t->cy*m_addy*Map->GetIsoSize(); + + + int o=0; + DWORD dwTmpTile=dwTile; + while(dwFirstStartPos!=dwCurPos && dwTile==dwLastTile) + { + o++; + if(o==10) break; + dwTmpTile=GetTileToPlace(dwCurPos, &bSmall); + + if((*tiledata)[dwTmpTile].cx==(*tiledata)[dwTile].cx && (*tiledata)[dwTile].cy==(*tiledata)[dwTmpTile].cy) + dwTile=dwTmpTile; + } + + + + t=&(*tiledata)[dwTile]; + + + + + + + + int p=0; + for(i=0;icx;i++) + { + for(e=0;ecy;e++) + { + + if(t->tiles[p].pic!=NULL) + { + + + Map->SetHeightAt(dwCurPos+i+e*Map->GetIsoSize(), startheight+t->tiles[p].bZHeight); + Map->SetTileAt(dwCurPos+i+e*Map->GetIsoSize(), dwTile, p); + + } + p++; + } + } + + if(m_addx>0) dwCurPos+=t->cx*m_addx; + if(m_addy>0) dwCurPos+=t->cy*m_addy*Map->GetIsoSize(); + + ModifyCurrentPos(&dwCurPos, FALSE, bSmall); + + dwLastTile=dwTile; + } + + return TRUE; +} + +void CCliffModifier::ModifyStartPos(DWORD *dwStartPos, BOOL bSmall) +{ + +} + +void CCliffModifier::ModifyCurrentPos(DWORD *dwPos, BOOL bBeforePlacing, BOOL bSmall) +{ + +} + +DWORD CCliffModifier::GetTileToPlace(DWORD dwPos, BOOL* bSmall) +{ + vector careables; + vector useables; + map notusedascliff; + + CString type; + int count=0; + + + switch(m_direction) + { + case cd_horiz_left: + case cd_horiz_right: + type="horiz_"; + break; + case cd_horizdiag_left: + case cd_horizdiag_right: + type="horiz_diag_"; + break; + case cd_vertic_top: + case cd_vertic_bottom: + type="vertic_"; + break; + case cd_verticdiag_top: + case cd_verticdiag_bottom: + type="vertic_diag_"; + break; + } + + + CString sec=GetDataSection(); + CIniFile& ini=Map->GetIniFile(); + if(g_data.sections.find(sec+ini.sections["Map"].values["Theater"])!=g_data.sections.end()) + sec=sec+ini.sections["Map"].values["Theater"]; + + count=atoi(g_data.sections[sec].values[type+"c"]); + + + + int i; + DWORD dwStartSet=0; + /*for(i=0;i<(*tiledata_count);i++) + { + if( (!m_bAlternative && (*tiledata)[i].wTileSet==cliffset) || (m_bAlternative && (*tiledata)[i].wTileSet==cliff2set)) + { + dwStartSet=i; + break; + } + }*/ + // a bit faster: + if(m_bAlternative) dwStartSet=cliff2set_start; + else dwStartSet=cliffset_start; + + for(i=0;iGetIsoSize(); + ModifyStartPos(&dwCurPos, FALSE); + int e; + for(i=-1;i<2;i++) + { + for(e=-1;e<2;e++) + { + FIELDDATA* fd=Map->GetFielddataAt(dwCurPos+i+e*isosize); + int ground=fd->wGround; + if(ground==0xFFFF) ground=0; + + if( (*tiledata)[ground].wTileSet==cliffset && notusedascliff.find(ground)==notusedascliff.end()) + { + + + if(i==0 && e==-1) {corner_searched="cornerleft_";break;} + if(i==0 && e==1) {corner_searched="cornerright_";break;} + if(i==-1 && e==0) {corner_searched="cornertop_";break;} + if(i==1 && e==0) {corner_searched="cornerbottom_";break;} + /*if(e==-1) {corner_searched="cornerleft_";break;} + if(e==1) {corner_searched="cornerright_";break;} + if(i==-1) {corner_searched="cornertop_";break;} + if(i==1) {corner_searched="cornerbottom_";break;}*/ + } + + } + if(corner_searched.GetLength()>0) break; + } + + BOOL bCornerFound=FALSE; + if(g_data.sections[sec].FindName(type+corner_searched+"c")>=0) + { + int icount=atoi(g_data.sections[sec].values[type+corner_searched+"c"]); + if(icount) + { + bCornerFound=TRUE; + count=icount; + } + } + + if(!bCornerFound) corner_searched=""; + + if(count==0) return -1; + + + DWORD dwX=dwPos%Map->GetIsoSize(); + DWORD dwY=dwPos/Map->GetIsoSize(); + DWORD dwDX=m_dwTo%Map->GetIsoSize(); + DWORD dwDY=m_dwTo/Map->GetIsoSize(); + + + for(i=0;i0 && dwX+m_addx*t.cx>dwDX) continue; + if(m_addy>0 && dwY+m_addy*t.cy>dwDY) continue; + if(m_addx<0 && dwX+m_addx*t.cxt1.cx || t.cy>t1.cy) {*bSmall=TRUE; break;} + } + + // check for water + BOOL bWater=FALSE; + for(i=0;iGetFielddataAt(dwPos+i+e*Map->GetIsoSize()); + int ground=fd->wGround; + if(ground==0xFFFF) ground=0; + if((i==t1.cx-1 || e==t1.cy-1) && (*tiledata)[ground].tiles[fd->bSubTile].bHackedTerrainType==TERRAINTYPE_WATER) + { + bWater=TRUE; + break; + } + } + if(bWater) break; + } + + + if(bWater && useables[k]-dwStartSet<22) + { + CString tset; + char c[50]; + int watercliffs=atoi(tiles->sections["General"].values["WaterCliffs"]); + if(m_bAlternative) watercliffs=cliffwater2set; + itoa(watercliffs, c, 10); + int e; + for(e=0;e<4-strlen(c);e++) + tset+="0"; + tset+=c; + CString sec="TileSet"; + sec+=tset; + + if(tiles->sections.find(sec)==tiles->sections.end()) return useables[k]; + + + if(atoi(tiles->sections[sec].values["TilesInSet"])>useables[k]-dwStartSet) + { + DWORD dwStartWaterSet=0; + for(i=0;i<(*tiledata_count);i++) + { + if((*tiledata)[i].wTileSet==watercliffs) + { + dwStartWaterSet=i; + return dwStartWaterSet+(useables[k]-dwStartSet); + } + } + + + } + } + + return useables[k]; +} + + diff --git a/MissionEditor/CliffModifier.h b/MissionEditor/CliffModifier.h new file mode 100644 index 0000000..0f12e03 --- /dev/null +++ b/MissionEditor/CliffModifier.h @@ -0,0 +1,62 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// CliffModifier.h: Schnittstelle fĂ¼r die Klasse CCliffModifier. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_CLIFFMODIFIER_H__3853D323_CD37_11D4_9C87_F2DC6A2E6849__INCLUDED_) +#define AFX_CLIFFMODIFIER_H__3853D323_CD37_11D4_9C87_F2DC6A2E6849__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "TerrainModifier.h" + + + +class CCliffModifier : public CTerrainModifier +{ + +public: + virtual BOOL PlaceCliff(DWORD dwXFrom, DWORD dwYFrom, DWORD dwXDest, DWORD dwYDest, BOOL bAlternative=FALSE); + CCliffModifier(); + virtual ~CCliffModifier(); + +protected: + virtual CString GetDataSection()=0; + virtual void ModifyCurrentPos(DWORD* dwPos, BOOL bBeforePlacing, BOOL bSmall); + virtual void ModifyStartPos(DWORD* dwStartPos, BOOL bSmall); + + enum e_cliffdirections {cd_horiz_left, cd_horiz_right, cd_horizdiag_left, + cd_horizdiag_right, cd_vertic_top, cd_vertic_bottom, cd_verticdiag_top, cd_verticdiag_bottom }; + + DWORD m_dwTo; + DWORD m_dwFrom; + e_cliffdirections m_direction; + + int m_addx; + int m_addy; + BOOL m_bAlternative; + virtual DWORD GetTileToPlace(DWORD dwPos, BOOL* bSmall) ; +}; + +#endif // !defined(AFX_CLIFFMODIFIER_H__3853D323_CD37_11D4_9C87_F2DC6A2E6849__INCLUDED_) diff --git a/MissionEditor/ComboUInputDlg.cpp b/MissionEditor/ComboUInputDlg.cpp new file mode 100644 index 0000000..d0bfff4 --- /dev/null +++ b/MissionEditor/ComboUInputDlg.cpp @@ -0,0 +1,135 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "finalsun.h" +#include "ComboUInputDlg.h" +#include "functions.h" +#include "inlines.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CComboUInputDlg + + +CComboUInputDlg::CComboUInputDlg(CWnd* pParent /*=NULL*/) + : CDialog(CComboUInputDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CComboUInputDlg) + m_Caption = _T(""); + m_Combo = _T(""); + //}}AFX_DATA_INIT + + m_type=0; + bTruncateStrings=FALSE; +} + + +void CComboUInputDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CComboUInputDlg) + DDX_Text(pDX, IDC_CAPTION, m_Caption); + DDX_CBString(pDX, IDC_COMBO1, m_Combo); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CComboUInputDlg, CDialog) + //{{AFX_MSG_MAP(CComboUInputDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CComboUInputDlg + +BOOL CComboUInputDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CComboBox* box=(CComboBox*)GetDlgItem(IDC_COMBO1); + + switch(m_type) + { + case COMBOUINPUT_HOUSES: + { + ListHouses(*box, FALSE, FALSE); + break; + } + case COMBOUINPUT_COUNTRIES: + ListHouses(*box, FALSE, TRUE); + break; + case COMBOUINPUT_TRIGGERS: + ListTriggers(*box); + break; + case COMBOUINPUT_TAGS: + ListTags(*box, FALSE); + break; + case COMBOUINPUT_HOUSES_N: + { + ListHouses(*box, TRUE, FALSE); + break; + } + case COMBOUINPUT_COUNTRIES_N: + ListHouses(*box, TRUE, TRUE); + break; + case COMBOUINPUT_MANUAL: + int i; + for(i=0;iAddString(m_ManualStrings[i]); + } + + box->SetCurSel(0); + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} + +void CComboUInputDlg::OnOK() +{ + UpdateData(TRUE); + + if(m_type==COMBOUINPUT_TRIGGERS || m_type==COMBOUINPUT_TAGS || m_type==COMBOUINPUT_HOUSES_N || m_type==COMBOUINPUT_COUNTRIES_N) TruncSpace(m_Combo); + else if(m_type==COMBOUINPUT_MANUAL) + { + if(bTruncateStrings) TruncSpace(m_Combo); + } + else + { + m_Combo=TranslateHouse(m_Combo, FALSE); + } + + EndDialog(0); + + //CDialog::OnOK(); +} + +void CComboUInputDlg::OnCancel() +{ + // TODO: Zusätzlichen Bereinigungscode hier einfĂ¼gen + + //CDialog::OnCancel(); +} diff --git a/MissionEditor/ComboUInputDlg.h b/MissionEditor/ComboUInputDlg.h new file mode 100644 index 0000000..f6e472e --- /dev/null +++ b/MissionEditor/ComboUInputDlg.h @@ -0,0 +1,84 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_COMBOUINPUTDLG_H__2EEED280_9A8C_11D5_89B3_00E07D97C331__INCLUDED_) +#define AFX_COMBOUINPUTDLG_H__2EEED280_9A8C_11D5_89B3_00E07D97C331__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ComboUInputDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CComboUInputDlg + +#include + +using namespace std; + +#define COMBOUINPUT_HOUSES 0 +#define COMBOUINPUT_COUNTRIES 1 +#define COMBOUINPUT_TRIGGERS 2 +#define COMBOUINPUT_TAGS 3 +#define COMBOUINPUT_HOUSES_N 4 +#define COMBOUINPUT_COUNTRIES_N 5 +#define COMBOUINPUT_MANUAL 6 + +class CComboUInputDlg : public CDialog +{ +// Konstruktion +public: + int m_type; + vector m_ManualStrings; + BOOL bTruncateStrings; + CComboUInputDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CComboUInputDlg) + enum { IDD = IDD_COMBO_UINPUT }; + CString m_Caption; + CString m_Combo; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CComboUInputDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CComboUInputDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual void OnCancel(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_COMBOUINPUTDLG_H__2EEED280_9A8C_11D5_89B3_00E07D97C331__INCLUDED_ diff --git a/MissionEditor/Defines.h b/MissionEditor/Defines.h new file mode 100644 index 0000000..52c6937 --- /dev/null +++ b/MissionEditor/Defines.h @@ -0,0 +1,200 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/************************** + Defines.h + Place any definitions here +**************************/ + +// set NOSURFACES to use palettized tile drawing - probably slower, but using less memory +#define NOSURFACES +#define NOSURFACES_EXTRACT // this will cause tiles to be extracted +// #undef NOSURFACES // enable this if display is too slow + +// set NOSURFACES_OBJECTS to use palettized object & overlay drawing - slower, but better display +#define NOSURFACES_OBJECTS +// #undef NOSURFACES_OBJECTS + +// MW 08/07/01: define SMUDGE_SUPP if you want to support smudges +// added this as switch because if there are problems with this new feature we can just disable it +#define SMUDGE_SUPP + +// tiberium / ore +#ifdef RA2_MODE +#define RIPARIUS_BEGIN 102 +#define RIPARIUS_END 121 +#define CRUENTUS_BEGIN 27 +#define CRUENTUS_END 38 +#define VINIFERA_BEGIN 127 +#define VINIFERA_END 146 +#define ABOREUS_BEGIN 147 +#define ABOREUS_END 166 +#else +#define RIPARIUS_BEGIN 102 +#define RIPARIUS_END 121 +#define CRUENTUS_BEGIN 27 +#define CRUENTUS_END 38 +#define VINIFERA_BEGIN 127 +#define VINIFERA_END 146 +#define ABOREUS_BEGIN 147 +#define ABOREUS_END 166 +#endif + +// picdata type +#define PICDATA_TYPE_BMP 0 +#define PICDATA_TYPE_SHP 1 +#define PICDATA_TYPE_VXL 2 + +#define SUBPOS_COUNT 3 +#define REAL_SUBPOS_COUNT 3 + +#define SOUND_NONE 0 +#define SOUND_POSITIVE 1 +#define SOUND_NEGATIVE 2 +#define SOUND_LAYDOWNTILE 3 +#define SOUND_DELETETILE 4 + +// actiondata modes (isoview user interface) +#define ACTIONMODE_PLACE 1 // place any unit, building, tree or overlay +#define ACTIONMODE_ERASEFIELD 2 // delete any unit, building, or tree +#define ACTIONMODE_WAYPOINT 3 // any waypoint editing +#define ACTIONMODE_CELLTAG 4 // any celltag editing +#define ACTIONMODE_NODE 5 // any node editing +#define ACTIONMODE_MAPTOOL 6 +#define ACTIONMODE_SETTILE 10 // setting ground tiles +#define ACTIONMODE_HEIGHTEN 11 // heighten ground +#define ACTIONMODE_LOWER 12 // lower ground +#define ACTIONMODE_LOWERTILE 13 +#define ACTIONMODE_HEIGHTENTILE 14 +#define ACTIONMODE_FLATTENGROUND 15 +#define ACTIONMODE_HIDETILESET 16 // make specific tileset invisible +#define ACTIONMODE_HIDEFIELD 17 // make specific field invisible +#define ACTIONMODE_CLIFFFRONT 18 // add front cliff +#define ACTIONMODE_CLIFFBACK 19 // add back cliff +#define ACTIONMODE_COPY 20 +#define ACTIONMODE_PASTE 21 +#define ACTIONMODE_RANDOMTERRAIN 22 +#define ACTIONMODE_SMUDGE 23 + +// paramtype list types +#define PARAMTYPE_NOTHING 0 +#define PARAMTYPE_HOUSES 1 +#define PARAMTYPE_TEAMTYPES 2 +#define PARAMTYPE_UNITTYPES 3 +#define PARAMTYPE_INFANTRYTYPES 4 +#define PARAMTYPE_AIRCRAFTTYPES 5 +#define PARAMTYPE_BUILDINGTYPES 6 +#define PARAMTYPE_VIDEOS 7 +#define PARAMTYPE_TUTORIALTEXTS 8 +#define PARAMTYPE_TRIGGERS 9 +#define PARAMTYPE_YESNO 10 +#define PARAMTYPE_SOUNDS 11 +#define PARAMTYPE_THEMES 12 +#define PARAMTYPE_SPEECHES 13 +#define PARAMTYPE_SPECIALWEAPONS 14 +#define PARAMTYPE_ANIMATIONS 15 +#define PARAMTYPE_PARTICLES 16 +#define PARAMTYPE_WAYPOINTS 17 +#define PARAMTYPE_CRATETYPES 18 +#define PARAMTYPE_SPEECHBUBBLETYPES 19 +#define PARAMTYPE_GLOBALS 20 +#define PARAMTYPE_RULESGLOBALS 27 +#define PARAMTYPE_BUILDINGTYPESINI 28 +#define PARAMTYPE_TECHTYPES 29 + +#define THEATER0 "TEMPERATE" +#define THEATER1 "SNOW" +#define THEATER2 "URBAN" +#define THEATER3 "NEWURBAN" +#define THEATER4 "LUNAR" +#define THEATER5 "DESERT" + + +#define ra2_mode 1 +#define ts_mode 0 + + +#ifndef RA2_MODE + +#define NO_URBAN +#define MAXHEIGHT 14 + +#define f_y 24 +#define f_x 48 + +#define TERRAINTYPE_GROUND 0x0d +#define TERRAINTYPE_WATER 0x09 +#define TERRAINTYPE_IMPASSABLE 0x0f +#define TERRAINTYPE_ROUGH 0x0e +#define TERRAINTYPE_PAVED 0x0b +#define TERRAINTYPE_BUILDING 0x07 +#define TERRAINTYPE_DIRT_ROAD 0x0c +#define TERRAINTYPE_ICE 0x01 + +#define MAINMIX "TIBSUN.MIX" +#define HOUSES "Houses" +#define MAPHOUSES "Houses" + +#endif +#ifdef RA2_MODE + +#define MAINMIX "RA2.MIX" +#define HOUSES "Countries" +#define MAPHOUSES "Houses" + +#define MAXHEIGHT 14 + +#define f_y 30 +#define f_x 60 + +#define TERRAINTYPE_GROUND 0x0d +#define TERRAINTYPE_WATER 0x09 +#define TERRAINTYPE_IMPASSABLE 0x0f +#define TERRAINTYPE_ROUGH 0x0e +#define TERRAINTYPE_PAVED 0x0b +#define TERRAINTYPE_BUILDING 0x07 +#define TERRAINTYPE_DIRT_ROAD 0x0c +#define TERRAINTYPE_ICE 0x01 + +#endif + +#define SLOPE_UP_RIGHT 1 +#define SLOPE_UP_BOTTOM 2 +#define SLOPE_UP_LEFT 3 +#define SLOPE_UP_TOP 4 +#define SLOPE_UP_RIGHTBOTTOM 5 +#define SLOPE_UP_LEFTBOTTOM 6 +#define SLOPE_UP_LEFTTOP 7 +#define SLOPE_UP_RIGHTTOP 8 +#define SLOPE_DOWN_LEFTTOP 9 +#define SLOPE_DOWN_RIGHTTOP 10 +#define SLOPE_DOWN_RIGHTBOTTOM 11 +#define SLOPE_DOWN_LEFTBOTTOM 12 +#define SLOPE_DOWN_TOP 13 // z difference of x-1/y-1 to x+1/y+1 is -2, to x+1/y 1, to x/y+1 1 +#define SLOPE_DOWN_RIGHT 14 +#define SLOPE_DOWN_BOTTOM 15 +#define SLOPE_DOWN_LEFT 16 +#define SLOPE_UP_LEFTBOTTOM_AND_RIGHTTOP 17 +#define SLOPE_UP_LEFTTOP_AND_RIGHTBOTTOM 18 +#define SLOPE_UP_LEFTBOTTOM_AND_RIGHTTOP2 19 +#define SLOPE_UP_LEFTTOP_AND_RIGHTBOTTOM2 20 + +// max images loaded from one overlay graphic file (SHP) +#define max_ovrl_img 60 \ No newline at end of file diff --git a/MissionEditor/DownloadSession.cpp b/MissionEditor/DownloadSession.cpp new file mode 100644 index 0000000..a487644 --- /dev/null +++ b/MissionEditor/DownloadSession.cpp @@ -0,0 +1,49 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "stdafx.h" +#include "DownloadSession.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +////////////////////////////////////////////////////////////////////// +// Konstruktion/Destruktion +////////////////////////////////////////////////////////////////////// + +CDownloadSession::CDownloadSession():CInternetSession("FinalAlert Download", 1, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC | INTERNET_FLAG_DONT_CACHE) +{ + +} + +CDownloadSession::~CDownloadSession() +{ + +} + + +void CDownloadSession::OnStatusCallback(DWORD dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength ) +{ + +} \ No newline at end of file diff --git a/MissionEditor/DownloadSession.h b/MissionEditor/DownloadSession.h new file mode 100644 index 0000000..3f6ed90 --- /dev/null +++ b/MissionEditor/DownloadSession.h @@ -0,0 +1,40 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include + +#if !defined(AFX_DOWNLOADSESSION_H__944482A1_E98F_11D4_9C88_82B0A7E03C49__INCLUDED_) +#define AFX_DOWNLOADSESSION_H__944482A1_E98F_11D4_9C88_82B0A7E03C49__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CDownloadSession : public CInternetSession +{ +public: + CDownloadSession(); + virtual ~CDownloadSession(); +protected: + virtual void OnStatusCallback( DWORD dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength ); + +}; + +#endif // !defined(AFX_DOWNLOADSESSION_H__944482A1_E98F_11D4_9C88_82B0A7E03C49__INCLUDED_) diff --git a/MissionEditor/DynamicGraphDlg.cpp b/MissionEditor/DynamicGraphDlg.cpp new file mode 100644 index 0000000..6cad11d --- /dev/null +++ b/MissionEditor/DynamicGraphDlg.cpp @@ -0,0 +1,67 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "finalsun.h" +#include "DynamicGraphDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CDynamicGraphDlg + + +CDynamicGraphDlg::CDynamicGraphDlg(CWnd* pParent /*=NULL*/) + : CDialog(CDynamicGraphDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDynamicGraphDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Elementinitialisierung ein + //}}AFX_DATA_INIT + + Create(CDynamicGraphDlg::IDD, pParent); +} + + +void CDynamicGraphDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDynamicGraphDlg) + DDX_Control(pDX, IDC_PROGRESS, m_Progress); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDynamicGraphDlg, CDialog) + //{{AFX_MSG_MAP(CDynamicGraphDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Zuordnungsmakros fĂ¼r Nachrichten ein + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CDynamicGraphDlg + +void CDynamicGraphDlg::PostNcDestroy() +{ + // delete this; +} diff --git a/MissionEditor/DynamicGraphDlg.h b/MissionEditor/DynamicGraphDlg.h new file mode 100644 index 0000000..8cf4286 --- /dev/null +++ b/MissionEditor/DynamicGraphDlg.h @@ -0,0 +1,69 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_DYNAMICGRAPHDLG_H__ED5FED21_83F5_11D4_9C87_86ADAD0FBC4A__INCLUDED_) +#define AFX_DYNAMICGRAPHDLG_H__ED5FED21_83F5_11D4_9C87_86ADAD0FBC4A__INCLUDED_ + +#include "resource.h" + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DynamicGraphDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CDynamicGraphDlg + +class CDynamicGraphDlg : public CDialog +{ +// Konstruktion +public: + CDynamicGraphDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CDynamicGraphDlg) + enum { IDD = IDD_DYNAMICLOAD }; + CProgressCtrl m_Progress; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CDynamicGraphDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CDynamicGraphDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Member-Funktionen ein + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_DYNAMICGRAPHDLG_H__ED5FED21_83F5_11D4_9C87_86ADAD0FBC4A__INCLUDED_ diff --git a/MissionEditor/FinalSun.cpp b/MissionEditor/FinalSun.cpp new file mode 100644 index 0000000..b65e21c --- /dev/null +++ b/MissionEditor/FinalSun.cpp @@ -0,0 +1,628 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// +// This is the application code. Mainly shows the main dialog and initializes some application global stuff +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "FinalSunDlg.h" +#include "structs.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" +#include "inlines.h" +#include + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define APPID "FinalSun App" + +extern char AppPath[]; + +extern ACTIONDATA AD; + +///////////////////////////////////////////////////////////////////////////// +// CFinalSunApp + +BEGIN_MESSAGE_MAP(CFinalSunApp, CWinApp) + //{{AFX_MSG_MAP(CFinalSunApp) + //}}AFX_MSG_MAP + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFinalSunApp construction + +void __cdecl term_func() +{ + if (MessageBox(0, "Fatal error. Exit FinalSun?", "Fatal error", MB_YESNO) == IDCANCEL) return; + + exit(-1); +} + + +CFinalSunApp::CFinalSunApp() +{ + m_cf = RegisterClipboardFormat("FINAL*FORMAT"); + + if (!m_cf) MessageBox(0, "Failed to register clipboard format, clipboard functions not available", "", 0); + + tiledata_count = &t_tiledata_count; + tiledata = &t_tiledata; + + // first: set up global variable AppPath + // [02/16/2000] using GetModuleFileName() instead of GetCurrentDirectory(): always the correct path + wchar_t AppPathUtf16[MAX_PATH] = { 0 }; + GetModuleFileNameW(NULL, AppPathUtf16, MAX_PATH); + strcpy_s(AppPath, utf16ToUtf8(AppPathUtf16).c_str()); + *(strrchr(AppPath, '\\') + 1) = 0; + + // Initialize AppData + const std::wstring AppDataPathFolder = utf8ToUtf16(u8AppDataPath.substr(0, u8AppDataPath.size() - 1)); + auto create_dir_res = SHCreateDirectoryExW(NULL, AppDataPathFolder.c_str(), nullptr); + if (ERROR_SUCCESS != create_dir_res && ERROR_ALREADY_EXISTS != create_dir_res) + { + wchar_t err_msg[1025] = { 0 }; + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, 0, create_dir_res, 0, err_msg, 1024, NULL); + MessageBoxW(NULL, err_msg, (std::wstring(L"Failed to open ") + AppDataPathFolder).c_str(), 0); + exit(1); + } + + if ((GetFileAttributesW(AppDataPathFolder.c_str()) & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY) + { + MessageBoxW(NULL, (AppDataPathFolder + L" must be a directory, not a file").c_str(), (std::wstring(L"Failed to open ") + AppDataPathFolder).c_str(), 0); + exit(1); + } + + /*memset(t_tilepics, 0, sizeof(TILEPICDATA)*10000); + memset(s_tilepics, 0, sizeof(TILEPICDATA)*10000);*/ + + m_Options.LanguageName = "English"; + m_Options.bFlat = FALSE; + m_Options.bEasy = FALSE; + m_Options.bSupportMarbleMadness = FALSE; + m_Options.bMarbleMadness = FALSE; + + auto log = u8AppDataPath; +#ifdef TS_MODE + log += "finalsunlog.txt"; +#else + log += "finalalert2log.txt"; +#endif + m_u8LogFileName = log; + errstream.open(m_u8LogFileName, ios_base::trunc); + errstream << "\uFEFF"; // BOM + +#ifdef TS_MODE + errstream << "FinalSun log file" << std::endl << "----------------------" << std::endl << std::endl; +#else + errstream << "FinalAlert 2 log file" << std::endl << "----------------------" << std::endl << std::endl; +#endif + errstream << "CFinalSunApp::CFinalSunApp() called" << std::endl; + + errstream << "App Path: " << AppPath << std::endl; + errstream << "AppData Path: " << u8AppDataPath << std::endl; + errstream << "Locale: " << setlocale(LC_ALL, nullptr) << std::endl; + errstream << "Windows ACP: " << GetACP() << std::endl; + + + INITCOMMONCONTROLSEX ctr; + ctr.dwSize = sizeof(INITCOMMONCONTROLSEX); + ctr.dwICC = ICC_STANDARD_CLASSES; + if (!InitCommonControlsEx(&ctr)) + { + errstream << "Error: Common controls could not be initialized" << std::endl; + MessageBox(0, "Common controls could not be initialized.", "Error", 0); + } + + errstream << std::endl << std::endl << std::endl; + + errstream.flush(); + +} + + +///////////////////////////////////////////////////////////////////////////// +// CFinalSunApp initialization + +BOOL CFinalSunApp::InitInstance() +{ + m_hAccel = LoadAccelerators(this->m_hInstance, MAKEINTRESOURCE(IDR_MAIN)); + +#ifndef NOSURFACES + if (GetDeviceCaps(GetDC(GetDesktopWindow()), BITSPIXEL) <= 8) + { + MessageBox(0, "You currently only have 8 bit color mode enabled. This is not recommended. You can continue, but this will cause a significant slowdown while loading graphics, and result in poor graphics quality", "Error", 0); + //exit(0); + } +#else + if (GetDeviceCaps(GetDC(GetDesktopWindow()), BITSPIXEL) <= 8) + { + MessageBox(0, "You currently only have 8 bit color mode enabled. FinalSun/FinalAlert 2 will not work in 8 bit color mode. See readme.txt for further information!", "Error", 0); + exit(0); + } +#endif + + ParseCommandLine(); + + // Load application data + std::string datafile = AppPath; +#ifdef TS_MODE + datafile += "\\FSData.ini"; +#else + datafile += "\\FAData.ini"; +#endif + + g_data.LoadFile(datafile); + + // Load language data + std::string languagefile = AppPath; +#ifndef RA2_MODE + languagefile += "\\FSLanguage.ini"; +#else + languagefile += "\\FALanguage.ini"; +#endif + language.LoadFile(languagefile); + + if (language.sections.size() == 0) + { + MessageBox(0, "FALanguage.ini does not exist or is not valid (download corrupt?)", "", 0); + exit(0); + } + +#ifndef RA2_MODE + const std::string iniName = "FinalSun.ini"; + const std::string defaultIniName = "FinalSunDefaults.ini"; +#else + const std::string iniName = "FinalAlert.ini"; + const std::string defaultIniName = "FinalAlertDefaults.ini"; +#endif + + // ok lets get some options + CIniFile optini; + std::string iniFile = u8AppDataPath + iniName; + std::string templateIniFile = std::string(AppPath) + defaultIniName; + + bool copiedDefaultFile = false; + if (!DoesFileExist(iniFile.c_str())) + { + if (CopyFileW(utf8ToUtf16(templateIniFile).c_str(), utf8ToUtf16(iniFile).c_str(), TRUE)) + copiedDefaultFile = true; + } + + optini.LoadFile(iniFile); + +#ifdef RA2_MODE + CString game = "RA2"; + CString app = "FinalAlert"; +#else + CString game = "TS"; + CString app = "FinalSun"; +#endif + + std::wstring key; +#ifdef RA2_MODE + key = L"Software\\Westwood\\Red Alert 2"; +#else + key = L"Software\\Westwood\\Tiberian Sun"; +#endif + + auto& opts = m_Options; + + HKEY hKey = 0; + int res; + res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_EXECUTE/*KEY_ALL_ACCESS*/, &hKey); + if (res != ERROR_SUCCESS) + { + std::wstring s = L"Failed to access registry. Using manual setting. Error was:\n"; + wchar_t c[1024] = { 0 }; + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, 0, res, 0, c, 1023, NULL); + MessageBoxW(0, (s + c).c_str(), L"Error", 0); + opts.TSExe = optini.sections[game].values["Exe"]; + } + else + { + // key opened + wchar_t path[MAX_PATH + 1] = { 0 }; + DWORD pathsize = MAX_PATH; + DWORD type = REG_SZ; + if ((res = RegQueryValueExW(hKey, L"InstallPath", 0, &type, (unsigned char*)path, &pathsize)) != ERROR_SUCCESS) + { + std::wstring s = L"Failed to access registry. Using manual setting. Error was:\n"; + wchar_t c[1024] = { 0 }; + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, 0, res, 0, c, 1023, NULL); + MessageBoxW(0, (s + c).c_str(), L"Error", 0); + opts.TSExe = optini.sections[game].values["Exe"]; + } + else + opts.TSExe = path; + } + + + if (copiedDefaultFile || + optini.sections.size() == 0 || + opts.TSExe.GetLength() == 0 || + optini.sections[app].values["Language"].GetLength() == 0 || + optini.sections[app].values.find("FileSearchLikeGame") == optini.sections[app].values.end() || + optini.sections[app].values.find("PreferLocalTheaterFiles") == optini.sections[app].values.end()) + { + opts.bSearchLikeTS = TRUE; + + bOptionsStartup = TRUE; + ShowOptionsDialog(); + bOptionsStartup = FALSE; + + } + else + { + opts.LanguageName = optini.sections[app].values["Language"]; + if (optini.sections[app].values["FileSearchLikeGame"] != "no") + opts.bSearchLikeTS = TRUE; + else opts.bSearchLikeTS = FALSE; + } + opts.bPreferLocalTheaterFiles = optini.sections[app].values.emplace("PreferLocalTheaterFiles", opts.bPreferLocalTheaterFiles ? "1" : "0").first->second == "1"; + + opts.bDoNotLoadAircraftGraphics = optini.sections["Graphics"].values["NoAircraftGraphics"] == "1"; + opts.bDoNotLoadVehicleGraphics = optini.sections["Graphics"].values["NoVehicleGraphics"] == "1"; + opts.bDoNotLoadBuildingGraphics = optini.sections["Graphics"].values["NoBuildingGraphics"] == "1"; + opts.bDoNotLoadInfantryGraphics = optini.sections["Graphics"].values["NoInfantryGraphics"] == "1"; + opts.bDoNotLoadTreeGraphics = optini.sections["Graphics"].values["NoTreeGraphics"] == "1"; + opts.bDoNotLoadSnowGraphics = optini.sections["Graphics"].values["NoSnowGraphics"] == "1"; + opts.bDoNotLoadTemperateGraphics = optini.sections["Graphics"].values["NoTemperateGraphics"] == "1"; + opts.bDoNotLoadBMPs = optini.sections["Graphics"].values["NoBMPs"] == "1"; + opts.bDoNotLoadOverlayGraphics = optini.sections["Graphics"].values["NoOverlayGraphics"] == "1"; + opts.bVSync = optini.sections["Graphics"].values.emplace("VSync", opts.bVSync ? "1" : "0").first->second == "1"; + + opts.bDisableAutoShore = optini.sections["UserInterface"].values["DisableAutoShore"] == "1"; + opts.bDisableAutoLat = optini.sections["UserInterface"].values["DisableAutoLat"] == "1"; + opts.bNoSounds = optini.sections["UserInterface"].values["Sounds"] != "1"; + opts.bDisableSlopeCorrection = optini.sections["UserInterface"].values["DisableSlopeCorrection"] == "1"; + opts.fLoadScreenDelayInSeconds = static_cast(atof(optini.sections["UserInterface"].values.emplace("LoadScreenDelay", std::to_string(opts.fLoadScreenDelayInSeconds).c_str()).first->second)); + opts.bShowStats = optini.sections["UserInterface"].values.emplace("ShowStats", opts.bShowStats ? "1" : "0").first->second == "1"; + opts.bHighResUI = optini.sections["UserInterface"].values.emplace("HighRes", opts.bHighResUI ? "1" : "0").first->second == "1"; + opts.useDefaultMouseCursor = optini.sections["UserInterface"].values.emplace("UseDefaultMouseCursor", opts.useDefaultMouseCursor ? "1" : "0").first->second == "1"; + + opts.fMiniMapScale = static_cast(atof(optini.sections["MiniMap"].values.emplace("Scale", std::to_string(opts.fMiniMapScale).c_str()).first->second)); + + auto defaultViewSteps = CString(Join(",", opts.viewScaleSteps | std::views::transform([](auto v) {return std::to_string(v); })).c_str()); + auto viewScaleStepsRange = SplitParams(optini.sections["UserInterface"].values.emplace("ViewScaleSteps", defaultViewSteps).first->second) | std::views::transform([](auto v) { return static_cast(std::atof(v)); }); + opts.viewScaleSteps.assign(viewScaleStepsRange.begin(), viewScaleStepsRange.end()); + opts.viewScaleUseSteps = optini.sections["UserInterface"].values.emplace("ViewScaleUseSteps", opts.viewScaleUseSteps ? "1" : "0").first->second == "1"; + opts.viewScaleSpeed = static_cast(atof(optini.sections["UserInterface"].values.emplace("ViewScaleSpeed", std::to_string(opts.viewScaleSpeed).c_str()).first->second)); + + // MW 07/19/01 + opts.bShowCells = optini.sections["UserInterface"].values["ShowBuildingCells"] == "1"; + + optini.SaveFile(iniFile); + + // MW 07/20/01: Load file list + int i; + for (i = 0;i < 4;i++) + { + char c[50]; + itoa(i, c, 10); + opts.prev_maps[i] = optini.sections["Files"].values[c]; + } + + if (opts.bDoNotLoadTemperateGraphics && opts.bDoNotLoadSnowGraphics) + { + MessageBox(0, "You have turned off loading of both snow and temperate terrain in 'FinalAlert.ini'. At least one of these must be loaded. The application will now quit.", "Error", 0); + exit(-982); + } + + int EasyView; + if (optini.sections["UserInterface"].FindName("EasyView") < 0) + { + MessageBox(0, GetLanguageStringACP("ExplainEasyView"), GetLanguageStringACP("ExplainEasyViewCap"), 0); + EasyView = 1; + + optini.LoadFile(iniFile); + optini.sections["UserInterface"].values["EasyView"] = "1"; + optini.SaveFile(iniFile); + } + else + { + EasyView = atoi(optini.sections["UserInterface"].values["EasyView"]); + } + if (EasyView != 0) theApp.m_Options.bEasy = TRUE; + + + + + CString cTSPath = theApp.m_Options.TSExe; + auto lastSlash = cTSPath.ReverseFind('\\'); + if (lastSlash >= 0) + cTSPath.SetAt(lastSlash + 1, 0); + strcpy(TSPath, cTSPath); + + // MW 01/23/2013: changed the global CMapData Map to a global CMapData* to get rid of static initialization/shutdown problems + { + std::unique_ptr mapData(new CMapData()); + Map = mapData.get(); + + CLoading loading(NULL); + m_loading = &loading; + + CFinalSunDlg dlg; + m_pMainWnd = &dlg; + + dlg.DoModal(); + } + + // Map and dialog closed, do further work if required + + return FALSE; +} + +void CFinalSunApp::ParseCommandLine() +{ +#ifdef 0 // Removed as it can conflict with Steam game arguments! -LF 23.02.2024 + char data[MAX_PATH + 30]; + + strcpy(data, theApp.m_lpCmdLine); + if (strlen(data) == 0) + { + strcpy(currentMapFile, ""); + return; + } + + strcpy(currentMapFile, data); +#endif +} + +void CFinalSunApp::ShowTipAtStartup(void) +{ + CTipDlg dlg; + if (dlg.m_bStartup) + dlg.DoModal(); + + +} + +void CFinalSunApp::ShowTipOfTheDay(void) +{ + CTipDlg dlg; + dlg.DoModal(); + +} + +int CFinalSunApp::Run() +{ + return CWinApp::Run(); + +} + +BOOL CFinalSunApp::ProcessMessageFilter(int code, LPMSG lpMsg) +{ + if (lpMsg->message == WM_KEYDOWN) + { + /*if(lpMsg->wParam==VK_F1) + { + if(ShellExecute(0, NULL, (CString)AppPath+"/help/index.htm", NULL, NULL, SW_NORMAL)==0) + { + MessageBox(0,(CString)"Could not open manual! Try opening "+(CString)AppPath+(CString)"/help/index.htm manually","Error",0); + } + return TRUE; + }*/ + + // check AD mode + + if (lpMsg->wParam == VK_PRIOR || lpMsg->wParam == VK_NEXT) + { + if (lpMsg->wParam == VK_PRIOR) + { + AD.z_data += 1; + } + if (lpMsg->wParam == VK_NEXT) + { + AD.z_data -= 1; + } + + if (AD.mode == ACTIONMODE_SETTILE || AD.mode == ACTIONMODE_PASTE) + { + CIsoView* v = ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; + CTerrainDlg& tdlg = ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_browser->m_bar; + WORD isox, isoy; + RECT r; + POINT p; + v->GetWindowRect(&r); + GetCursorPos(&p); + isox = p.x - r.left; + isoy = p.y - r.top; + + if (isox > r.right - r.left || isoy > r.bottom - r.top) + { + + } + else + { + LPARAM lParam; + memcpy(&lParam, &isox, 2); + memcpy((BYTE*)&lParam + 2, &isoy, 2); + v->SendMessage(WM_MOUSEMOVE, 0, lParam); + } + + } + } + + + + + + if (AD.mode == ACTIONMODE_SETTILE) + { + CIsoView* v = ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; + CTerrainDlg& tdlg = ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_browser->m_bar; + WORD isox, isoy; + RECT r; + POINT p; + v->GetWindowRect(&r); + GetCursorPos(&p); + isox = p.x - r.left; + isoy = p.y - r.top; + if (isox > r.right - r.left || isoy > r.bottom - r.top) + { + + } + else + { + LPARAM lParam; + memcpy(&lParam, &isox, 2); + memcpy((BYTE*)&lParam + 2, &isoy, 2); + + int searchedTileSet; + int z; + switch (lpMsg->wParam) + { + + case VK_LEFT: + if (AD.type > 0 && (*tiledata)[AD.type].wTileSet == (*tiledata)[AD.type - 1].wTileSet) { AD.type -= 1; AD.z_data = 0; } + v->SendMessage(WM_MOUSEMOVE, 0, lParam); + return 0; + break; + case VK_RIGHT: + if (AD.type < (*tiledata_count) - 1 && (*tiledata)[AD.type].wTileSet == (*tiledata)[AD.type + 1].wTileSet) { AD.type += 1; AD.z_data = 0; } + v->SendMessage(WM_MOUSEMOVE, 0, lParam); + return 0; + break; + case VK_UP: + searchedTileSet = (*tiledata)[AD.type].wTileSet - 1; + case VK_DOWN: + if (lpMsg->wParam == VK_DOWN) + searchedTileSet = (*tiledata)[AD.type].wTileSet + 1; + + if (searchedTileSet >= 0 && searchedTileSet < tilesets_start.size()) + { + int i; + int s = 1; + int start = 0; + int count = tilesets_start.size() - searchedTileSet; + + if (searchedTileSet < (*tiledata)[AD.type].wTileSet) + { + s = -1; + start = 0; + count = searchedTileSet + 1; + } + + + + + for (i = start;i < count;i += 1) + { + if (searchedTileSet + i * s < 0 || searchedTileSet + i * s >= tilesets_start.size()) continue; + + int pos = tilesets_start[searchedTileSet + i * s]; + + + + + int e; + CComboBox* cb = ((CComboBox*)tdlg.GetDlgItem(IDC_TILESET)); + BOOL bFound = FALSE; + for (e = 0;e < cb->GetCount();e++) + { + if (cb->GetItemData(e) == searchedTileSet + i * s) + { + cb->SendMessage(CB_SETCURSEL, e, 0); + bFound = TRUE; + break; + } + } + + if (bFound) + { + AD.type = tilesets_start[searchedTileSet + i * s]; + AD.data = 0; + AD.data2 = 0; + AD.data3 = 0; + AD.data_s = ""; + v->SendMessage(WM_MOUSEMOVE, 0, lParam); + + return 0; + } + + + } + + + return 0; + break; + + + } + + return 0; + break; + + + } + } + + } + + } + + return CWinApp::ProcessMessageFilter(code, lpMsg); +} + +LRESULT CFinalSunApp::ProcessWndProcException(CException* e, const MSG* pMsg) +{ + // TODO: Speziellen Code hier einfĂ¼gen und/oder Basisklasse aufrufen + e->ReportError(MB_YESNO); + + return TRUE; + //return CWinApp::ProcessWndProcException(e, pMsg); +} + +BOOL CFinalSunApp::PreTranslateMessage(MSG* pMsg) +{ + + if (!TranslateAccelerator( + *this->m_pMainWnd, // handle to receiving window + m_hAccel, // handle to active accelerator table + pMsg)) // message data + + return CWinApp::PreTranslateMessage(pMsg); + + return FALSE; +} + + + +BOOL CFinalSunApp::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) +{ + + return CWinApp::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); +} + +BOOL CFinalSunApp::OnIdle(LONG lCount) +{ + ((CFinalSunDlg*)m_pMainWnd)->m_view.m_isoview->UpdateWindow(); + //MessageBox(0,"Idled","",0); + return CWinApp::OnIdle(lCount); +} diff --git a/MissionEditor/FinalSun.h b/MissionEditor/FinalSun.h new file mode 100644 index 0000000..e3dc5c4 --- /dev/null +++ b/MissionEditor/FinalSun.h @@ -0,0 +1,132 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// +// Main header file +// + +#if !defined(AFX_TIBERIANSUNMISSIONEDITOR_H__9F773422_63BB_11D3_99E0_C30F10710B17__INCLUDED_) +#define AFX_TIBERIANSUNMISSIONEDITOR_H__9F773422_63BB_11D3_99E0_C30F10710B17__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols +#include "ddeml.h" +#include "loading.h" + +struct OPTIONS{ + CString TSExe; + CString LanguageName; + CString prev_maps[4]; + bool bPreferLocalTheaterFiles = true; + BOOL bFlat; + BOOL bEasy; + BOOL bMarbleMadness; + BOOL bSupportMarbleMadness; + BOOL bShowCells; + BOOL bDoNotLoadBuildingGraphics; + BOOL bDoNotLoadInfantryGraphics; + BOOL bDoNotLoadAircraftGraphics; + BOOL bDoNotLoadTreeGraphics; + BOOL bDoNotLoadSnowGraphics; + BOOL bDoNotLoadTemperateGraphics; + BOOL bDoNotLoadVehicleGraphics; + BOOL bDoNotLoadBMPs; + BOOL bDoNotLoadOverlayGraphics; + BOOL bDisableAutoShore; + BOOL bDisableAutoLat; + BOOL bNoSounds; + BOOL bDisableSlopeCorrection; + float fMiniMapScale = 2.0f; + float fLoadScreenDelayInSeconds = 3.5f; + bool bShowStats = false; + bool bHighResUI = true; + bool bVSync = false; + std::vector viewScaleSteps = { 0.75f, 0.5f, 0.25f }; + bool viewScaleUseSteps = true; + float viewScaleSpeed = 15.0f; + bool useDefaultMouseCursor = false; + +public: + BOOL bSearchLikeTS; +}; + + +///////////////////////////////////////////////////////////////////////////// +// CFinalSunApp: +// Look at FinalSun.cpp for the implementation of this class +// + +class CFinalSunApp : public CWinApp +{ +public: + DWORD pidInst; + OPTIONS m_Options; + CLoading* m_loading; + CFinalSunApp(); + + const std::string& getLogFileName() const + { + return m_u8LogFileName; + } + + +// Ăœberladungen + // Vom Klassenassistenten generierte Ăœberladungen virtueller Funktionen + //{{AFX_VIRTUAL(CFinalSunApp) + public: + virtual BOOL InitInstance(); + virtual int Run(); + virtual BOOL ProcessMessageFilter(int code, LPMSG lpMsg); + virtual LRESULT ProcessWndProcException(CException* e, const MSG* pMsg); + virtual BOOL PreTranslateMessage(MSG* pMsg); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + virtual BOOL OnIdle(LONG lCount); + //}}AFX_VIRTUAL + +// Implementierung + + //{{AFX_MSG(CFinalSunApp) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + public: + UINT m_cf; + HACCEL m_hAccel; + void ParseCommandLine(); + void ShowTipAtStartup(void); + void ShowTipOfTheDay(void); + +private: + std::string m_u8LogFileName; +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // !defined(AFX_TIBERIANSUNMISSIONEDITOR_H__9F773422_63BB_11D3_99E0_C30F10710B17__INCLUDED_) diff --git a/MissionEditor/FinalSunDlg.cpp b/MissionEditor/FinalSunDlg.cpp new file mode 100644 index 0000000..355c661 --- /dev/null +++ b/MissionEditor/FinalSunDlg.cpp @@ -0,0 +1,4135 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// +// Main dialog implementation +// + +#include "stdafx.h" +#include "structs.h" +#include "FinalSun.h" +#include "FinalSunDlg.h" +#include "tsoptions.h" +#include "info.h" +#include "loading.h" +#include "MapOpenDialog.h" +//#include "NewMap->h" +#include "newmapcreatedlg.h" +#include "newmapcreatenewdlg.h" +#include "newmapimportdlg.h" +#include "newmapspdlg.h" +#include "newmaptypedlg.h" +#include "MapValidator.h" +#include "ShutDownDlg.h" +#include "SavingDlg.h" +#include "functions.h" +#include "mapdata.h" +#include "variables.h" +#include "GlobalsDlg.h" +#include "savemapoptionsdlg.h" +#include "MissionEditorPackLib.h" +#include "bitmap2mapconverter.h" +#include "multisaveoptionsdlg.h" +#include "mmxsavingoptionsdlg.h" +#include +#include "inlines.h" +#include "MapCode.h" +#include "SearchWaypointDlg.h" +#include "userscriptsdlg.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + + +#include +#include +#include +#include +#include + +extern ACTIONDATA AD; +extern BOOL bNoDraw; + +extern char AppPath[MAX_PATH + 1]; +extern const std::string u8AppDataPath; +extern BOOL bMiniMapClosedByUser; + +HCURSOR m_hArrowCursor = NULL; + +static UINT indicators[] = +{ + ID_SEPARATOR, // Sstatus bar + ID_INDICATOR_CAPS, + ID_INDICATOR_NUM, + ID_INDICATOR_SCRL, +}; + + + +#define ID_STATBAR 26111 + +///////////////////////////////////////////////////////////////////////////// +// CFinalSunDlg Dialogfeld + +CFinalSunDlg::CFinalSunDlg(CWnd* pParent /*=NULL*/) + : CDialog(CFinalSunDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CFinalSunDlg) + // HINWEIS: Der Klassenassistent fĂ¼gt hier Member-Initialisierung ein + //}}AFX_DATA_INIT + // Beachten Sie, dass LoadIcon unter Win32 keinen nachfolgenden DestroyIcon-Aufruf benötigt + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); + m_hGameCursor = AfxGetApp()->LoadCursor(MAKEINTRESOURCE(IDC_EDITOR_ARROW)); + m_hArrowCursor = m_hGameCursor; + +} + +void CFinalSunDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CFinalSunDlg) + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CFinalSunDlg, CDialog) + //{{AFX_MSG_MAP(CFinalSunDlg) + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + ON_COMMAND(ID_FILE_QUIT, OnFileQuit) + ON_WM_SYSCOMMAND() + ON_COMMAND(ID_OPTIONS_TIBERIANSUNOPTIONS, OnOptionsTiberiansunoptions) + ON_COMMAND(ID_FILE_OPENMAP, OnFileOpenmap) + ON_COMMAND(ID_FILE_SAVEAS, OnFileSaveas) + ON_COMMAND(ID_OPTIONS_EXPORTRULESINI, OnOptionsExportrulesini) + ON_COMMAND(ID_HELP_INFO, OnHelpInfo) + ON_WM_SHOWWINDOW() + ON_COMMAND(ID_FILE_SAVE, OnFileSave) + ON_WM_MENUSELECT() + ON_COMMAND(ID_FILE_RUNTIBERIANSUN, OnFileRuntiberiansun) + ON_COMMAND(ID_FILE_IMPORTMOD, OnFileImportmod) + ON_COMMAND(ID_DEBUG_EXPORTMAPPACKNOSECTIONS, OnDebugExportmappacknosections) + ON_COMMAND(ID_DEBUG_EXPORTMAPPACK, OnDebugExportmappack) + ON_COMMAND(ID_FILE_NEW, OnFileNew) + ON_COMMAND(ID_HELP_TIPOFTHEDAY, OnHelpTipoftheday) + ON_COMMAND(ID_OPTIONS_SIMPLEVIEW, OnOptionsSimpleview) + ON_COMMAND(ID_OPTIONS_SHOWMINIMAP, OnOptionsShowminimap) + ON_COMMAND(ID_FILE_VALIDATEMAP, OnFileValidatemap) + ON_WM_ENTERIDLE() + ON_COMMAND(ID_EDIT_BASICSETTINGS, OnEditBasicsettings) + ON_COMMAND(ID_EDIT_SINGLEPLAYERSETTINGS, OnEditSingleplayersettings) + ON_WM_SIZING() + ON_WM_SIZE() + ON_COMMAND(ID_EDIT_HOUSES, OnEditHouses) + ON_COMMAND(ID_EDIT_AITRIGGERS, OnEditAitriggers) + ON_COMMAND(ID_EDIT_AITRIGGERENABLING, OnEditAitriggerenabling) + ON_COMMAND(ID_EDIT_INIEDITING, OnEditIniediting) + ON_COMMAND(ID_EDIT_LIGHTING, OnEditLighting) + ON_COMMAND(ID_EDIT_MAP, OnEditMap) + ON_COMMAND(ID_EDIT_SCRIPTS, OnEditScripts) + ON_COMMAND(ID_EDIT_SPECIALFLAGS, OnEditSpecialflags) + ON_COMMAND(ID_EDIT_TAGS, OnEditTags) + ON_COMMAND(ID_EDIT_TASKFORCES, OnEditTaskforces) + ON_COMMAND(ID_EDIT_TEAMS, OnEditTeams) + ON_COMMAND(ID_EDIT_TRIGGERS, OnEditTriggers) + ON_WM_SETFOCUS() + ON_COMMAND(ID_TERRAIN_HEIGHTENGROUND, OnTerrainHeightenground) + ON_COMMAND(ID_TERRAIN_LOWERGROUND, OnTerrainLowerground) + ON_COMMAND(ID_TERRAIN_LOWERTILE, OnTerrainLowertile) + ON_COMMAND(ID_TERRAIN_RAISETILE, OnTerrainRaisetile) + ON_COMMAND(ID_TERRAIN_FLATTEN, OnTerrainFlatten) + ON_COMMAND(ID_TERRAIN_CLOAK, OnTerrainCloak) + ON_COMMAND(ID_TERRAIN_SHOWEVERYTILE, OnTerrainShoweverytile) + ON_COMMAND(ID_TERRAIN_SHOWALLFIELDS, OnTerrainShowallfields) + ON_COMMAND(ID_TERRAIN_HIDEFIELD, OnTerrainHidefield) + ON_COMMAND(ID_EDIT_TRIGGEREDITOR, OnEditTriggereditor) + ON_WM_KEYDOWN() + ON_COMMAND(ID_MAPTOOLS_CHANGEMAPHEIGHT, OnMaptoolsChangemapheight) + ON_COMMAND(ID_EDIT_GLOBALVARIABLES, OnEditGlobalvariables) + ON_COMMAND(ID_EDIT_UNDO, OnEditUndo) + ON_COMMAND(ID_HELP, OnHelpManual) + ON_COMMAND(ID_HELP_SHOWLOGS, &CFinalSunDlg::OnHelpShowlogs) + ON_COMMAND(ID_MAPTOOLS_AUTOLEVEL, OnMaptoolsAutolevel) + ON_UPDATE_COMMAND_UI(ID_EDIT_AITRIGGERENABLING, OnUpdateEditAitriggerenabling) + ON_UPDATE_COMMAND_UI(ID_EDIT_AITRIGGERS, OnUpdateEditAitriggers) + ON_UPDATE_COMMAND_UI(ID_EDIT_BASICSETTINGS, OnUpdateEditBasicsettings) + ON_UPDATE_COMMAND_UI(ID_EDIT_GLOBALVARIABLES, OnUpdateEditGlobalvariables) + ON_UPDATE_COMMAND_UI(ID_EDIT_HOUSES, OnUpdateEditHouses) + ON_UPDATE_COMMAND_UI(ID_EDIT_INIEDITING, OnUpdateEditIniediting) + ON_UPDATE_COMMAND_UI(ID_EDIT_LIGHTING, OnUpdateEditLighting) + ON_UPDATE_COMMAND_UI(ID_EDIT_MAP, OnUpdateEditMap) + ON_UPDATE_COMMAND_UI(ID_EDIT_SCRIPTS, OnUpdateEditScripts) + ON_UPDATE_COMMAND_UI(ID_EDIT_SINGLEPLAYERSETTINGS, OnUpdateEditSingleplayersettings) + ON_UPDATE_COMMAND_UI(ID_EDIT_SPECIALFLAGS, OnUpdateEditSpecialflags) + ON_UPDATE_COMMAND_UI(ID_EDIT_TAGS, OnUpdateEditTags) + ON_UPDATE_COMMAND_UI(ID_EDIT_TASKFORCES, OnUpdateEditTaskforces) + ON_UPDATE_COMMAND_UI(ID_EDIT_TEAMS, OnUpdateEditTeams) + ON_UPDATE_COMMAND_UI(ID_EDIT_TRIGGEREDITOR, OnUpdateEditTriggereditor) + ON_UPDATE_COMMAND_UI(ID_EDIT_TRIGGERS, OnUpdateEditTriggers) + ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo) + ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave) + ON_UPDATE_COMMAND_UI(ID_FILE_SAVEAS, OnUpdateFileSaveas) + ON_UPDATE_COMMAND_UI(ID_FILE_VALIDATEMAP, OnUpdateFileValidatemap) + ON_UPDATE_COMMAND_UI(ID_MAPTOOLS_AUTOLEVEL, OnUpdateMaptoolsAutolevel) + ON_UPDATE_COMMAND_UI(ID_MAPTOOLS_CHANGEMAPHEIGHT, OnUpdateMaptoolsChangemapheight) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_SHOWMINIMAP, OnUpdateOptionsShowminimap) + ON_UPDATE_COMMAND_UI(ID_TERRAIN_CLOAK, OnUpdateTerrainCloak) + ON_UPDATE_COMMAND_UI(ID_TERRAIN_FLATTEN, OnUpdateTerrainFlatten) + ON_UPDATE_COMMAND_UI(ID_TERRAIN_HEIGHTENGROUND, OnUpdateTerrainHeightenground) + ON_UPDATE_COMMAND_UI(ID_TERRAIN_HIDEFIELD, OnUpdateTerrainHidefield) + ON_UPDATE_COMMAND_UI(ID_TERRAIN_LOWERGROUND, OnUpdateTerrainLowerground) + ON_UPDATE_COMMAND_UI(ID_TERRAIN_LOWERTILE, OnUpdateTerrainLowertile) + ON_UPDATE_COMMAND_UI(ID_TERRAIN_RAISETILE, OnUpdateTerrainRaisetile) + ON_UPDATE_COMMAND_UI(ID_TERRAIN_SHOWALLFIELDS, OnUpdateTerrainShowallfields) + ON_UPDATE_COMMAND_UI(ID_TERRAIN_SHOWEVERYTILE, OnUpdateTerrainShoweverytile) + ON_COMMAND(ID_MAPTOOLS_FRONTCLIFF, OnMaptoolsFrontcliff) + ON_COMMAND(ID_MAPTOOLS_BACKCLIFF, OnMaptoolsBackcliff) + ON_COMMAND(ID_EDIT_REDO, OnEditRedo) + ON_COMMAND(ID_MAPTOOLS_AUTOCREATESHORES, OnMaptoolsAutocreateshores) + ON_COMMAND(ID_OPTIONS_DISABLEAUTOSHORE, OnOptionsDisableautoshore) + ON_COMMAND(ID_OPTIONS_DISABLEAUTOLAT, OnOptionsDisableautolat) + ON_COMMAND(ID_EDIT_PASTE, OnEditPaste) + ON_COMMAND(ID_EDIT_COPY, OnEditCopy) + ON_COMMAND(ID_EDIT_COPYWHOLEMAP, OnEditCopywholemap) + ON_COMMAND(ID_EDIT_PASTEWHOLEMAP, OnEditPastewholemap) + ON_COMMAND(ID_MARBLEMADNESS, OnMarblemadness) + ON_COMMAND(ID_OPTIONS_SOUNDS, OnOptionsSounds) + ON_UPDATE_COMMAND_UI(ID_OPTIONS_SOUNDS, OnUpdateOptionsSounds) + ON_COMMAND(ID_OPTIONS_DISABLESLOPECORRECTION, OnOptionsDisableslopecorrection) + ON_COMMAND(ID_OPTIONS_SHOWBUILDINGOUTLINE, OnOptionsShowbuildingoutline) + ON_COMMAND(ID_FILE_FILE1, OnFileFile1) + ON_COMMAND(ID_FILE_FILE2, OnFileFile2) + ON_COMMAND(ID_FILE_FILE3, OnFileFile3) + ON_COMMAND(ID_FILE_FILE4, OnFileFile4) + ON_COMMAND(ID_MAPTOOLS_SEARCHWAYPOINT, OnMaptoolsSearchwaypoint) + ON_COMMAND(ID_MAPTOOLS_TOOLSCRIPTS, OnMaptoolsToolscripts) + //}}AFX_MSG_MAP + ON_COMMAND(ID_OPTIONS_SMOOTHZOOM, &CFinalSunDlg::OnOptionsSmoothzoom) + ON_WM_SETCURSOR() + ON_COMMAND(ID_OPTIONS_USEDEFAULTMOUSECURSOR, &CFinalSunDlg::OnOptionsUsedefaultmousecursor) + END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CFinalSunDlg message handler + +BOOL CFinalSunDlg::OnInitDialog() +{ + + CDialog::OnInitDialog(); + + m_hArrowCursor = theApp.m_Options.useDefaultMouseCursor ? LoadCursor(NULL, IDC_ARROW) : m_hGameCursor; + + errstream << "CFinalSunDlg::OnInitDialog() called" << endl; + errstream.flush(); + + ShowWindow(SW_HIDE); + SetWindowPos(NULL, 0, 0, GetSystemMetrics(SM_CXFULLSCREEN), GetSystemMetrics(SM_CYFULLSCREEN), 0); + + SetIcon(m_hIcon, TRUE); // use big symbol + SetIcon(m_hIcon, FALSE); // use small symbol + + CString cap; +#ifndef RA2_MODE + cap= GetLanguageStringACP("MainDialogCaption"); +#else + cap=GetLanguageStringACP("MainDialogCaptionRA2"); +#endif + + cap+=" ("; + cap+=GetLanguageStringACP("NoMapLoaded"); + cap+=")"; + SetWindowText(cap); + + + // Matze: + // July 9th: + // Added toolbars + + BOOL success=true; + RECT r; + SIZE size_mainbar; + SIZE size_terrainbar; + GetClientRect(&r); + r.top+=32; + success = success && m_view.Create(NULL, GetLanguageStringACP("IsoCaption"), WS_CHILD, r, this); + + r.top=0; + r.bottom=32; + success = success && m_bar.Create(RBS_AUTOSIZE, r, this, 5000); + success = success && m_maintoolbar.Create(this); + success = success && m_maintoolbar.LoadToolBar(IDR_MAINFRAME); + m_maintoolbar.GetToolBarCtrl().SetStyle(m_maintoolbar.GetToolBarCtrl().GetStyle() | TBSTYLE_FLAT | TBSTYLE_TRANSPARENT | TBSTYLE_TOOLTIPS); + success = success && m_maintoolbar.GetToolBarCtrl().GetMaxSize(&size_mainbar); + success = success && m_terraintoolbar.Create(this); + success = success && m_terraintoolbar.LoadToolBar(IDR_TERRAINBAR); + m_terraintoolbar.GetToolBarCtrl().SetStyle(m_terraintoolbar.GetToolBarCtrl().GetStyle() | TBSTYLE_FLAT | TBSTYLE_TRANSPARENT | TBSTYLE_TOOLTIPS ); + success = success && m_terraintoolbar.GetToolBarCtrl().GetMaxSize(&size_terrainbar); + m_terraintoolbar.SetBarStyle(m_terraintoolbar.GetBarStyle()); + success = success && m_clifftoolbar.Create(this); + success = success && m_clifftoolbar.LoadToolBar(IDR_CLIFFBAR); + m_clifftoolbar.GetToolBarCtrl().SetStyle(m_clifftoolbar.GetToolBarCtrl().GetStyle() | TBSTYLE_FLAT | TBSTYLE_TRANSPARENT | TBSTYLE_TOOLTIPS ); + m_clifftoolbar.SetBarStyle(m_terraintoolbar.GetBarStyle()); + + success = success && m_settingsbar.Create(this, IDD_TOOLSETTINGS, CBRS_TOP, 6000); + + REBARBANDINFO rbi = { 0 }; + rbi.cbSize= sizeof(REBARBANDINFO); + rbi.fMask= RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_TEXT /*| RBBIM_SIZE*/ | RBBIM_IDEALSIZE; + rbi.fStyle= RBBS_GRIPPERALWAYS; + rbi.cxMinChild= size_mainbar.cx+30; + rbi.cyMinChild= 30; + rbi.cch= 0; + rbi.cx= size_mainbar.cx+30; + rbi.cxIdeal=size_mainbar.cx+30; + rbi.hbmBack= NULL; + rbi.hwndChild= (HWND)m_maintoolbar; + success = success && m_bar.InsertBand(0, &rbi); + rbi.hwndChild= (HWND)m_terraintoolbar; + rbi.cx=size_terrainbar.cx+30; + rbi.cxIdeal=size_terrainbar.cx+30; + rbi.cxMinChild= size_terrainbar.cx+30; + success = success && m_bar.InsertBand(1, &rbi); + rbi.hwndChild = (HWND)m_clifftoolbar; + rbi.cx = 560; + rbi.cxMinChild = 170; + rbi.cxIdeal = 560; + success = success && m_bar.InsertBand(2, &rbi); + rbi.hwndChild= (HWND)m_settingsbar; + rbi.cxMinChild= 170; + rbi.cx=170; + rbi.cxIdeal=170; + success = success && m_bar.InsertBand(3, &rbi); + + + m_bar.ShowWindow(SW_SHOW); + m_maintoolbar.ShowWindow(SW_SHOW); + m_terraintoolbar.ShowWindow(SW_SHOW); + m_settingsbar.ShowWindow(SW_SHOW); + + m_bar.MinimizeBand(0); + m_bar.MaximizeBand(3); + + + + if(!success) + { + // sometimes, insufficient resources are available. + // this is a very rare case - but it happened on Win9x + // especially when running the developer studio and IE5, this happens often + // 04/02/2000: Should not anymore occur. + MessageBox(GetLanguageStringACP("Err_InsufficientResources")); + exit(-5); + } + + + errstream << "Updating menu" << endl; + errstream.flush(); + + if(theApp.m_Options.bEasy && GetMenu()) GetMenu()->CheckMenuItem(ID_OPTIONS_SIMPLEVIEW, MF_BYCOMMAND | MF_CHECKED); + + UpdateStrings(); + + + + + // Matze: + // June 21, CLoading now non-modal. + // CLoading will free itself + // September 6th, CLoading will not free itself as it is a member of CFinalSunApp + if(theApp.m_loading->m_hWnd ==NULL) + { + MessageBox("Loading dialog could not be created. Please close any programs and start again."); + exit(-99); + } + theApp.m_loading->ShowWindow(SW_SHOW); + theApp.m_loading->UpdateWindow(); + theApp.m_loading->Load(); + + if(!theApp.m_Options.bSupportMarbleMadness) + { + TBBUTTON b; + m_terraintoolbar.GetToolBarCtrl().GetButton(9, &b); + + m_terraintoolbar.GetToolBarCtrl().HideButton(b.idCommand); + m_terraintoolbar.GetToolBarCtrl().HideButton(ID_MARBLEMADNESS); + } + + ShowWindow(SW_SHOWMAXIMIZED); + CDialog::BringWindowToTop(); + + if(strlen(currentMapFile)==0) // no map file specified + { + // ok, let the user choose a map! + // hmm... no, don´t let him. we already have our tips dialog. + // OnFileOpenmap(); + + theApp.ShowTipAtStartup(); + } + else // yah, map file specified + { + CString str = GetLanguageStringACP("MainDialogCaption"); + str+=" ("; + str+=currentMapFile; + str+=")"; + + this->SetWindowText(str); + SetCursor(LoadCursor(NULL, IDC_WAIT)); + + Map->LoadMap(currentMapFile); + + SetCursor(m_hArrowCursor); + + } + + UpdateDialogs(); + +#ifndef RA2_MODE + CTime t=t.GetCurrentTime(); + + if(t.GetDay()>=24 && t.GetDay()<=26 && t.GetMonth()==12) + { + CString str; + GetWindowText(str); + + SetWindowText(str+" Merry Christmas! Fröhliche Weihnachten!"); + + } +#endif + + + return TRUE; +} + +void CFinalSunDlg::OnPaint() +{ + + if (IsIconic()) + { + CPaintDC dc(this); // DC for painting + + SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); + + // center symbol + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // draw symbol + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CDialog::OnPaint(); + } + + +} + +HCURSOR CFinalSunDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + +void CFinalSunDlg::OnFileQuit() +{ + UnloadAll(); +} + + +void CFinalSunDlg::OnSysCommand(UINT nID, LPARAM lParam) +{ + if(nID==SC_CLOSE) + { + UnloadAll(); + return; + } + CDialog::OnSysCommand(nID, lParam); +} + + + +void CFinalSunDlg::OnOK() +{ + //just do nothing... + // this is a stub +} + +void CFinalSunDlg::OnCancel() +{ + //do nothing... + // stub +} + +void CFinalSunDlg::OnOptionsTiberiansunoptions() +{ + + ShowOptionsDialog(); + +} + +void CFinalSunDlg::OnFileOpenmap() +{ + + //CMapOpenDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_FILEMUSTEXIST, "TS maps|*.mpr;*.map|TS multi maps|*.mpr|TS single maps|*.map|"); + CString r=GetLanguageStringACP("SAVEDLG_FILETYPES"); + if(yuri_mode) + { + r=GetLanguageStringACP("SAVEDLG_FILETYPES_YR"); + } + r=TranslateStringVariables(8, r, ";"); + + if(!yuri_mode) r.Replace(".yrm",".mpr"); + + CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_FILEMUSTEXIST, r); + + char cuPath[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, cuPath); + dlg.m_ofn.lpstrInitialDir=cuPath; + + if(theApp.m_Options.TSExe.GetLength()) dlg.m_ofn.lpstrInitialDir=(char*)(LPCTSTR)theApp.m_Options.TSExe; + + + if(dlg.DoModal()==IDCANCEL) return; + + m_PKTHeader.Clear(); + + CString fileToOpen=dlg.GetPathName(); + fileToOpen.MakeLower(); + CString ext=dlg.GetFileExt(); + ext.MakeLower(); + BOOL bLoadedFromMMX=FALSE; + if(ext=="mmx") + { + HMIXFILE hMix=FSunPackLib::XCC_OpenMix(fileToOpen, NULL); + fileToOpen.Replace(".mmx", ".map"); + + if(fileToOpen.ReverseFind('\\')>=0) fileToOpen=fileToOpen.Right(fileToOpen.GetLength()-fileToOpen.ReverseFind('\\')-1); + + CString extractFile=u8AppDataPath.c_str(); + CString pktFile=fileToOpen; + pktFile.Replace(".map", ".pkt"); + extractFile+="\\mmx_tmp.pkt"; + + FSunPackLib::XCC_ExtractFile(pktFile, extractFile, hMix); + m_PKTHeader.LoadFile(extractFile, TRUE); + fileToOpen=m_PKTHeader.sections["MultiMaps"].values["1"]+".map"; + + + + extractFile=u8AppDataPath.c_str(); + extractFile+="\\mmx_tmp.map"; + FSunPackLib::XCC_ExtractFile(fileToOpen, extractFile, hMix); + fileToOpen=extractFile; + + + + FSunPackLib::XCC_CloseMix(hMix); + bLoadedFromMMX=TRUE; + } + + CIniFile f; + f.InsertFile(fileToOpen, "Map"); + if((f.sections["Map"].values["Theater"]==THEATER0 && theApp.m_Options.bDoNotLoadTemperateGraphics) || (f.sections["Map"].values["Theater"]==THEATER1 && theApp.m_Options.bDoNotLoadSnowGraphics)) + { + MessageBox("You have selected to don´t show temperate or snow theater, but this map uses this theater. You cannot load it without restarting FinalSun/FinalAlert 2 with this theater enabled.", "Error"); + return; + } + + bNoDraw=TRUE; + + CString str; + str = GetLanguageStringACP("MainDialogCaption"); + str+=" ("; + str+=(char*)(LPCTSTR)dlg.GetPathName(); + str+=")"; + + // MW 07/20/01: Update prev. files + InsertPrevFile(dlg.GetPathName()); + + this->SetWindowText(str); + + SetCursor(LoadCursor(NULL, IDC_WAIT)); + + errstream << "Map->LoadMap() will be called" << endl; + errstream.flush(); + + + + Map->LoadMap((char*)(LPCTSTR)fileToOpen); + + + BOOL bNoMapFile=FALSE; + if(!Map->CheckMapPackData()) + { + int res=MessageBox("This map seems to be corrupt. Do you want to try repairing it? If you click cancel, a empty map will be created, if you click no, it will load the map as it is","Corrupt", MB_YESNOCANCEL); + if(res==IDCANCEL) + { + Map->CreateMap(32,32,THEATER0,0); + bNoMapFile=TRUE; + } + else + { + if(res==IDYES) // try repair + { + int fielddata_size=Map->GetIsoSize()*Map->GetIsoSize(); + + int i; + for(i=0;iGetFielddataAt(i)->wGround; + if(gr==0xFFFF) gr=0; + + if(gr>=(*tiledata_count)) + { + Map->SetTileAt(i, 0, 0); + } + else + { + if((*tiledata)[gr].wTileCount<=Map->GetFielddataAt(i)->bSubTile) + { + Map->SetTileAt(i, 0, 0); + } + } + } + + } + } + } + + if(!bNoMapFile) + { + if(bLoadedFromMMX) + { + //currentMapFile[0]=0; + strcpy(currentMapFile, dlg.GetPathName()); + } + else + strcpy(currentMapFile, fileToOpen); + } + + Sleep(200); + + SetCursor(m_hArrowCursor); + + + bNoDraw=FALSE; + + m_view.m_isoview->UpdateDialog(TRUE); + UpdateDialogs(); +} + +void CFinalSunDlg::UpdateDialogs(BOOL bOnlyMissionControl, BOOL bNoRepos) +{ + RepairRulesHouses(); + + OutputDebugString("Dialogs updated\n"); + + if(m_basic.m_hWnd) m_basic.UpdateDialog(); + if(m_all.m_hWnd) m_all.UpdateDialog(); + if(m_map.m_hWnd) m_map.UpdateDialog(); + if(m_lighting.m_hWnd) m_lighting.UpdateDialog(); + if(m_specialflags.m_hWnd) m_specialflags.UpdateDialog(); + if(m_teamtypes.m_hWnd) m_teamtypes.UpdateDialog(); + if(m_houses.m_hWnd) m_houses.UpdateDialog(); + if(m_taskforces.m_hWnd) m_taskforces.UpdateDialog(); + if(m_Scripttypes.m_hWnd) m_Scripttypes.UpdateDialog(); + if(m_triggers.m_hWnd) m_triggers.UpdateDialog(); + if(m_triggereditor.m_hWnd) m_triggereditor.UpdateDialog(); + if(m_tags.m_hWnd) m_tags.UpdateDialog(); + if(m_aitriggertypesenable.m_hWnd) m_aitriggertypesenable.UpdateDialog(); + if(m_aitriggertypes.m_hWnd) m_aitriggertypes.UpdateDialog(); + if(m_singleplayersettings.m_hWnd) m_singleplayersettings.UpdateDialog(); + + CIniFile& ini=Map->GetIniFile(); + if(ini.sections.find(MAPHOUSES)!=ini.sections.end() && ini.sections[MAPHOUSES].values.size()>0) + { + if(ini.sections[MAPHOUSES].FindValue("Neutral")>=0) + currentOwner="Neutral"; + else + currentOwner=*ini.sections[MAPHOUSES].GetValue(0); + } + else + currentOwner="Neutral";//*rules.sections[HOUSES].GetValue(0); + + if(!bOnlyMissionControl) + { + UpdateWindow(); + UpdateStrings(); + + + + m_view.m_isoview->UpdateDialog(!bNoRepos); + m_view.m_objectview->UpdateDialog(); + m_view.m_minimap.UpdateView(); + + if(tiles!=NULL && tiledata!=NULL && tiledata_count!=NULL) + m_view.m_browser->m_bar.Update(); + } + + AD.reset(); +} + +void CFinalSunDlg::OnFileSaveas() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + + CMapValidator validator; + int iCancel=validator.DoModal(); + if(iCancel==IDCANCEL) return; + CString r=GetLanguageStringACP("SAVEDLG_FILETYPES"); + if(yuri_mode) + { + r=GetLanguageStringACP("SAVEDLG_FILETYPES_YR"); + } + r=TranslateStringVariables(8, r, ";"); + + CString ext, fname; + if(Map->IsMultiplayer()) + { + ext=".mpr"; + fname="noname.mpr"; + + // MW 07/27/01: YRM support + //if(Map->IsYRMap()) + // MW Fix: Usually always YRM in Yuri Mode, + // because YR does NOT read MPR + if(yuri_mode) + { + ext=".yrm"; + fname="noname.yrm"; + } + } + else{ + ext=".map"; + fname="noname.map"; + } + + CFileDialog dlg(FALSE, ext, /*fname*/ NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, r); + char cuPath[MAX_PATH]; + + GetCurrentDirectory(MAX_PATH, cuPath); + dlg.m_ofn.lpstrInitialDir=cuPath; + + + + if(theApp.m_Options.TSExe.GetLength()) dlg.m_ofn.lpstrInitialDir=(char*)(LPCTSTR)theApp.m_Options.TSExe; + + if(dlg.DoModal()!=IDCANCEL) + { + strcpy(currentMapFile, dlg.GetPathName()); + + CString str=GetLanguageStringACP("MainDialogCaption"); + str+=" ("; + str+=(char*)(LPCTSTR)dlg.GetPathName(); + str+=")"; + + this->SetWindowText(str); + + SaveMap(dlg.GetPathName()); + } + + + + SetCursor(m_hArrowCursor); + +} + +void CFinalSunDlg::OnOptionsExportrulesini() +{ + int res=MessageBox("This will export the Rules.Ini of Tiberian Sun V1.13 MMX. ou should not modify this rules.ini because you won´t be able to play online then and ecause this could cause compatibility problems.\nIf you want to modify the rules.ini, you need to rename it before you play online.", "Export Rules.INI", MB_OK); + + CFileDialog dlg(FALSE, ".ini", "rules.ini", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Rules.INI|rules.ini|"); + + char cuPath[MAX_PATH]; + BOOL hidePreview=FALSE; + BOOL previewPrinted=FALSE; + GetCurrentDirectory(MAX_PATH, cuPath); + dlg.m_ofn.lpstrInitialDir=cuPath; + + if(theApp.m_Options.TSExe.GetLength()) dlg.m_ofn.lpstrInitialDir=(char*)(LPCTSTR)theApp.m_Options.TSExe; + + if(dlg.DoModal()!=IDCANCEL) + { + SetCursor(LoadCursor(NULL, IDC_WAIT)); + + HRSRC r; + r=FindResource(NULL, MAKEINTRESOURCE(IDR_RULES) ,"TEXTFILE"); + + if(r==0) {MessageBox("FindResource() failed to find IDR_RULES", "DEBUG");return;} + + HGLOBAL hres=LoadResource(NULL, r); + + if(hres==0) {MessageBox("LoadResource() failed to load IDR_RULES", "DEBUG");return;} + + char* data=(char*)LockResource(hres); + + int hfile=_open((char*)(LPCTSTR)dlg.GetPathName(),_O_BINARY | _O_CREAT | _O_WRONLY, _S_IREAD | _S_IWRITE); + + if(hfile==-1) { MessageBox("File could not be opened","DEBUG"); return; } + + _write(hfile, (void*) data, strlen(data)); + + _close(hfile); + + SetCursor(m_hArrowCursor); + + } +} + +void CFinalSunDlg::OnHelpInfo() +{ + // handle the help dialog + CInfo info; + info.DoModal(); +} + + +void CFinalSunDlg::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialog::OnShowWindow(bShow, nStatus); + + m_view.ShowWindow(SW_SHOW); + + if(!bShow) return; + + + +} + + + + +void CFinalSunDlg::OnFileSave() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + + if(strlen(currentMapFile)==0) { OnFileSaveas(); return; } + + CMapValidator validator; + int iCancel=validator.DoModal(); + if(iCancel==IDCANCEL) return; + + SaveMap(currentMapFile); +} + + + + +void CFinalSunDlg::SaveMap(CString FileName_) +{ + SetCursor(LoadCursor(NULL, IDC_WAIT)); + + errstream << "SaveMap() called" << endl; + errstream.flush(); + + BOOL bSaveAsMMX=FALSE; + BOOL hidePreview=FALSE; + BOOL previewPrinted=FALSE; + + + + FileName_.MakeLower(); + FileName_=(LPCSTR)FileName_; // GetLength() needs to return proper size + + + CString CoreName=FileName_; + CString Description; + int minplayers; + int maxplayers; + BOOL standard; + BOOL meatgrind; + BOOL navalwar; + BOOL nukewar; + BOOL airwar; + BOOL megawealth; + BOOL duel; + BOOL cooperative; + // MW Apr 17th, 2002: Added Teamgame! + BOOL teamgame; + + if(CoreName.ReverseFind('\\')>=0) CoreName=CoreName.Right(CoreName.GetLength()-CoreName.ReverseFind('\\')-1); + if(CoreName.Find(".")>=0) CoreName=CoreName.Left(CoreName.Find(".")); + + + + +#ifdef RA2_MODE + if(Map->IsMultiplayer()) + { + if(FileName_.Find(".mmx")>=0) bSaveAsMMX=TRUE; else bSaveAsMMX=FALSE; + if(FileName_.Find(".map")>=0) FileName_.Replace(".map",".mpr"); + + // MW 07/27/01: Check for YRM + if(FileName_.Find(".mpr")>=0 && Map->IsYRMap()) FileName_.Replace(".mpr",".yrm"); + + + // MW 07/28/01: Create [Header] + int i; + int wp_count=0; + int xw[8]={0,0,0,0,0,0,0,0}; + int yw[8]={0,0,0,0,0,0,0,0}; + for(i=0;iGetWaypointCount();i++) + { + CString id; + DWORD pos; + Map->GetWaypointData(i, &id, &pos); + int idi; + idi=atoi(id); + if(idi!=i) break; + if(idi>=0 && idi<8) + { + int x,y; + x=pos/Map->GetIsoSize(); + y=pos%Map->GetIsoSize(); + //PosToXY(pos, x,y); + xw[wp_count]=calcXPos(x,y); + yw[wp_count]=calcYPos(x,y); + wp_count++; + } + + } + char c[50]; + CIniFile& ini=Map->GetIniFile(); + CIniFileSection& sec=ini.sections["Header"]; + itoa(wp_count, c, 10); + sec.values["NumberStartingPoints"]=c; + for(i=0;i<8;i++) + { + CString s="Waypoint"; + itoa(i+1, c, 10); + s+=c; + itoa(xw[i], c, 10); + CString val=c; + val+=","; + itoa(yw[i], c, 10); + val+=c; + sec.values[s]=val; + } + + int startx, starty, width, height; + MC_GetHeaderRect(startx, starty, width, height); + + itoa(height, c, 10); + sec.values["Height"]=c; + itoa(width, c, 10); + sec.values["Width"]=c; + + //CIniFile& ini=Map->GetIniFile(); + + CString left=GetParam(ini.sections["Map"].values["LocalSize"], 0); + CString top=GetParam(ini.sections["Map"].values["LocalSize"], 1); + + //startx=1;//Map->GetHeight()/2;//atoi(left);//Map->GetIsoSize()/2-Map->GetWidth()/2;//198/2-50;//Map->GetIsoSize()/2-Map->GetHeight()/2;//Map->GetWidth()/2-50; + //starty=Map->GetWidth();//Map->GetIsoSize()/2-Map->GetWidth()/2;//198/2-50;//Map->GetIsoSize()/2-Map->GetWidth()/2;//Map->GetHeight()/2-50; + itoa(startx, c, 10); + sec.values["StartX"]=c; + itoa(starty, c, 10); + sec.values["StartY"]=c; + + /*CMultiSaveOptionsDlg mso; + + if(FileName.Find(".mmx")>=0) mso.m_mmx=0; else mso.m_mmx=1; + + if(mso.DoModal()==IDCANCEL) return; + + if(mso.m_mmx==0) + { + FileName.Replace(".mpr", ".map"); + //FileName.Replace(" ", ""); + if(CoreName.GetLength()>8) + { + CoreName=CoreName.Left(8); + FileName=CoreName+".map"; + + CString s="The maximum filename length for MMX files is 8 chars, do you want to save the map as "; + s+=CoreName; + s+=".mmx?"; + int res=MessageBox(s,"Error", MB_YESNO); + if(res!=IDYES) return; + } + + bSaveAsMMX=TRUE; + + } + else + { + FileName.Replace(".mmx", ".mpr"); + bSaveAsMMX=FALSE; + }*/ + } +#endif + + CString MMXFileName=CoreName; + MMXFileName+=".mmx"; + + CString PKTFileName=CoreName; + PKTFileName+=".pkt"; + + CString MAPFileName=CoreName; + MAPFileName+=".map"; + + DWORD dwFlags=MAPDATA_UPDATE_TO_INI_ALL; + + if(!bSaveAsMMX) + { + CSaveMapOptionsDlg opt; + + + CString gm=Map->GetIniFile().sections["Basic"].values["GameMode"]; + gm.MakeLower(); + if(gm.GetLength()) + { + opt.m_Standard=gm.Find("standard")>=0; + opt.m_AirWar=gm.Find("airwar")>=0; + opt.m_Cooperative=gm.Find("cooperative")>=0; + opt.m_Duel=gm.Find("duel")>=0; + opt.m_Navalwar=gm.Find("navalwar")>=0; + opt.m_Nukewar=gm.Find("nukewar")>=0; + opt.m_Meatgrind=gm.Find("meatgrind")>=0; + opt.m_Megawealth=gm.Find("megawealth")>=0; + opt.m_TeamGame=gm.Find("teamgame")>=0; + } + else + opt.m_Standard=TRUE; + + + if(opt.DoModal()==IDCANCEL) return; + + gm=""; + if(opt.m_Standard) gm+="standard, "; + if(opt.m_Meatgrind) gm+="meatgrind, "; + if(opt.m_Navalwar) gm+="navalwar, "; + if(opt.m_Nukewar) gm+="nukewar, "; + if(opt.m_AirWar) gm+="airwar, "; + if(opt.m_Megawealth) gm+="megawealth, "; + if(opt.m_Duel) gm+="duel, "; + if(opt.m_Cooperative) gm+="cooperative, "; + if(opt.m_TeamGame) gm+="teamgame, "; + + if(gm.ReverseFind(',')>=0) gm=gm.Left(gm.ReverseFind(',')); + + if(gm.GetLength()==0) gm="standard"; + + + Map->GetIniFile().sections["Basic"].values["Name"]=opt.m_MapName; + Map->GetIniFile().sections["Basic"].values["GameMode"]=gm; + + int i; + int count=0; + for(i=0;iGetWaypointCount();i++) + { + CString id; + DWORD pos; + Map->GetWaypointData(i, &id, &pos); + int idi; + idi=atoi(id); + if(idi!=i) break; + if(idi>=0 && idi<8) count++; + } + + if(count<2) count=2; + + Map->GetIniFile().sections["Basic"].values["MinPlayer"]="2"; + char c[50]; + itoa(count, c, 10); + Map->GetIniFile().sections["Basic"].values["MaxPlayer"]=c; + + if(opt.m_Compress==0) dwFlags|=MAPDATA_UPDATE_TO_INI_ALL_COMPRESSED; + if(opt.m_PreviewMode==0) dwFlags|=MAPDATA_UPDATE_TO_INI_ALL_PREVIEW; + if(opt.m_PreviewMode==2) hidePreview=TRUE; + } + else + { + CMMXSavingOptionsDlg opt; + + if(m_PKTHeader.sections.size()>0) // old pkt header exists + { + CIniFileSection& sec=m_PKTHeader.sections[m_PKTHeader.sections["MultiMaps"].values["1"]]; + if(sec.values["Description"].GetLength()>0) opt.m_Description=sec.values["Description"]; + opt.m_MinPlayers=atoi(sec.values["MinPlayers"])-2; + opt.m_Maxplayers=atoi(sec.values["MaxPlayers"])-2; + CString gm=sec.values["GameMode"]; + gm.MakeLower(); + opt.m_Standard=gm.Find("standard")>=0; + opt.m_AirWar=gm.Find("airwar")>=0; + opt.m_Cooperative=gm.Find("cooperative")>=0; + opt.m_Duel=gm.Find("duel")>=0; + opt.m_NavalWar=gm.Find("navalwar")>=0; + opt.m_NukeWar=gm.Find("nukewar")>=0; + opt.m_Meatgrind=gm.Find("meatgrind")>=0; + opt.m_MegaWealth=gm.Find("megawealth")>=0; + } + + if(opt.DoModal()==IDCANCEL) return; + + Description=opt.m_Description; + standard=opt.m_Standard; + airwar=opt.m_AirWar; + cooperative=opt.m_Cooperative; + duel=opt.m_Duel; + navalwar=opt.m_NavalWar; + nukewar=opt.m_NukeWar; + meatgrind=opt.m_Meatgrind; + megawealth=opt.m_MegaWealth; + + maxplayers=opt.m_Maxplayers+2; + minplayers=opt.m_MinPlayers+2; + + dwFlags|=MAPDATA_UPDATE_TO_INI_ALL_PREVIEW; + + Map->GetIniFile().sections["Basic"].values["Official"]="Yes"; + + // Map->GetIniFile().sections["Basic"].values["Name"]=opt.m_Description; + } + + SetText("Packing data..."); + UpdateWindow(); + errstream << "Calling UpdateIniFile()"<UpdateIniFile(dwFlags); + + + + CIniFile& ini=Map->GetIniFile(); + + + int i; + + for(i=0;ivalues.size()==0 || ini.GetSectionName(i)->GetLength()==0) + { + ini.sections.erase(*ini.GetSectionName(i)); + } + } + + for(i=0;iTrimLeft(); + { + CString value=*sec.GetValue(e); + CString name=*sec.GetValueName(e); + + sec.values.erase(name); + name.TrimLeft(); + sec.values[name]=value; + } + } + } + + for(i=0;iTrimRight(); + { + CString value=*sec.GetValue(e); + CString name=*sec.GetValueName(e); + + sec.values.erase(name); + name.TrimRight(); + sec.values[name]=value; + } + } + } + + + + SetText("Saving..."); + UpdateWindow(); + + + + + std::wstring FileName = utf8ToUtf16(FileName_.GetString()); + + map rulessections; + + std::string tempfile=u8AppDataPath; + tempfile+="\\TmpMap.map"; + std::wstring u16tempfile = utf8ToUtf16(tempfile); + + CString fi; + + deleteFile(tempfile); + HANDLE hFile=CreateFileW(u16tempfile.c_str(), GENERIC_WRITE, 0, NULL, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + CloseHandle(hFile); + hFile=CreateFileW(u16tempfile.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + + + DWORD bwr; + +#ifdef TS_MODE + fi= "; Map created with FinalSun Mission Editor"; + fi+="\n"; + fi+= "; note that all comments were truncated" ; + fi+= "\n"; + fi+="\n"; +#else + fi= "; Map created with FinalAlert 2 Mission Editor"; + fi+="\n"; + fi+= "; note that all comments were truncated" ; + fi+= "\n"; + fi+="\n"; +#endif + + WriteFile(hFile, fi, fi.GetLength(), &bwr, NULL); + + fi=""; + + // MW 07/28/01: Header saving at top + for(i=0;iIsRulesSection(*ini.GetSectionName(i))) + { + rulessections[*ini.GetSectionName(i)]=TRUE; + + fi= "[" ; + fi+= *ini.GetSectionName(i); + fi+= "]" ; + fi+= "\n"; + + WriteFile(hFile, fi, fi.GetLength(), &bwr, NULL); + + int e; + CIniFileSection& sec=*ini.GetSection(i); + CString d; + + + char c[50]; + for(e=0;edata()); + + + //its a standard section: + fi= "[" ; + fi+= *ini.GetSectionName(i); + fi+= "]" ; + fi+= "\n"; + + WriteFile(hFile, fi, fi.GetLength(), &bwr, NULL); + + int e; + CIniFileSection& sec=*ini.GetSection(i); + CString d; + + + char c[50]; + for(e=0;e=0) gm=gm.Left(gm.ReverseFind(',')); + + f.sections[CoreName].values["GameMode"]=gm; + + char c[50]; + itoa(maxplayers, c, 10); + f.sections[CoreName].values["MaxPlayers"]=c; + itoa(minplayers,c,10); + f.sections[CoreName].values["MinPlayers"]=c; + + f.sections[CoreName].values["CD"]="0,1"; + + + f.SaveFile(PKTFileName); + + LPCSTR files[2]; + files[0]=(LPCSTR)PKTFileName; + files[1]=(LPCSTR)MAPFileName; + +#ifdef RA2_MODE + auto game = yuri_mode ? FSunPackLib::Game::RA2_YR : FSunPackLib::Game::RA2; +#else + auto game = FSunPackLib::Game::TS; +#endif + FSunPackLib::WriteMixFile(MMXFileName, files, 2, game); + + DeleteFile(PKTFileName); + DeleteFile(MAPFileName); + } + else + { + // MW 07/20/01: + InsertPrevFile(u8FileName.c_str()); + } + } + + deleteFile(tempfile); + + SetCursor(m_hArrowCursor); + //SetReady(); + + } + +void CFinalSunDlg::SetReady() +{ + m_view.m_statbar.GetStatusBarCtrl().SetText(TranslateStringACP("Ready"), 0,0); +} + +void CFinalSunDlg::SetText(const char *text) +{ + m_view.m_statbar.GetStatusBarCtrl().SetText(text,0,0); +} + +void CFinalSunDlg::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu) +{ + + + CDialog::OnMenuSelect(nItemID, nFlags, hSysMenu); + + switch(nItemID) + { + case ID_FILE_OPENMAP: + SetText(GetLanguageStringACP("FileOpenHelp")); + break; + case ID_FILE_SAVE: + SetText(GetLanguageStringACP("FileSaveHelp")); + break; + case ID_FILE_SAVEAS: + SetText(GetLanguageStringACP("FileSaveAsHelp")); + break; + case ID_FILE_IMPORTMOD: + SetText(GetLanguageStringACP("FileImportModHelp")); + break; + case ID_FILE_QUIT: + SetText(GetLanguageStringACP("FileQuitHelp")); + break; + case ID_FILE_VALIDATEMAP: + SetText(GetLanguageStringACP("FileCheckMapHelp")); + break; + case ID_FILE_RUNTIBERIANSUN: + SetText(GetLanguageStringACP("FileRunTiberianSunHelp")); + break; + case ID_FILE_NEW: + SetText(GetLanguageStringACP("FileNewHelp")); + break; + case ID_MAPVIEW: + SetText(GetLanguageStringACP("OptionsShowMapViewHelp")); + break; + case ID_HELP_INFO: + SetText(GetLanguageStringACP("HelpInfoHelp")); + break; + case ID_HELP_TIPOFTHEDAY: + SetText(GetLanguageStringACP("HelpTipOfTheDayHelp")); + break; + case ID_OPTIONS_EXPORTRULESINI: + SetText("Export the file rules.ini"); + break; + default: + SetReady(); + } +} + + +void se_translator(unsigned int e, _EXCEPTION_POINTERS* p) +{ + throw(unsigned int)(e); +} + + + + +void CFinalSunDlg::OnFileRuntiberiansun() // or RA2 +{ + PROCESS_INFORMATION pi; + STARTUPINFO si; + memset(&si, 0, sizeof(STARTUPINFO)); + si.cb=sizeof(STARTUPINFO); + + CString exe=theApp.m_Options.TSExe; + exe.MakeLower(); + if(yuri_mode) + { + exe.Replace("ra2.exe","ra2md.exe"); + } + + + BOOL success=CreateProcess(exe, + NULL, + NULL, + NULL, + FALSE, + NORMAL_PRIORITY_CLASS, + NULL, + NULL, + &si, + &pi); + +} + + + + +void CFinalSunDlg::OnFileImportmod() +{ + /*CImportModDlg dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_FILEMUSTEXIST, "TS maps|*.mpr;*.map|TS multi maps|*.mpr|TS single maps|*.map|"); + + + + char cuPath[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, cuPath); + dlg.m_ofn.lpstrInitialDir=cuPath; + + //if(theApp.m_Options.TSExe.GetLength()) dlg.m_ofn.lpstrInitialDir=(char*)(LPCTSTR)theApp.m_Options.TSExe; + + if(dlg.DoModal()==IDCANCEL) return; */ + + +} + +void CFinalSunDlg::OnDebugExportmappacknosections() +{ + CIniFile& ini=Map->GetIniFile(); + + CString ovrl; + int i; + + + ovrl=""; + + for(i=0;iGetIniFile(); + + int i; + for(i=0;i=0) + { + CBitmap2MapConverter conv; + HBITMAP hBitmap=(HBITMAP)LoadImageW(NULL, utf8ToUtf16(file.GetString()).c_str(), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); + + conv.Convert(hBitmap, *Map); + + DeleteObject(hBitmap); + } + else + { + Map->LoadMap(file.GetString()); + + if(!bImportOverlay) { + Map->ClearOverlay(); + Map->ClearOverlayData(); + } + + CIniFile& ini=Map->GetIniFile(); + + int i; + int count=Map->GetTerrainCount(); + if(!bImportTrees) + { + for(i=0;iDeleteTerrain(0); + } + + if(!bImportUnits) + { + count=Map->GetInfantryCount(); + for(i=0;iDeleteInfantry(0); + count=Map->GetUnitCount(); + for(i=0;iDeleteUnit(0); + count=Map->GetStructureCount(); + for(i=0;iDeleteStructure(0); + count=Map->GetAircraftCount(); + for(i=0;iDeleteAircraft(0); + } + + ini.sections["Basic"].values["Name"]="Noname"; + + for(i=0;iCreateMap(width, height, theater_s, stdheight); + + if(!bSingleplayer) + { + last_succeeded_operation=11003; + + // create map function was created for SP. Fix it here; + Map->DeleteWaypoint(0); + Map->DeleteWaypoint(0); + int midx=Map->GetIsoSize()/2; + int midy=Map->GetIsoSize()/2; + Map->AddWaypoint("0", midx+midy*Map->GetIsoSize()); + Map->AddWaypoint("1", midx+1+midy*Map->GetIsoSize()); + Map->AddWaypoint("2", midx+2+midy*Map->GetIsoSize()); + Map->AddWaypoint("3", midx+3+midy*Map->GetIsoSize()); + Map->AddWaypoint("4", midx+(midy+1)*Map->GetIsoSize()); + Map->AddWaypoint("5", midx+1+(midy+1)*Map->GetIsoSize()); + Map->AddWaypoint("6", midx+2+(midy+1)*Map->GetIsoSize()); + Map->AddWaypoint("7", midx+3+(midy+1)*Map->GetIsoSize()); + + } + + } + + + last_succeeded_operation=11004; + + + CIniFile& ini=Map->GetIniFile(); + + if(!bSingleplayer) ini.sections["Basic"].values["MultiplayerOnly"]="1"; + + if(bSingleplayer) + { + ini.sections["Basic"].values["MultiplayerOnly"]="0"; + + ini.sections.erase("Preview"); + ini.sections.erase("PreviewPack"); + + + + + if(bPrepareHouses) + { + //CString plhouse; + //plhouse=GetHouseSectionName(dlg.m_House); + plhouse+=" House"; + ini.sections["Basic"].values["Player"]=plhouse; + + int i; + for (i=0;iUpdateIniFile(MAPDATA_UPDATE_FROM_INI); + + last_succeeded_operation=11001; + + Sleep(200); + + SetCursor(m_hArrowCursor); + + bNoDraw=FALSE; + + //if(RepairRulesHouses()) + // MessageBox("Repaired houses"); + + m_view.m_isoview->UpdateDialog(TRUE); + m_view.m_minimap.RedrawWindow(); + UpdateDialogs(); + + last_succeeded_operation=11002; +} + + +/* + UpdateStrings(); + Updates all dialog CStrings, and the CStrings from the isoview object list and the child dialogs +*/ +void CFinalSunDlg::UpdateStrings() +{ + last_succeeded_operation=20; + + CString str; + + // update the menu + CMenu* menu=GetMenu(); + + + // destroy the old menu + if(menu) menu->DestroyMenu(); + // if(menu) delete menu; + + CMenu* my_menu=new(CMenu); + // first, we load the original menu (we can´t translate from for example german!) + my_menu->LoadMenu(IDR_MAIN); + + int i,e; + for(i=0;iGetMenuItemCount();i++) + { + MENUITEMINFO mii; + ZeroMemory(&mii, sizeof(MENUITEMINFO)); + mii.cbSize=sizeof(MENUITEMINFO); + mii.fMask=MIIM_ID | MIIM_STATE | MIIM_TYPE; + + my_menu->GetMenuItemInfo(i, &mii, TRUE); + my_menu->GetMenuString(i, str, MF_BYPOSITION); + my_menu->ModifyMenu(i,mii.fState | mii.fType | MF_BYPOSITION | MF_STRING, mii.wID, TranslateStringACP((LPCTSTR)str)); + for(e=0;eGetSubMenu(i)->GetMenuItemCount();e++) + { + int id=my_menu->GetSubMenu(i)->GetMenuItemID(e); + + ZeroMemory(&mii, sizeof(MENUITEMINFO)); + mii.cbSize=sizeof(MENUITEMINFO); + mii.fMask=MIIM_ID | MIIM_STATE | MIIM_TYPE; + my_menu->GetSubMenu(i)->GetMenuItemInfo(e, &mii, TRUE); + my_menu->GetSubMenu(i)->GetMenuString(e, str, MF_BYPOSITION); + my_menu->GetSubMenu(i)->ModifyMenu(e,mii.fState | mii.fType | MF_BYPOSITION | MF_STRING, mii.wID, TranslateStringACP((LPCTSTR)str)); + + } + } + + + if(theApp.m_Options.bEasy) my_menu->CheckMenuItem(ID_OPTIONS_SIMPLEVIEW, MF_BYCOMMAND | MF_CHECKED); + if(theApp.m_Options.bDisableAutoShore) my_menu->CheckMenuItem(ID_OPTIONS_DISABLEAUTOSHORE, MF_BYCOMMAND | MF_CHECKED); + if(theApp.m_Options.bDisableAutoLat) my_menu->CheckMenuItem(ID_OPTIONS_DISABLEAUTOLAT, MF_BYCOMMAND | MF_CHECKED); + if(theApp.m_Options.bDisableSlopeCorrection) my_menu->CheckMenuItem(ID_OPTIONS_DISABLESLOPECORRECTION, MF_BYCOMMAND | MF_CHECKED); + if(theApp.m_Options.bShowCells) my_menu->CheckMenuItem(ID_OPTIONS_SHOWBUILDINGOUTLINE, MF_BYCOMMAND | MF_CHECKED); + if(theApp.m_Options.useDefaultMouseCursor) my_menu->CheckMenuItem(ID_OPTIONS_USEDEFAULTMOUSECURSOR, MF_BYCOMMAND | MF_CHECKED); + if(!theApp.m_Options.viewScaleUseSteps) my_menu->CheckMenuItem(ID_OPTIONS_SMOOTHZOOM, MF_BYCOMMAND | MF_CHECKED); + + + // MW 07/20/01: Show prev. opened files + int prev_maps_count=0; + for(i=0;i<4;i++) + { + if(theApp.m_Options.prev_maps[i].GetLength()>0) + { + prev_maps_count++; + + int id=0; + CString str="bla"; + str=theApp.m_Options.prev_maps[i]; + + if(i==0) id=ID_FILE_FILE1; + else if(i==1) id=ID_FILE_FILE2; + else if(i==2) id=ID_FILE_FILE3; + else if(i==3) id=ID_FILE_FILE4; + + my_menu->GetSubMenu(0)->InsertMenu(10+prev_maps_count, MF_BYPOSITION | MF_STRING, id, str); + } + } + + +#ifdef RA2_MODE + // my_menu->DeleteMenu(4, MF_BYPOSITION); +#endif + + if(theApp.m_Options.bEasy) my_menu->GetSubMenu(3)->DeleteMenu(0, MF_BYPOSITION); + + if(theApp.m_Options.bEasy) + { + CMenu* edit_my_menu=my_menu->GetSubMenu(1); + for(i=edit_my_menu->GetMenuItemCount()-1;i>=11;i--) // MW 07/17/2001: i>=9 changed to i>=10 so Basic dialog is always available + { + edit_my_menu->DeleteMenu(i, MF_BYPOSITION); + } + CMenu* terrain_my_menu=my_menu->GetSubMenu(2); + for(i=terrain_my_menu->GetMenuItemCount()-1;i>=8;i--) + { + terrain_my_menu->DeleteMenu(i, MF_BYPOSITION); + } + } + +#ifndef SCRIPT_SUPPORT + my_menu->GetSubMenu(3)->DeleteMenu(ID_MAPTOOLS_TOOLSCRIPTS, MF_BYCOMMAND); +#endif + + // now attach this my_menu to the window + SetMenu(my_menu); + + + // update the tabs + /*TCITEM tci; + memset(&tci, 0, sizeof(TCITEM)); + tci.mask=TCIF_TEXT; + tci.pszText=(char*)(LPCTSTR)GetLanguageStringACP("TabBasic"); + m_TabCtrl.SetItem(TAB_BASIC, &tci); + tci.pszText=(char*)(LPCTSTR)GetLanguageStringACP("TabSingleplayerSettings"); + m_TabCtrl.SetItem(TAB_SINGLEPLAYERSETTINGS, &tci); + tci.pszText=(char*)(LPCTSTR)GetLanguageStringACP("TabMap"); + m_TabCtrl.SetItem(TAB_MAP, &tci); + tci.pszText=(char*)(LPCTSTR)GetLanguageStringACP("TabLighting"); + m_TabCtrl.SetItem(TAB_LIGHTNING, &tci); + tci.pszText=(char*)(LPCTSTR)GetLanguageStringACP("TabSpecial"); + m_TabCtrl.SetItem(TAB_SPECIALFLAGS, &tci); + tci.pszText=(char*)(LPCTSTR)GetLanguageStringACP("TabHouses"); + m_TabCtrl.SetItem(TAB_HOUSES, &tci); + tci.pszText=(char*)(LPCTSTR)GetLanguageStringACP("TabTaskForces"); + m_TabCtrl.SetItem(TAB_TASKFORCES, &tci); + tci.pszText=(char*)(LPCTSTR)GetLanguageStringACP("TabScriptTypes"); + m_TabCtrl.SetItem(TAB_SCRIPTTYPES, &tci); + tci.pszText=(char*)(LPCTSTR)GetLanguageStringACP("TabTeamTypes"); + m_TabCtrl.SetItem(TAB_TEAMTYPES, &tci); + tci.pszText=(char*)(LPCTSTR)GetLanguageStringACP("TabTriggers"); + m_TabCtrl.SetItem(TAB_TRIGGERS, &tci); + tci.pszText=(char*)(LPCTSTR)GetLanguageStringACP("TabTags"); + m_TabCtrl.SetItem(TAB_TAGS, &tci); + tci.pszText=(char*)(LPCTSTR)GetLanguageStringACP("TabAITriggers"); + m_TabCtrl.SetItem(TAB_AITRIGGERTYPES, &tci); + tci.pszText=(char*)(LPCTSTR)GetLanguageStringACP("TabAITriggerEnable"); + m_TabCtrl.SetItem(TAB_AITRIGGERTYPESENABLE, &tci); + tci.pszText=(char*)(LPCTSTR)GetLanguageStringACP("TabOther"); + m_TabCtrl.SetItem(TAB_OTHER, &tci); + */ + + // now the child windows and the iso view + m_view.m_objectview->UpdateDialog(); + m_view.m_browser->m_bar.Update(); + if(m_basic.m_hWnd) m_basic.UpdateStrings(); + if(m_houses.m_hWnd) m_houses.UpdateStrings(); + if(m_map.m_hWnd) m_map.UpdateStrings(); + if(m_singleplayersettings.m_hWnd) m_singleplayersettings.UpdateStrings(); + + // we need to check SimpleView if using easy view + if(theApp.m_Options.bEasy) GetMenu()->CheckMenuItem(ID_OPTIONS_SIMPLEVIEW, MF_BYCOMMAND | MF_CHECKED); + if(!theApp.m_Options.bNoSounds) GetMenu()->CheckMenuItem(ID_OPTIONS_SOUNDS, MF_BYCOMMAND | MF_CHECKED); + + + + RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); +} + +void CFinalSunDlg::OnHelpTipoftheday() +{ + CTipDlg tip; + tip.DoModal(); + +} + +void CFinalSunDlg::UnloadAll() +{ + int iQuit=MessageBox(GetLanguageStringACP("MainDialogExitQuestion"), GetLanguageStringACP("MainDialogExitQuestionCap"), MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2); + if(iQuit==IDNO) return; + else{ + try + { + + CShutDownDlg dlg(this); + dlg.ShowWindow(SW_SHOW); + dlg.UpdateWindow(); + + tiledata=0; + + theApp.m_loading->FreeAll(); + + rules.Clear(); + ai.Clear(); + art.Clear(); + tiles_t.Clear(); + tiles_s.Clear(); + tiles_u.Clear(); + Map->GetIniFile().Clear(); + sound.Clear(); + tutorial.Clear(); + g_data.Clear(); + language.Clear(); + + + + DestroyWindow(); + } + catch(...) + { + DestroyWindow(); + } + } + + +} + +void CFinalSunDlg::OnOptionsSimpleview() +{ + CIniFile Options; + Options.LoadFile(u8AppDataPath+"\\FinalSun.ini"); +#ifdef RA2_MODE + Options.LoadFile(u8AppDataPath+"\\FinalAlert.ini"); +#endif + + if(GetMenu()->GetMenuState(ID_OPTIONS_SIMPLEVIEW, MF_BYCOMMAND) & MF_CHECKED) + { + GetMenu()->CheckMenuItem(ID_OPTIONS_SIMPLEVIEW, MF_BYCOMMAND | MF_UNCHECKED); + theApp.m_Options.bEasy=FALSE; + Options.sections["UserInterface"].values["EasyView"]="0"; + + // hide all dialogs: + HideAllDialogs(); + } + else + { + GetMenu()->CheckMenuItem(ID_OPTIONS_SIMPLEVIEW, MF_BYCOMMAND | MF_CHECKED); + theApp.m_Options.bEasy=TRUE; + Options.sections["UserInterface"].values["EasyView"]="1"; + } + + UpdateStrings(); + +#ifndef RA2_MODE + Options.SaveFile(u8AppDataPath+"\\FinalSun.ini"); +#else + Options.SaveFile(u8AppDataPath+"\\FinalAlert.ini"); +#endif + + UpdateDialogs(); +} + + +void CFinalSunDlg::OnOptionsShowminimap() +{ + bMiniMapClosedByUser=FALSE; + this->m_view.m_minimap.UpdateView(); +} + +void CFinalSunDlg::HideAllDialogs() +{ + if (m_aitriggertypes) + m_aitriggertypes.ShowWindow(SW_HIDE); + if (m_aitriggertypesenable) + m_aitriggertypesenable.ShowWindow(SW_HIDE); + if (m_all) + m_all.ShowWindow(SW_HIDE); + if (m_basic) + m_basic.ShowWindow(SW_HIDE); + if (m_houses) + m_houses.ShowWindow(SW_HIDE); + if (m_lighting) + m_lighting.ShowWindow(SW_HIDE); + if (m_map) + m_map.ShowWindow(SW_HIDE); + if (m_Scripttypes) + m_Scripttypes.ShowWindow(SW_HIDE); + if (m_singleplayersettings) + m_singleplayersettings.ShowWindow(SW_HIDE); + if (m_specialflags) + m_specialflags.ShowWindow(SW_HIDE); + if (m_tags) + m_tags.ShowWindow(SW_HIDE); + if (m_taskforces) + m_taskforces.ShowWindow(SW_HIDE); + if (m_teamtypes) + m_teamtypes.ShowWindow(SW_HIDE); + if (m_triggers) + m_triggers.ShowWindow(SW_HIDE); +} + +void CFinalSunDlg::OnFileValidatemap() +{ + CMapValidator validator; + int iCancel=validator.DoModal(); + if(iCancel==IDCANCEL) return; +} + + + + +void CFinalSunDlg::OnEnterIdle(UINT nWhy, CWnd* pWho) +{ + CDialog::OnEnterIdle(nWhy, pWho); + + +} + + + +void CFinalSunDlg::OnEditBasicsettings() +{ + if(m_basic.m_hWnd==NULL) + { + if(!m_basic.Create(CBasic::IDD, NULL)) + { + MessageBox(GetLanguageStringACP("Err_CreateErr"), "Error"); + } + + } + + if(m_basic.m_hWnd!=NULL) + { + m_basic.UpdateStrings(); + m_basic.UpdateDialog(); + m_basic.ShowWindow(SW_SHOW); + Sound(SOUND_POSITIVE); + } +} + +void CFinalSunDlg::OnEditSingleplayersettings() +{ + if(m_singleplayersettings.m_hWnd==NULL) + { + if(!m_singleplayersettings.Create(CSingleplayerSettings::IDD, NULL)) + { + MessageBox(GetLanguageStringACP("Err_CreateErr"), "Error"); + } + } + + if(m_singleplayersettings.m_hWnd!=NULL) + { + m_singleplayersettings.UpdateStrings(); + m_singleplayersettings.UpdateDialog(); + m_singleplayersettings.ShowWindow(SW_SHOW); + Sound(SOUND_POSITIVE); + } +} + +void CFinalSunDlg::OnSizing(UINT fwSide, LPRECT pRect) +{ + CDialog::OnSizing(fwSide, pRect); + + +} + +void CFinalSunDlg::OnSize(UINT nType, int cx, int cy) +{ + CDialog::OnSize(nType, cx, cy); + + if(nType==SIZE_MINIMIZED) + { + if(!bMiniMapClosedByUser) m_view.m_minimap.ShowWindow(SW_MINIMIZE); + } + else if(nType==SIZE_MAXIMIZED) + { + if(!bMiniMapClosedByUser) m_view.m_minimap.ShowWindow(SW_RESTORE); + } + + RecalcLayout(); +} + +void CFinalSunDlg::OnEditHouses() +{ + if(m_houses.m_hWnd==NULL) + { + if(!m_houses.Create(CHouses::IDD, NULL)) + { + MessageBox(GetLanguageStringACP("Err_CreateErr"), "Error"); + } + } + + if(m_houses.m_hWnd!=NULL) + { + m_houses.UpdateStrings(); + m_houses.UpdateDialog(); + m_houses.ShowWindow(SW_SHOW); + Sound(SOUND_POSITIVE); + } +} + +void CFinalSunDlg::OnEditAitriggers() +{ + if(m_aitriggertypes.m_hWnd==NULL) + { + if(!m_aitriggertypes.Create(CAITriggerTypes::IDD, NULL)) + { + MessageBox(GetLanguageStringACP("Err_CreateErr"), "Error"); + } + } + + if(m_aitriggertypes.m_hWnd!=NULL) + { + //m_aitriggertypes.UpdateStrings(); + m_aitriggertypes.UpdateDialog(); + m_aitriggertypes.ShowWindow(SW_SHOW); + Sound(SOUND_POSITIVE); + + } + +} + +void CFinalSunDlg::OnEditAitriggerenabling() +{ + if(m_aitriggertypesenable.m_hWnd==NULL) + { + if(!m_aitriggertypesenable.Create(CAiTriggerTypesEnable::IDD, NULL)) + { + MessageBox(GetLanguageStringACP("Err_CreateErr"), "Error"); + } + } + + if(m_aitriggertypesenable.m_hWnd!=NULL) + { + //m_aitriggertypesenable.UpdateStrings(); + m_aitriggertypesenable.UpdateDialog(); + m_aitriggertypesenable.ShowWindow(SW_SHOW); + Sound(SOUND_POSITIVE); + + } +} + +void CFinalSunDlg::OnEditIniediting() +{ + if(m_all.m_hWnd==NULL) + { + if(!m_all.Create(CAll::IDD, NULL)) + { + MessageBox(GetLanguageStringACP("Err_CreateErr"), "Error"); + } + } + + if(m_all.m_hWnd!=NULL) + { + //m_all.UpdateStrings(); + m_all.UpdateDialog(); + m_all.ShowWindow(SW_SHOW); + Sound(SOUND_POSITIVE); + } +} + +void CFinalSunDlg::OnEditLighting() +{ + if(m_lighting.m_hWnd==NULL) + { + if(!m_lighting.Create(CLighting::IDD, NULL)) + { + MessageBox(GetLanguageStringACP("Err_CreateErr"), "Error"); + } + } + + if(m_lighting.m_hWnd!=NULL) + { + //m_lighting.UpdateStrings(); + m_lighting.UpdateDialog(); + m_lighting.ShowWindow(SW_SHOW); + Sound(SOUND_POSITIVE); + } + +} + +void CFinalSunDlg::OnEditMap() +{ + if(m_map.m_hWnd==NULL) + { + if(!m_map.Create(CMapD::IDD, NULL)) + { + MessageBox(GetLanguageStringACP("Err_CreateErr"), "Error"); + } + } + + if(m_map.m_hWnd!=NULL) + { + m_map.UpdateStrings(); + m_map.UpdateDialog(); + m_map.ShowWindow(SW_SHOW); + Sound(SOUND_POSITIVE); + } +} + +void CFinalSunDlg::OnEditScripts() +{ + if(m_Scripttypes.m_hWnd==NULL) + { + if(!m_Scripttypes.Create(CScriptTypes::IDD, NULL)) + { + MessageBox(GetLanguageStringACP("Err_CreateErr"), "Error"); + } + } + + if(m_Scripttypes.m_hWnd!=NULL) + { + //m_Scripttypes.UpdateStrings(); + m_Scripttypes.UpdateDialog(); + m_Scripttypes.ShowWindow(SW_SHOW); + Sound(SOUND_POSITIVE); + } +} + +void CFinalSunDlg::OnEditSpecialflags() +{ + if(m_specialflags.m_hWnd==NULL) + { + if(!m_specialflags.Create(CSpecialFlags::IDD, NULL)) + { + MessageBox(GetLanguageStringACP("Err_CreateErr"), "Error"); + } + } + + if(m_specialflags.m_hWnd!=NULL) + { + //m_specialflags.UpdateStrings(); + m_specialflags.UpdateDialog(); + m_specialflags.ShowWindow(SW_SHOW); + Sound(SOUND_POSITIVE); + } +} + +void CFinalSunDlg::OnEditTags() +{ + if(m_tags.m_hWnd==NULL) + { + if(!m_tags.Create(CTags::IDD, NULL)) + { + MessageBox(GetLanguageStringACP("Err_CreateErr"), "Error"); + } + } + + if(m_tags.m_hWnd!=NULL) + { + //m_tags.UpdateStrings(); + m_tags.UpdateDialog(); + m_tags.ShowWindow(SW_SHOW); + Sound(SOUND_POSITIVE); + } +} + +void CFinalSunDlg::OnEditTaskforces() +{ + if(m_taskforces.m_hWnd==NULL) + { + if(!m_taskforces.Create(CTaskForce::IDD, NULL)) + { + MessageBox(GetLanguageStringACP("Err_CreateErr"), "Error"); + } + } + + if(m_taskforces.m_hWnd!=NULL) + { + //m_taskforces.UpdateStrings(); + m_taskforces.UpdateDialog(); + m_taskforces.ShowWindow(SW_SHOW); + Sound(SOUND_POSITIVE); + } +} + +void CFinalSunDlg::OnEditTeams() +{ + if(m_teamtypes.m_hWnd==NULL) + { + if(!m_teamtypes.Create(CTeamTypes::IDD, NULL)) + { + MessageBox(GetLanguageStringACP("Err_CreateErr"), "Error"); + } + } + + if(m_teamtypes.m_hWnd!=NULL) + { + //m_teamtypes.UpdateStrings(); + m_teamtypes.UpdateDialog(); + m_teamtypes.ShowWindow(SW_SHOW); + Sound(SOUND_POSITIVE); + } +} + +void CFinalSunDlg::OnEditTriggers() +{ + if(m_triggers.m_hWnd==NULL) + { + if(!m_triggers.Create(CTriggers::IDD, NULL)) + { + MessageBox(GetLanguageStringACP("Err_CreateErr"), "Error"); + } + } + + if(m_triggers.m_hWnd!=NULL) + { + //m_triggers.UpdateStrings(); + m_triggers.UpdateDialog(); + m_triggers.ShowWindow(SW_SHOW); + Sound(SOUND_POSITIVE); + } +} + +void CFinalSunDlg::OnSetFocus(CWnd* pOldWnd) +{ + CDialog::OnSetFocus(pOldWnd); + + SetForegroundWindow(); +} + +BOOL CFinalSunDlg::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult) +{ + // + + + + return CDialog::OnChildNotify(message, wParam, lParam, pLResult); +} + +void CFinalSunDlg::RecalcLayout() +{ + if(m_bar.m_hWnd==NULL) return; + + RECT r,rr; + GetClientRect(&r); + m_bar.GetWindowRect(&rr); + int h=rr.bottom-rr.top+2; + m_bar.GetClientRect(&rr); + rr.right=r.right; + m_view.SetWindowPos(NULL, 0, h, r.right, r.bottom-h, SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); + m_bar.SetWindowPos(NULL, 0,0, rr.right, rr.bottom, SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); + m_bar.ShowBand(0, TRUE); + m_bar.ShowBand(1, TRUE); +} + +BOOL CFinalSunDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) +{ + NMHDR* pHead=(NMHDR*)lParam; + + if(pHead->hwndFrom==m_bar.m_hWnd && pHead->code==RBN_HEIGHTCHANGE) + { + RecalcLayout(); + } + + if(pHead->code==TTN_NEEDTEXT) + { + TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pHead; + UINT nID =pHead->idFrom; + if (pTTT->uFlags & TTF_IDISHWND) + { + // idFrom ist der HWND des Tools + nID = ::GetDlgCtrlID((HWND)nID); + } + + if(nID) + { + CString s; + char c[50]; + itoa(nID, c, 10); + + s.LoadString(nID); + s=TranslateStringACP(s); + //pTTT->lpszText = s; + if(s.GetLength()>80) s.SetAt(80, 0); + strcpy(pTTT->szText, s); + pTTT->hinst = NULL; + return(TRUE); + } + + } + + return CDialog::OnNotify(wParam, lParam, pResult); +} + +void CFinalSunDlg::OnTerrainHeightenground() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + + if(AD.mode!=ACTIONMODE_HEIGHTEN) + { + m_settingsbar.m_BrushSize=1; + m_settingsbar.UpdateData(FALSE); + m_view.m_isoview->m_BrushSize_x=2; + m_view.m_isoview->m_BrushSize_y=2; + } + + Sound(SOUND_POSITIVE); + + AD.mode=ACTIONMODE_HEIGHTEN; + +} + +void CFinalSunDlg::OnTerrainLowerground() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + + if(AD.mode!=ACTIONMODE_LOWER) + { + m_settingsbar.m_BrushSize=1; + m_settingsbar.UpdateData(FALSE); + m_view.m_isoview->m_BrushSize_x=2; + m_view.m_isoview->m_BrushSize_y=2; + } + + Sound(SOUND_POSITIVE); + + AD.mode=ACTIONMODE_LOWER; +} + +//DEL void CFinalSunDlg::OnTerrainPaint() +//DEL { +//DEL if(m_TerrainDlg.m_hWnd==NULL) +//DEL { +//DEL if(!m_TerrainDlg.Create(NULL, "Terrain-Browser", WS_OVERLAPPEDWINDOW, CFrameWnd::rectDefault, NULL, NULL, 0)) +//DEL { +//DEL MessageBox(GetLanguageStringACP("Err_CreateErr"), "Error"); +//DEL } +//DEL } +//DEL +//DEL if(m_TerrainDlg.m_hWnd!=NULL) +//DEL { +//DEL m_TerrainDlg.ShowWindow(SW_SHOW); +//DEL m_TerrainDlg.ActivateFrame(SW_SHOW); +//DEL m_TerrainDlg.m_bar.Update(); +//DEL } +//DEL } + +void CFinalSunDlg::OnTerrainLowertile() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + + if(AD.mode!=ACTIONMODE_LOWERTILE) + { + m_settingsbar.m_BrushSize=0; + m_settingsbar.UpdateData(FALSE); + m_view.m_isoview->m_BrushSize_x=1; + m_view.m_isoview->m_BrushSize_y=1; + + } + Sound(SOUND_POSITIVE); + + AD.mode=ACTIONMODE_LOWERTILE; + +} + +void CFinalSunDlg::OnTerrainRaisetile() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + + if(AD.mode!=ACTIONMODE_HEIGHTENTILE) + { + m_settingsbar.m_BrushSize=0; + m_settingsbar.UpdateData(FALSE); + m_view.m_isoview->m_BrushSize_x=1; + m_view.m_isoview->m_BrushSize_y=1; + } + Sound(SOUND_POSITIVE); + AD.mode=ACTIONMODE_HEIGHTENTILE; + +} + +void CFinalSunDlg::OnTerrainFlatten() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + + if(AD.mode!=ACTIONMODE_FLATTENGROUND) + { + m_settingsbar.m_BrushSize=1; + m_settingsbar.UpdateData(FALSE); + m_view.m_isoview->m_BrushSize_x=2; + m_view.m_isoview->m_BrushSize_y=2; + } + Sound(SOUND_POSITIVE); + + AD.mode=ACTIONMODE_FLATTENGROUND; +} + +void CFinalSunDlg::OnTerrainCloak() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + + AD.mode=ACTIONMODE_HIDETILESET; + Sound(SOUND_POSITIVE); +} + +void CFinalSunDlg::OnTerrainShoweverytile() +{ + if(!Map->GetIsoSize()) { + Sound(SOUND_NEGATIVE); + return; + } + + m_view.m_isoview->ShowAllTileSets(); + m_view.m_isoview->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + Sound(SOUND_POSITIVE); +} + +void CFinalSunDlg::OnTerrainShowallfields() +{ + if(!Map->GetIsoSize()) { + Sound(SOUND_NEGATIVE); + return; + } + + int i; + for(i=0;iGetIsoSize()*Map->GetIsoSize();i++) + { + Map->HideField(i, FALSE); + } + + m_view.m_isoview->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + Sound(SOUND_POSITIVE); +} + +void CFinalSunDlg::OnTerrainHidefield() +{ + if(!Map->GetIsoSize()) { + Sound(SOUND_NEGATIVE); + return; + } + + AD.mode=ACTIONMODE_HIDEFIELD; + Sound(SOUND_POSITIVE); +} + +void CFinalSunDlg::OnEditTriggereditor() +{ + + + if(m_triggereditor.m_hWnd==NULL) + { + if(!m_triggereditor.Create(CTriggerEditorDlg::IDD, NULL)) + { + MessageBox(GetLanguageStringACP("Err_CreateErr"), "Error"); + } + } + + if(m_triggereditor.m_hWnd!=NULL) + { + //m_all.UpdateStrings(); + m_triggereditor.UpdateDialog(); + m_triggereditor.ShowWindow(SW_SHOW); + Sound(SOUND_POSITIVE); + } +} + +void CFinalSunDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + + CDialog::OnKeyDown(nChar, nRepCnt, nFlags); +} + +void CFinalSunDlg::OnMaptoolsChangemapheight() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + + Sound(SOUND_POSITIVE); + + int vmin=-MAXHEIGHT; + int vmax=MAXHEIGHT; + + int isosize=Map->GetIsoSize(); + int mapsize=isosize*isosize; + int mapwidth=Map->GetWidth(); + int mapheight=Map->GetHeight(); + int max=Map->GetIsoSize()*Map->GetIsoSize(); + int i; + for(i=0;imapwidth+mapheight*2 || (dwY+1>mapwidth && dwXmapwidth && dwY+mapwidthmapwidth+mapheight*2 || (dwY+2>mapwidth && dwX-2mapwidth && dwY+mapwidth-2mapwidth+mapheight*2 || (dwY+1>mapwidth && dwX-1mapwidth && dwY+mapwidth-1GetHeightAt(i); + if(v+vmin <0) + { + vmin=-v; + } + if(v+vmax>MAXHEIGHT) + { + vmax=MAXHEIGHT-v; + } + } + } + + CString p=GetLanguageStringACP("StrChangeHeight"); + char c[50]; + itoa(vmin, c, 10); + p=TranslateStringVariables(1, p, c); + itoa(vmax, c, 10); + p=TranslateStringVariables(2, p, c); + + CString res=InputBox(p, + GetLanguageStringACP("StrChangeHeightCap")); + + if(res.GetLength()<0) return; + + int a=atoi(res); + if(a==0) return; + + + + + + for(i=0;imapwidth+mapheight*2 || (dwY+1>mapwidth && dwXmapwidth && dwY+mapwidthmapwidth+mapheight*2 || (dwY+2>mapwidth && dwX-2mapwidth && dwY+mapwidth-2mapwidth+mapheight*2 || (dwY+1>mapwidth && dwX-1mapwidth && dwY+mapwidth-1GetHeightAt(i); + if(v+a <0 || v+a>MAXHEIGHT) + { + MessageBox(GetLanguageStringACP("StrChangeHeightErr"), GetLanguageStringACP("StrChangeHeightErrCap"), MB_ICONSTOP); + return; + } + } + } + + for(i=0;iGetHeightAt(i); + Map->SetHeightAt(i, v+a); + } + + this->m_view.m_isoview->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); +} + +void CFinalSunDlg::OnEditGlobalvariables() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + + Sound(SOUND_POSITIVE); + CGlobalsDlg dlg; + dlg.DoModal(); + UpdateDialogs(TRUE); +} + +BOOL CFinalSunDlg::PreTranslateMessage(MSG* pMsg) +{ + // CG: Der folgende Block wurde von der Komponente "QuickInfo" hinzugefĂ¼gt. + { + // Diese Nachricht von QuickInfo verarbeiten lassen. + //m_tooltip.RelayEvent(pMsg); + } + return CDialog::PreTranslateMessage(pMsg); // CG: Dies wurde von der Komponente "QuickInfo" hinzugefĂ¼gt. +} + +void CFinalSunDlg::OnEditUndo() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + + //int a=0; + //int b=2/a; + //memcpy( (void*)0xddffeedd,&a, 1); + Sound(SOUND_POSITIVE); + Map->Undo(); + //UpdateDialogs(FALSE); + m_view.m_isoview->SendMessage(WM_RBUTTONUP); + m_view.m_isoview->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); +} + +void CFinalSunDlg::OnHelpManual() +{ + Sound(SOUND_POSITIVE); + if(ShellExecuteW(0, NULL, (utf8ToUtf16(AppPath)+L"\\HelpManual.pdf").c_str(), NULL, NULL, SW_NORMAL) == 0) + { + MessageBox((CString)"Could not open HelpManual.pdf! Try opening "+(CString)AppPath+(CString)"\\HelpManual manually."); + } +} + + +LONG __stdcall ExceptionHandler( + _EXCEPTION_POINTERS *ExceptionInfo // address of + // exception info +) +{ + CString s; + CString s2; + CString s_add; + char adress[50]; + char c[50]; + itoa((int)ExceptionInfo->ExceptionRecord->ExceptionAddress, adress, 16); + s="Unknown exception"; + switch(ExceptionInfo->ExceptionRecord->ExceptionCode) + { + case EXCEPTION_ACCESS_VIOLATION: + s="EXCEPTION_ACCESS_VIOLATION"; + s2="Thread did not have read or write access to the virtual address."; + if(ExceptionInfo->ExceptionRecord->ExceptionInformation[0]) + { + s_add="\nAdditional information: Write access to 0x"; + } + else + s_add="\nAdditional information: Read access from 0x"; + + itoa(ExceptionInfo->ExceptionRecord->ExceptionInformation[1], c, 16); + + s_add+=c; + + break; + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + s="EXCEPTION_ARRAY_BOUNDS_EXCEEDED"; + s2="Thread tried to access an array out of bounds."; + break; + case EXCEPTION_BREAKPOINT : + s="EXCEPTION_BREAKPOINT"; + s2="Encountered breakpoint."; + break; + case EXCEPTION_DATATYPE_MISALIGNMENT: + s="EXCEPTION_DATATYPE_MISALIGNMENT"; + s2="Access to memory was misaligned for the given datatype."; + break; + case EXCEPTION_FLT_DENORMAL_OPERAND: + s="EXCEPTION_FLT_DENORMAL_OPERAND"; + s2="Denormal operand in floating point operation."; + break; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + s="EXCEPTION_FLT_DIVIDE_BY_ZERO"; + s2="Thread divided by zero in a floating point operation."; + break; + case EXCEPTION_FLT_INEXACT_RESULT : + s="EXCEPTION_FLT_INEXACT_RESULT"; + s2="Floating point operation result not representable with exact decimal fraction."; + break; + case EXCEPTION_FLT_INVALID_OPERATION: + s="EXCEPTION_FLT_INVALID_OPERATION"; + s2="Invalid floating point operation."; + break; + case EXCEPTION_FLT_OVERFLOW : + s="EXCEPTION_FLT_OVERFLOW"; + s2="Floating point overflow error."; + break; + case EXCEPTION_FLT_STACK_CHECK : + s="EXCEPTION_FLT_STACK_CHECK"; + s2="Floating point operation caused stack overflow or underflow."; + break; + case EXCEPTION_FLT_UNDERFLOW: + s="EXCEPTION_FLT_UNDERFLOW"; + s2="Floating point underflow error."; + break; + case EXCEPTION_ILLEGAL_INSTRUCTION: + s="EXCEPTION_ILLEGAL_INSTRUCTION"; + s2="Thread executed illegal instruction."; + break; + case EXCEPTION_IN_PAGE_ERROR: + s="EXCEPTION_IN_PAGE_ERROR"; + s2="Thread tried to access a page that could not be retrieved by the system."; + break; + case EXCEPTION_INT_DIVIDE_BY_ZERO: + s="EXCEPTION_INT_DIVIDE_BY_ZERO"; + s2="Thread divided by zero in an integer operation."; + break; + case EXCEPTION_INT_OVERFLOW: + s="EXCEPTION_INT_OVERFLOW"; + s2="Integer operation caused overflow."; + break; + case EXCEPTION_INVALID_DISPOSITION: + s="EXCEPTION_INVALID_DISPOSITION"; + s2="Exception handler returned invalid disposition."; + break; + case EXCEPTION_NONCONTINUABLE_EXCEPTION: + s="EXCEPTION_NONCONTINUABLE_EXCEPTION"; + s2="Cannot continue execution after a noncontinuable exception."; + break; + case EXCEPTION_PRIV_INSTRUCTION : + s="EXCEPTION_PRIV_INSTRUCTION"; + s2="Instruction not valid in the current machine mode."; + break; + case EXCEPTION_SINGLE_STEP: + s="EXCEPTION_SINGLE_STEP"; + s2="Instruction step has been executed."; + break; + case EXCEPTION_STACK_OVERFLOW: + s="EXCEPTION_STACK_OVERFLOW"; + s2="Stack overflow."; + + } + + CString s3; +#ifdef TS_MODE + s3="INTERNAL APPLICATION ERROR\n\nApplication will now try to free memory, save the current map as \"fcrash_backup.map\" in the FinalSun directory and quit.\n\n\n"; +#else // RA2_MODE + s3="INTERNAL APPLICATION ERROR\n\nApplication will now try to free memory, save the current map as \"fcrash_backup.map\" in the FinalAlert 2 directory and quit.\n\n\n"; +#endif + + s3+="Important: If this error has occured while loading graphics, it can very often be fixed by using another system color resolution (16, 24 or 32 bit)."; + + s3+="\n\nThe following information is available, please note every line below:\n\n"; + s3+="Last succeeded operation: "; + itoa(last_succeeded_operation,c,10); + s3+=c; + s3+=""; + s3+="\nLast library operation: "; + itoa(FSunPackLib::last_succeeded_operation,c,10); + s3+=c; + s3+="\n"; + s3+="\nException data:\n"; + s3+=s; + s3+="\n"; + s3+=s2; + s3+="\nAt address: "; + s3+=adress; + s3+=s_add; + + + errstream << "Exception occured. Current data:" << endl; + errstream << "Last succeeded operation:" << last_succeeded_operation << endl; + errstream << "Last succeeded library operation:" << FSunPackLib::last_succeeded_operation << endl; + errstream << "Trying to save current map" << endl; + errstream.flush(); + + + + if(MessageBox(0,s3,"Fatal error",MB_OKCANCEL)==IDOK) + { + return EXCEPTION_CONTINUE_EXECUTION; + } + + std::string file=u8AppDataPath; + file+="\\fcrash_backup.map"; + ((CFinalSunDlg*)theApp.m_pMainWnd)->SaveMap(file.c_str()); + + theApp.m_loading->FreeAll(); + + rules.Clear(); + ai.Clear(); + art.Clear(); + tiles_t.Clear(); + tiles_s.Clear(); + tiles_u.Clear(); + Map->GetIniFile().Clear(); + sound.Clear(); + tutorial.Clear(); + g_data.Clear(); + language.Clear(); + +#ifdef _DEBUG + return EXCEPTION_CONTINUE_SEARCH; +#endif + + return EXCEPTION_EXECUTE_HANDLER;//EXCEPTION_CONTINUE_SEARCH;//EXCEPTION_EXECUTE_HANDLER; +} + +int CFinalSunDlg::DoModal() +{ + int res=0; + SetUnhandledExceptionFilter(ExceptionHandler); + + res=CDialog::DoModal(); + + return res; +} + +void CFinalSunDlg::OnMaptoolsAutolevel() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + + Sound(SOUND_POSITIVE); + MessageBox("This tool will try to automatically raise the terrain using the cliffs.\nIt may take some seconds to execute, as there are masses of data to handle.\nAfter this, you should check your map if everything looks fine. If not, you should use the different height tools, especially flatten ground, to fix any errors. You can use Edit->Undo to undo anything that has been done by using this function.", "Auto Leveler"); + + m_view.m_isoview->AutoLevel(); +} + +void CFinalSunDlg::OnUpdateEditAitriggerenabling(CCmdUI* pCmdUI) +{ + + /*if(Map->GetIsoSize()==0) pCmdUI->Enable(FALSE); + else pCmdUI->Enable(TRUE);*/ + +} + +void CFinalSunDlg::OnUpdateEditAitriggers(CCmdUI* pCmdUI) +{ + /*if(Map->GetIsoSize()==0) pCmdUI->Enable(FALSE); + else pCmdUI->Enable(TRUE);*/ +} + +void CFinalSunDlg::OnUpdateEditBasicsettings(CCmdUI* pCmdUI) +{ + /*if(Map->GetIsoSize()==0) pCmdUI->Enable(FALSE); + else pCmdUI->Enable(TRUE);*/ +} + +void CFinalSunDlg::OnUpdateEditGlobalvariables(CCmdUI* pCmdUI) +{ + /*if(Map->GetIsoSize()==0) pCmdUI->Enable(FALSE); + else pCmdUI->Enable(TRUE);*/ +} + +void CFinalSunDlg::OnUpdateEditHouses(CCmdUI* pCmdUI) +{ + CheckAvail(pCmdUI); +} + +void CFinalSunDlg::OnUpdateEditIniediting(CCmdUI* pCmdUI) +{ + + CheckAvail(pCmdUI); + +} + +void CFinalSunDlg::OnUpdateEditLighting(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateEditMap(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateEditScripts(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateEditSingleplayersettings(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateEditSpecialflags(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateEditTags(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateEditTaskforces(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateEditTeams(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateEditTriggereditor(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateEditTriggers(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateEditUndo(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateFileSave(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateFileSaveas(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateFileValidatemap(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateMaptoolsAutolevel(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateMaptoolsChangemapheight(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateOptionsShowminimap(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateTerrainCloak(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateTerrainFlatten(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateTerrainHeightenground(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateTerrainHidefield(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateTerrainLowerground(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateTerrainLowertile(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateTerrainRaisetile(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateTerrainShowallfields(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnUpdateTerrainShoweverytile(CCmdUI* pCmdUI) +{ + // TODO: Code fĂ¼r die Befehlsbehandlungsroutine zum Aktualisieren der Benutzeroberfläche hier einfĂ¼gen + +} + +void CFinalSunDlg::OnMaptoolsFrontcliff() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + if(Map->GetTheater()==THEATER4) + { + MessageBox("There are no cliffs in the Lunar theater"); + return; + } + + Sound(SOUND_POSITIVE); + AD.mode=ACTIONMODE_CLIFFFRONT; +} + +void CFinalSunDlg::OnMaptoolsBackcliff() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + if(Map->GetTheater()==THEATER4) + { + MessageBox("There are no cliffs in the Lunar theater"); + return; + } + + Sound(SOUND_POSITIVE); + AD.mode=ACTIONMODE_CLIFFBACK; +} + +void CFinalSunDlg::OnEditRedo() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + + Sound(SOUND_POSITIVE); + Map->Redo(); + + m_view.m_isoview->SendMessage(WM_RBUTTONUP); + m_view.m_isoview->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); +} + +void CFinalSunDlg::OnMaptoolsAutocreateshores() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + + Sound(SOUND_POSITIVE); + + Map->TakeSnapshot(); + + Map->CreateShore(0,0,Map->GetIsoSize(), Map->GetIsoSize()); + m_view.m_isoview->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + Map->TakeSnapshot(); + Map->Undo(); + +} + +void CFinalSunDlg::OnOptionsDisableautoshore() +{ + + CIniFile Options; + Options.LoadFile(u8AppDataPath+"\\FinalSun.ini"); +#ifdef RA2_MODE + Options.LoadFile(u8AppDataPath+"\\FinalAlert.ini"); +#endif + + if(GetMenu()->GetMenuState(ID_OPTIONS_DISABLEAUTOSHORE, MF_BYCOMMAND) & MF_CHECKED) + { + GetMenu()->CheckMenuItem(ID_OPTIONS_DISABLEAUTOSHORE, MF_BYCOMMAND | MF_UNCHECKED); + theApp.m_Options.bDisableAutoShore=FALSE; + Options.sections["UserInterface"].values["DisableAutoShore"]="0"; + } + else + { + GetMenu()->CheckMenuItem(ID_OPTIONS_DISABLEAUTOSHORE, MF_BYCOMMAND | MF_CHECKED); + theApp.m_Options.bDisableAutoShore=TRUE; + Options.sections["UserInterface"].values["DisableAutoShore"]="1"; + } + + +#ifndef RA2_MODE + Options.SaveFile(u8AppDataPath+"\\FinalSun.ini"); +#else + Options.SaveFile(u8AppDataPath+"\\FinalAlert.ini"); +#endif + +} + + + + + +//DEL void CFinalSunDlg::OnNcPaint() +//DEL { +//DEL CBitmap b; +//DEL b.LoadBitmap(IDB_TEXTURE1); +//DEL CDC dc; +//DEL +//DEL +//DEL CDC* target=GetWindowDC(); +//DEL dc.CreateCompatibleDC(target); +//DEL dc.SelectObject(b); +//DEL +//DEL BITMAP bd; +//DEL b.GetBitmap(&bd); +//DEL +//DEL RECT r; +//DEL GetWindowRect(&r); +//DEL +//DEL int count=(r.right-r.left)/bd.bmWidth+1; +//DEL int i; +//DEL for(i=0;iBitBlt(i*bd.bmWidth,0,bd.bmWidth, bd.bmHeight-1, &dc, 0, 0, SRCCOPY); +//DEL } +//DEL +//DEL ReleaseDC(target); +//DEL +//DEL CMenu* m=GetMenu(); +//DEL if(m) +//DEL { +//DEL count=m->GetMenuItemCount(); +//DEL for(i=0;iGetMenuItemID(i); +//DEL t.itemAction=ODA_DRAWENTIRE; +//DEL t.itemState=ODS_DEFAULT; +//DEL t.hwndItem=(HWND)m->m_hMenu; +//DEL t.rcItem=r; +//DEL CString text; +//DEL m->GetMenuString(t.itemID, text, MF_BYCOMMAND); +//DEL t.itemData=(int)(LPCSTR)text; +//DEL +//DEL m->DrawItem(&t); +//DEL } +//DEL } +//DEL +//DEL +//DEL +//DEL dc.DeleteDC(); +//DEL b.DeleteObject(); +//DEL +//DEL // Kein Aufruf von CDialog::OnNcPaint() fĂ¼r Zeichnungsnachrichten +//DEL } + +void CFinalSunDlg::OnOptionsDisableautolat() +{ + CIniFile Options; + Options.LoadFile(u8AppDataPath+"\\FinalSun.ini"); +#ifdef RA2_MODE + Options.LoadFile(u8AppDataPath+"\\FinalAlert.ini"); +#endif + + if(GetMenu()->GetMenuState(ID_OPTIONS_DISABLEAUTOLAT, MF_BYCOMMAND) & MF_CHECKED) + { + GetMenu()->CheckMenuItem(ID_OPTIONS_DISABLEAUTOLAT, MF_BYCOMMAND | MF_UNCHECKED); + theApp.m_Options.bDisableAutoLat=FALSE; + Options.sections["UserInterface"].values["DisableAutoLat"]="0"; + } + else + { + GetMenu()->CheckMenuItem(ID_OPTIONS_DISABLEAUTOLAT, MF_BYCOMMAND | MF_CHECKED); + theApp.m_Options.bDisableAutoLat=TRUE; + Options.sections["UserInterface"].values["DisableAutoLat"]="1"; + } + + +#ifndef RA2_MODE + Options.SaveFile(u8AppDataPath+"\\FinalSun.ini"); +#else + Options.SaveFile(u8AppDataPath+"\\FinalAlert.ini"); +#endif +} + +void CFinalSunDlg::OnEditPaste() +{ + Sound(SOUND_POSITIVE); + AD.mode=ACTIONMODE_PASTE; + AD.z_data=0; +} + +void CFinalSunDlg::OnEditCopy() +{ + Sound(SOUND_POSITIVE); + AD.mode=ACTIONMODE_COPY; +} + +void CFinalSunDlg::OnEditCopywholemap() +{ + Sound(SOUND_POSITIVE); + Map->Copy(); +} + +void CFinalSunDlg::OnEditPastewholemap() +{ + Sound(SOUND_POSITIVE); + Map->Paste(Map->GetIsoSize()/2,Map->GetIsoSize()/2,0); + m_view.m_isoview->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); +} + +void CFinalSunDlg::OnMarblemadness() +{ + if(Map->GetIsoSize()==0) + { + Sound(SOUND_NEGATIVE); + return; + } + + Sound(SOUND_POSITIVE); + + theApp.m_Options.bMarbleMadness=! theApp.m_Options.bMarbleMadness; + + m_view.m_isoview->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + m_view.m_browser->m_view.SetTileSet(m_view.m_browser->m_view.m_currentTileSet, TRUE); +} + +void CFinalSunDlg::CheckAvail(CCmdUI *pCmdUI) +{ + /*if(Map->GetIsoSize()==0) + { + pCmdUI->Enable(FALSE); + + if(pCmdUI->m_pMenu) + { + pCmdUI->m_pMenu->DeleteMenu(pCmdUI->m_nIndex, MF_BYPOSITION); + } + } + else + { + pCmdUI->Enable(TRUE); + + + if(pCmdUI->m_pMenu) + { + pCmdUI->m_pMenu->ModifyMenu(pCmdUI->m_nID, MF_BYCOMMAND | MF_ENABLED); + } + }*/ +} + +void CFinalSunDlg::OnOptionsSounds() +{ + CIniFile Options; + Options.LoadFile(u8AppDataPath+"\\FinalSun.ini"); +#ifdef RA2_MODE + Options.LoadFile(u8AppDataPath+"\\FinalAlert.ini"); +#endif + + if(GetMenu()->GetMenuState(ID_OPTIONS_SOUNDS, MF_BYCOMMAND) & MF_CHECKED) + { + GetMenu()->CheckMenuItem(ID_OPTIONS_SOUNDS, MF_BYCOMMAND | MF_UNCHECKED); + theApp.m_Options.bNoSounds=TRUE; + Options.sections["UserInterface"].values["Sounds"]="0"; + } + else + { + GetMenu()->CheckMenuItem(ID_OPTIONS_SOUNDS, MF_BYCOMMAND | MF_CHECKED); + theApp.m_Options.bNoSounds=FALSE; + Options.sections["UserInterface"].values["Sounds"]="1"; + } + + +#ifndef RA2_MODE + Options.SaveFile(u8AppDataPath+"\\FinalSun.ini"); +#else + Options.SaveFile(u8AppDataPath+"\\FinalAlert.ini"); +#endif +} + +void CFinalSunDlg::OnUpdateOptionsSounds(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck(theApp.m_Options.bNoSounds ? 0 : 1); +} + +void CFinalSunDlg::OnOptionsDisableslopecorrection() +{ + CIniFile Options; + Options.LoadFile(u8AppDataPath +"\\FinalSun.ini"); +#ifdef RA2_MODE + Options.LoadFile(u8AppDataPath +"\\FinalAlert.ini"); +#endif + + if(GetMenu()->GetMenuState(ID_OPTIONS_DISABLESLOPECORRECTION, MF_BYCOMMAND) & MF_CHECKED) + { + GetMenu()->CheckMenuItem(ID_OPTIONS_DISABLESLOPECORRECTION, MF_BYCOMMAND | MF_UNCHECKED); + theApp.m_Options.bDisableSlopeCorrection=FALSE; + Options.sections["UserInterface"].values["DisableSlopeCorrection"]="0"; + } + else + { + GetMenu()->CheckMenuItem(ID_OPTIONS_DISABLESLOPECORRECTION, MF_BYCOMMAND | MF_CHECKED); + theApp.m_Options.bDisableSlopeCorrection=TRUE; + Options.sections["UserInterface"].values["DisableSlopeCorrection"]="1"; + } + +#ifndef RA2_MODE + Options.SaveFile(u8AppDataPath+"\\FinalSun.ini"); +#else + Options.SaveFile(u8AppDataPath+"\\FinalAlert.ini"); +#endif +} + +void CFinalSunDlg::OnOptionsShowbuildingoutline() +{ + + + CIniFile Options; + Options.LoadFile(u8AppDataPath+"\\FinalSun.ini"); +#ifdef RA2_MODE + Options.LoadFile(u8AppDataPath+"\\FinalAlert.ini"); +#endif + + if(GetMenu()->GetMenuState(ID_OPTIONS_SHOWBUILDINGOUTLINE, MF_BYCOMMAND) & MF_CHECKED) + { + GetMenu()->CheckMenuItem(ID_OPTIONS_SHOWBUILDINGOUTLINE, MF_BYCOMMAND | MF_UNCHECKED); + theApp.m_Options.bShowCells=FALSE; + Options.sections["UserInterface"].values["ShowBuildingCells"]="0"; + } + else + { + GetMenu()->CheckMenuItem(ID_OPTIONS_SHOWBUILDINGOUTLINE, MF_BYCOMMAND | MF_CHECKED); + theApp.m_Options.bShowCells=TRUE; + Options.sections["UserInterface"].values["ShowBuildingCells"]="1"; + } + + m_view.m_isoview->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + +#ifndef RA2_MODE + Options.SaveFile(u8AppDataPath +"\\FinalSun.ini"); +#else + Options.SaveFile(u8AppDataPath +"\\FinalAlert.ini"); +#endif +} + + +void CFinalSunDlg::OnFileFile1() +{ + if(DoesFileExist(theApp.m_Options.prev_maps[0])) OpenMap(theApp.m_Options.prev_maps[0]); + +} + +void CFinalSunDlg::OnFileFile2() +{ + if(DoesFileExist(theApp.m_Options.prev_maps[1])) OpenMap(theApp.m_Options.prev_maps[1]); + +} + +void CFinalSunDlg::OnFileFile3() +{ + if(DoesFileExist(theApp.m_Options.prev_maps[2])) OpenMap(theApp.m_Options.prev_maps[2]); + +} + +void CFinalSunDlg::OnFileFile4() +{ + if(DoesFileExist(theApp.m_Options.prev_maps[3])) OpenMap(theApp.m_Options.prev_maps[3]); + +} + +// MW 07/20/01: Checks if file already exists in prev. files list. If not, adds it (may delete old ones) +void CFinalSunDlg::InsertPrevFile(CString lpFilename) +{ + int i; + + //int free_at=-1; + for(i=0;i<4;i++) + { + CString f=theApp.m_Options.prev_maps[i]; + CString f2=lpFilename; + f2.MakeLower(); + f.MakeLower(); + + if(f==f2) + { + return; + } + + /*if(free_at<0) + { + if(theApp.m_Options.prev_maps[i].GetLength()==0) + { + free_at=i; + } + }*/ + } + + CIniFile Options; + Options.LoadFile(u8AppDataPath +"\\FinalSun.ini"); +#ifdef RA2_MODE + Options.LoadFile(u8AppDataPath +"\\FinalAlert.ini"); +#endif + + + + + + + for(i=3;i>0;i--) + { + theApp.m_Options.prev_maps[i]=theApp.m_Options.prev_maps[i-1]; + char e[10]; + itoa(i, e, 10); + + Options.sections["Files"].values[e]=theApp.m_Options.prev_maps[i]; + } + + theApp.m_Options.prev_maps[0]=lpFilename; + Options.sections["Files"].values["0"]=theApp.m_Options.prev_maps[0]; + + + +#ifndef RA2_MODE + Options.SaveFile(u8AppDataPath +"\\FinalSun.ini"); +#else + Options.SaveFile(u8AppDataPath +"\\FinalAlert.ini"); +#endif + + UpdateStrings(); +} + +// MW 07/20/01: New: for files clicked in the file list... copied from OnFileOpenmap(); +void CFinalSunDlg::OpenMap(LPCSTR lpFilename) +{ + CString r=GetLanguageStringACP("SAVEDLG_FILETYPES"); + r=TranslateStringVariables(8, r, ";"); + //CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_FILEMUSTEXIST, r); + + char cuPath[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, cuPath); + //dlg.m_ofn.lpstrInitialDir=cuPath; + + //if(theApp.m_Options.TSExe.GetLength()) dlg.m_ofn.lpstrInitialDir=(char*)(LPCTSTR)theApp.m_Options.TSExe; + + + //if(dlg.DoModal()==IDCANCEL) return; + + + m_PKTHeader.Clear(); + + CString fileToOpen=lpFilename;//dlg.GetPathName(); + fileToOpen.MakeLower(); + CString ext=fileToOpen.Right(fileToOpen.GetLength()-fileToOpen.ReverseFind('.')-1); //dlg.GetFileExt(); + + ext.MakeLower(); + BOOL bLoadedFromMMX=FALSE; + if(ext=="mmx") + { + HMIXFILE hMix=FSunPackLib::XCC_OpenMix(fileToOpen, NULL); + fileToOpen.Replace(".mmx", ".map"); + + if(fileToOpen.ReverseFind('\\')>=0) fileToOpen=fileToOpen.Right(fileToOpen.GetLength()-fileToOpen.ReverseFind('\\')-1); + + CString extractFile=u8AppDataPath.c_str(); + CString pktFile=fileToOpen; + pktFile.Replace(".map", ".pkt"); + extractFile+="\\mmx_tmp.pkt"; + + FSunPackLib::XCC_ExtractFile(pktFile, extractFile, hMix); + m_PKTHeader.LoadFile(extractFile, TRUE); + fileToOpen=m_PKTHeader.sections["MultiMaps"].values["1"]+".map"; + + + + extractFile=u8AppDataPath.c_str(); + extractFile+="\\mmx_tmp.map"; + FSunPackLib::XCC_ExtractFile(fileToOpen, extractFile, hMix); + fileToOpen=extractFile; + + + + FSunPackLib::XCC_CloseMix(hMix); + bLoadedFromMMX=TRUE; + } + + CIniFile f; + f.InsertFile(fileToOpen, "Map"); + if((f.sections["Map"].values["Theater"]==THEATER0 && theApp.m_Options.bDoNotLoadTemperateGraphics) || (f.sections["Map"].values["Theater"]==THEATER1 && theApp.m_Options.bDoNotLoadSnowGraphics)) + { + MessageBox("You have selected to don´t show temperate or snow theater, but this map uses this theater. You cannot load it without restarting FinalSun/FinalAlert 2 with this theater enabled.", "Error"); + return; + } + + bNoDraw=TRUE; + + CString str = GetLanguageStringACP("MainDialogCaption"); + str+=" ("; + str+=(char*)(LPCTSTR)lpFilename; + str+=")"; + + // MW 07/20/01: Update prev. files + InsertPrevFile(lpFilename); + + this->SetWindowText(str); + + SetCursor(LoadCursor(NULL, IDC_WAIT)); + + errstream << "Map->LoadMap() will be called" << endl; + errstream.flush(); + + + + Map->LoadMap((char*)(LPCTSTR)fileToOpen); + + + BOOL bNoMapFile=FALSE; + if(!Map->CheckMapPackData()) + { + int res=MessageBox("This map seems to be corrupt. Do you want to try repairing it? If you click cancel, a empty map will be created, if you click no, it will load the map as it is","Corrupt", MB_YESNOCANCEL); + if(res==IDCANCEL) + { + Map->CreateMap(32,32,THEATER0,0); + bNoMapFile=TRUE; + } + else + { + if(res==IDYES) // try repair + { + int fielddata_size=Map->GetIsoSize()*Map->GetIsoSize(); + + int i; + for(i=0;iGetFielddataAt(i)->wGround; + if(gr==0xFFFF) gr=0; + + if(gr>=(*tiledata_count)) + { + Map->SetTileAt(i, 0, 0); + } + else + { + if((*tiledata)[gr].wTileCount<=Map->GetFielddataAt(i)->bSubTile) + { + Map->SetTileAt(i, 0, 0); + } + } + } + + } + } + } + + if(!bNoMapFile) + { + if(bLoadedFromMMX) + { + //currentMapFile[0]=0; + strcpy(currentMapFile, lpFilename); + } + else + strcpy(currentMapFile, fileToOpen); + } + + Sleep(200); + + SetCursor(m_hArrowCursor); + + + bNoDraw=FALSE; + + m_view.m_isoview->UpdateDialog(TRUE); + UpdateDialogs(); + +} + +void CFinalSunDlg::OnMaptoolsSearchwaypoint() +{ + if(Map->GetIsoSize()==0) return; + + CSearchWaypointDlg dlg; + if(dlg.DoModal()==IDCANCEL) return; + if(dlg.m_WaypointIndex<0) return; + + m_view.m_isoview->FocusWaypoint(dlg.m_WaypointIndex); +} + +void CFinalSunDlg::OnMaptoolsToolscripts() +{ + if(Map->GetIsoSize()==0) return; + + CUserScriptsDlg dlg; + dlg.DoModal(); + +} + + +void CFinalSunDlg::OnHelpShowlogs() +{ + // TODO: FĂ¼gen Sie hier Ihren Befehlshandlercode ein. + + Sound(SOUND_POSITIVE); + errstream.flush(); + auto f = utf8ToUtf16(theApp.getLogFileName()); + if (ShellExecuteW(0, NULL, f.c_str(), NULL, NULL, SW_NORMAL) == 0) + { + MessageBoxW(nullptr, (std::wstring(L"Could not open log! Try opening ") + f + L" manually").c_str(), L"Cannot open log", MB_ICONEXCLAMATION); + } +} + + +void CFinalSunDlg::OnOptionsSmoothzoom() +{ + CIniFile Options; + Options.LoadFile(u8AppDataPath + "\\FinalSun.ini"); +#ifdef RA2_MODE + Options.LoadFile(u8AppDataPath + "\\FinalAlert.ini"); +#endif + + if (GetMenu()->GetMenuState(ID_OPTIONS_SMOOTHZOOM, MF_BYCOMMAND) & MF_CHECKED) + { + GetMenu()->CheckMenuItem(ID_OPTIONS_SMOOTHZOOM, MF_BYCOMMAND | MF_UNCHECKED); + theApp.m_Options.viewScaleUseSteps = true; + } + else + { + GetMenu()->CheckMenuItem(ID_OPTIONS_SMOOTHZOOM, MF_BYCOMMAND | MF_CHECKED); + theApp.m_Options.viewScaleUseSteps = false; + } + + Options.sections["UserInterface"].values["ViewScaleUseSteps"] = theApp.m_Options.viewScaleUseSteps ? "1" : "0"; + +#ifndef RA2_MODE + Options.SaveFile(u8AppDataPath + "\\FinalSun.ini"); +#else + Options.SaveFile(u8AppDataPath + "\\FinalAlert.ini"); +#endif +} + + +BOOL CFinalSunDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) +{ + if (!CDialog::OnSetCursor(pWnd, nHitTest, message)) + SetCursor(m_hArrowCursor); + return TRUE; +} + + + +void CFinalSunDlg::OnOptionsUsedefaultmousecursor() +{ + CIniFile Options; + Options.LoadFile(u8AppDataPath + "\\FinalSun.ini"); +#ifdef RA2_MODE + Options.LoadFile(u8AppDataPath + "\\FinalAlert.ini"); +#endif + + if (GetMenu()->GetMenuState(ID_OPTIONS_USEDEFAULTMOUSECURSOR, MF_BYCOMMAND) & MF_CHECKED) + { + GetMenu()->CheckMenuItem(ID_OPTIONS_USEDEFAULTMOUSECURSOR, MF_BYCOMMAND | MF_UNCHECKED); + theApp.m_Options.useDefaultMouseCursor = false; + m_hArrowCursor = m_hGameCursor; + } + else + { + GetMenu()->CheckMenuItem(ID_OPTIONS_USEDEFAULTMOUSECURSOR, MF_BYCOMMAND | MF_CHECKED); + theApp.m_Options.useDefaultMouseCursor = true; + m_hArrowCursor = LoadCursor(NULL, IDC_ARROW); + } + + Options.sections["UserInterface"].values["UseDefaultMouseCursor"] = theApp.m_Options.useDefaultMouseCursor ? "1" : "0"; + +#ifndef RA2_MODE + Options.SaveFile(u8AppDataPath + "\\FinalSun.ini"); +#else + Options.SaveFile(u8AppDataPath + "\\FinalAlert.ini"); +#endif +} diff --git a/MissionEditor/FinalSunDlg.h b/MissionEditor/FinalSunDlg.h new file mode 100644 index 0000000..20081c1 --- /dev/null +++ b/MissionEditor/FinalSunDlg.h @@ -0,0 +1,254 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// +// Header-Datei +// + +#if !defined(AFX_TIBERIANSUNMISSIONEDITORDLG_H__9F773424_63BB_11D3_99E0_C30F10710B17__INCLUDED_) +#define AFX_TIBERIANSUNMISSIONEDITORDLG_H__9F773424_63BB_11D3_99E0_C30F10710B17__INCLUDED_ + +#include "ScriptTypes.h" +#include "Triggers.h" +#include "Houses.h" +#include "Basic.h" +#include "all.h" +#include "mapd.h" +#include "Lighting.h" +#include "SpecialFlags.h" +#include "IsoView.h" +#include "TeamTypes.h" +#include "TaskForce.h" +#include "tags.h" +#include "myviewframe.h" +#include "AiTriggerTypesEnable.h" +#include "AITriggerTypes.h" +#include "resource.h" +#include "SingleplayerSettings.h" // HinzugefĂ¼gt von der Klassenansicht +#include "loading.h" +#include "TileSetBrowserFrame.h" // HinzugefĂ¼gt von der Klassenansicht +#include "ToolSettingsBar.h" +#include "TriggerEditorDlg.h" + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CLoading; + +///////////////////////////////////////////////////////////////////////////// +// CFinalSunDlg Dialogfeld + +class CFinalSunDlg : public CDialog +{ +// Konstruktion +public: + void OpenMap(LPCSTR lpFilename); + void InsertPrevFile(CString lpFilename); + void CheckAvail(CCmdUI* pCmdUI); + virtual BOOL PreTranslateMessage(MSG* pMsg); + CTileSetBrowserFrame m_TerrainDlg; + void RecalcLayout(); + CToolBar m_clifftoolbar; + CToolBar m_terraintoolbar; + CToolBar m_maintoolbar; + CToolSettingsBar m_settingsbar; + CReBarCtrl m_bar; + void HideAllDialogs(); + CSingleplayerSettings m_singleplayersettings; + void UpdateStrings(); + CAITriggerTypes m_aitriggertypes; + CAiTriggerTypesEnable m_aitriggertypesenable; + void SetText(const char* text); + void SaveMap(CString FileName); + void SetReady(); + CScriptTypes m_Scripttypes; + CTriggers m_triggers; + CTriggerEditorDlg m_triggereditor; + CTags m_tags; + CTaskForce m_taskforces; + CTeamTypes m_teamtypes; + + CHouses m_houses; + + CSplitterWnd m_splitter_view; + CMyViewFrame m_view; + CSpecialFlags m_specialflags; + CLighting m_lighting; + void UpdateDialogs(BOOL bOnlyMissionControl=FALSE, BOOL bNoRepos=FALSE); + CAll m_all; + CBasic m_basic; + CMapD m_map; + CIniFile m_PKTHeader; + CFinalSunDlg(CWnd* pParent = NULL); // Standard-Konstruktor + +// Dialogfelddaten + //{{AFX_DATA(CFinalSunDlg) + enum { IDD = IDD_FINALSUN_DIALOG }; + CTabCtrl m_TabCtrl; + //}}AFX_DATA + + // Vom Klassenassistenten generierte Ăœberladungen virtueller Funktionen + //{{AFX_VIRTUAL(CFinalSunDlg) + public: + virtual BOOL OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult); + virtual int DoModal(); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); + //}}AFX_VIRTUAL + +// Implementierung +protected: + HICON m_hIcon; + + // Generierte Message-Map-Funktionen + //{{AFX_MSG(CFinalSunDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + afx_msg void OnFileQuit(); + afx_msg void OnSysCommand(UINT nID, LPARAM lParam); + virtual void OnOK(); + virtual void OnCancel(); + afx_msg void OnOptionsTiberiansunoptions(); + afx_msg void OnFileOpenmap(); + afx_msg void OnFileSaveas(); + afx_msg void OnOptionsExportrulesini(); + afx_msg void OnHelpInfo(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + afx_msg void OnFileSave(); + afx_msg void OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu); + afx_msg void OnFileRuntiberiansun(); + afx_msg void OnFileImportmod(); + afx_msg void OnDebugExportmappacknosections(); + afx_msg void OnDebugExportmappack(); + afx_msg void OnFileNew(); + afx_msg void OnHelpTipoftheday(); + afx_msg void OnOptionsSimpleview(); + afx_msg void OnOptionsShowminimap(); + afx_msg void OnFileValidatemap(); + afx_msg void OnEnterIdle(UINT nWhy, CWnd* pWho); + afx_msg void OnEditBasicsettings(); + afx_msg void OnEditSingleplayersettings(); + afx_msg void OnSizing(UINT fwSide, LPRECT pRect); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnEditHouses(); + afx_msg void OnEditAitriggers(); + afx_msg void OnEditAitriggerenabling(); + afx_msg void OnEditIniediting(); + afx_msg void OnEditLighting(); + afx_msg void OnEditMap(); + afx_msg void OnEditScripts(); + afx_msg void OnEditSpecialflags(); + afx_msg void OnEditTags(); + afx_msg void OnEditTaskforces(); + afx_msg void OnEditTeams(); + afx_msg void OnEditTriggers(); + afx_msg void OnSetFocus(CWnd* pOldWnd); + afx_msg void OnTerrainHeightenground(); + afx_msg void OnTerrainLowerground(); + afx_msg void OnTerrainLowertile(); + afx_msg void OnTerrainRaisetile(); + afx_msg void OnTerrainFlatten(); + afx_msg void OnTerrainCloak(); + afx_msg void OnTerrainShoweverytile(); + afx_msg void OnTerrainShowallfields(); + afx_msg void OnTerrainHidefield(); + afx_msg void OnEditTriggereditor(); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnMaptoolsChangemapheight(); + afx_msg void OnEditGlobalvariables(); + afx_msg void OnEditUndo(); + afx_msg void OnHelpManual(); + afx_msg void OnMaptoolsAutolevel(); + afx_msg void OnUpdateEditAitriggerenabling(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditAitriggers(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditBasicsettings(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditGlobalvariables(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditHouses(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditIniediting(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditLighting(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditMap(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditScripts(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditSingleplayersettings(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditSpecialflags(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditTags(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditTaskforces(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditTeams(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditTriggereditor(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditTriggers(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditUndo(CCmdUI* pCmdUI); + afx_msg void OnUpdateFileSave(CCmdUI* pCmdUI); + afx_msg void OnUpdateFileSaveas(CCmdUI* pCmdUI); + afx_msg void OnUpdateFileValidatemap(CCmdUI* pCmdUI); + afx_msg void OnUpdateMaptoolsAutolevel(CCmdUI* pCmdUI); + afx_msg void OnUpdateMaptoolsChangemapheight(CCmdUI* pCmdUI); + afx_msg void OnUpdateOptionsShowminimap(CCmdUI* pCmdUI); + afx_msg void OnUpdateTerrainCloak(CCmdUI* pCmdUI); + afx_msg void OnUpdateTerrainFlatten(CCmdUI* pCmdUI); + afx_msg void OnUpdateTerrainHeightenground(CCmdUI* pCmdUI); + afx_msg void OnUpdateTerrainHidefield(CCmdUI* pCmdUI); + afx_msg void OnUpdateTerrainLowerground(CCmdUI* pCmdUI); + afx_msg void OnUpdateTerrainLowertile(CCmdUI* pCmdUI); + afx_msg void OnUpdateTerrainRaisetile(CCmdUI* pCmdUI); + afx_msg void OnUpdateTerrainShowallfields(CCmdUI* pCmdUI); + afx_msg void OnUpdateTerrainShoweverytile(CCmdUI* pCmdUI); + afx_msg void OnMaptoolsFrontcliff(); + afx_msg void OnMaptoolsBackcliff(); + afx_msg void OnEditRedo(); + afx_msg void OnMaptoolsAutocreateshores(); + afx_msg void OnOptionsDisableautoshore(); + afx_msg void OnOptionsDisableautolat(); + afx_msg void OnEditPaste(); + afx_msg void OnEditCopy(); + afx_msg void OnEditCopywholemap(); + afx_msg void OnEditPastewholemap(); + afx_msg void OnMarblemadness(); + afx_msg void OnOptionsSounds(); + afx_msg void OnUpdateOptionsSounds(CCmdUI* pCmdUI); + afx_msg void OnOptionsDisableslopecorrection(); + afx_msg void OnOptionsShowbuildingoutline(); + afx_msg void OnFileFile1(); + afx_msg void OnFileFile2(); + afx_msg void OnFileFile3(); + afx_msg void OnFileFile4(); + afx_msg void OnMaptoolsSearchwaypoint(); + afx_msg void OnMaptoolsToolscripts(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + void UnloadAll(); + + HCURSOR m_hGameCursor; + +public: + afx_msg void OnHelpShowlogs(); + afx_msg void OnOptionsSmoothzoom(); + afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); + afx_msg void OnOptionsUsedefaultmousecursor(); +}; + +extern HCURSOR m_hArrowCursor; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // !defined(AFX_TIBERIANSUNMISSIONEDITORDLG_H__9F773424_63BB_11D3_99E0_C30F10710B17__INCLUDED_) diff --git a/MissionEditor/FloatEdit.cpp b/MissionEditor/FloatEdit.cpp new file mode 100644 index 0000000..e722aaf --- /dev/null +++ b/MissionEditor/FloatEdit.cpp @@ -0,0 +1,102 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// +// FloatEdit.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "FloatEdit.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CFloatEdit + +CFloatEdit::CFloatEdit() +{ +} + +CFloatEdit::~CFloatEdit() +{ +} + + +BEGIN_MESSAGE_MAP(CFloatEdit, CEdit) + //{{AFX_MSG_MAP(CFloatEdit) + ON_WM_ACTIVATE() + ON_CONTROL_REFLECT(EN_KILLFOCUS, OnKillfocus) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CFloatEdit + + + + + + +void CFloatEdit::OnKillfocus() +{ + + // okay, we need to convert it to a float + CString text, originaltext; + GetWindowText(text); + originaltext=text; + + if(strlen(text)<1) + { + //SetWindowText("0.000000"); + return; + } + + double res=atof(text); + int c,d; + char* j=_fcvt(res, 6, &c, &d); + + int i, slen=strlen(j); + char j2[50]; + + for(i=0;i<6-slen;i++) + { + strcpy(j2, j+i); + j[i]=0; + strcat(j, "0"); + strcat(j,j2); + } + + if(j==NULL) return; + //MessageBox(j,text); + text=j; + text.Insert(c, "."); + + //MessageBox(text); + if(strchr(text, '.')==text) text.Insert(0, "0"); + //delete[](j); + if(originaltext==text) return; + SetWindowText(text); + +} diff --git a/MissionEditor/FloatEdit.h b/MissionEditor/FloatEdit.h new file mode 100644 index 0000000..ef315bf --- /dev/null +++ b/MissionEditor/FloatEdit.h @@ -0,0 +1,68 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_FLOATEDIT_H__D0F98066_6E8E_11D3_99E1_D18E6230AA05__INCLUDED_) +#define AFX_FLOATEDIT_H__D0F98066_6E8E_11D3_99E1_D18E6230AA05__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// FloatEdit.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Fenster CFloatEdit + +class CFloatEdit : public CEdit +{ +// Konstruktion +public: + CFloatEdit(); + +// Attribute +public: + +// Operationen +public: + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CFloatEdit) + //}}AFX_VIRTUAL + +// Implementierung +public: + virtual ~CFloatEdit(); + + // Generierte Nachrichtenzuordnungsfunktionen +protected: + //{{AFX_MSG(CFloatEdit) + afx_msg void OnKillfocus(); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_FLOATEDIT_H__D0F98066_6E8E_11D3_99E1_D18E6230AA05__INCLUDED_ diff --git a/MissionEditor/FrontCliffModifier.cpp b/MissionEditor/FrontCliffModifier.cpp new file mode 100644 index 0000000..b195d88 --- /dev/null +++ b/MissionEditor/FrontCliffModifier.cpp @@ -0,0 +1,103 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// FrontCliffModifier.cpp: Implementierung der Klasse CFrontCliffModifier. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "stdafx.h" +#include "FrontCliffModifier.h" +#include +#include "variables.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +////////////////////////////////////////////////////////////////////// +// Konstruktion/Destruktion +////////////////////////////////////////////////////////////////////// + +CFrontCliffModifier::CFrontCliffModifier() +{ + +} + +CFrontCliffModifier::~CFrontCliffModifier() +{ + +} + + + + + +void CFrontCliffModifier::ModifyStartPos(DWORD *dwStartPos, BOOL bSmall) +{ + + if(m_direction==cd_horiz_right) (*dwStartPos)-=1+0*Map->GetIsoSize(); + if(m_direction==cd_horiz_left) (*dwStartPos)+=-(1)+Map->GetIsoSize(); + if(m_direction==cd_vertic_top) (*dwStartPos)-=-1+0*Map->GetIsoSize(); + if(m_direction==cd_vertic_bottom) (*dwStartPos)-=0*Map->GetIsoSize(); + + if(m_direction==cd_verticdiag_top) (*dwStartPos)+=1+Map->GetIsoSize(); + if(m_direction==cd_verticdiag_bottom) (*dwStartPos)+=0-Map->GetIsoSize(); + + + if(m_direction==cd_horizdiag_right) (*dwStartPos)+=1+0*Map->GetIsoSize(); + if(m_direction==cd_horizdiag_left) (*dwStartPos)+=0+1*Map->GetIsoSize(); +} + +void CFrontCliffModifier::ModifyCurrentPos(DWORD *dwPos, BOOL bBeforePlacing, BOOL bSmall) +{ + if(!bBeforePlacing) + { + if(!bSmall) + { + if(m_direction==cd_verticdiag_top) (*dwPos)+=0+2*Map->GetIsoSize(); + if(m_direction==cd_verticdiag_bottom) (*dwPos)+=0-2*Map->GetIsoSize(); + } + else + { + if(m_direction==cd_verticdiag_top) (*dwPos)+=0+2*Map->GetIsoSize(); + if(m_direction==cd_verticdiag_bottom) (*dwPos)+=0-2*Map->GetIsoSize(); + } + } + else + { + if(bSmall) + { + if(m_direction==cd_verticdiag_top) (*dwPos)+=0-1*Map->GetIsoSize(); + if(m_direction==cd_verticdiag_bottom) (*dwPos)+=0+1*Map->GetIsoSize(); + + + } + + } +} + +CString CFrontCliffModifier::GetDataSection() +{ + if(m_bAlternative) return ("CliffFrontDataAlt"); + return("CliffFrontData"); +} diff --git a/MissionEditor/FrontCliffModifier.h b/MissionEditor/FrontCliffModifier.h new file mode 100644 index 0000000..7bf45dc --- /dev/null +++ b/MissionEditor/FrontCliffModifier.h @@ -0,0 +1,46 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// FrontCliffModifier.h: Schnittstelle fĂ¼r die Klasse CFrontCliffModifier. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_FRONTCLIFFMODIFIER_H__3853D324_CD37_11D4_9C87_F2DC6A2E6849__INCLUDED_) +#define AFX_FRONTCLIFFMODIFIER_H__3853D324_CD37_11D4_9C87_F2DC6A2E6849__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "CliffModifier.h" + +class CFrontCliffModifier : public CCliffModifier +{ +public: + CFrontCliffModifier(); + virtual ~CFrontCliffModifier(); + +protected: + virtual CString GetDataSection(); + virtual void ModifyCurrentPos(DWORD* dwPos, BOOL bBeforePlacing, BOOL bSmall); + virtual void ModifyStartPos(DWORD* dwStartPos, BOOL bSmall); +}; + +#endif // !defined(AFX_FRONTCLIFFMODIFIER_H__3853D324_CD37_11D4_9C87_F2DC6A2E6849__INCLUDED_) diff --git a/MissionEditor/GlobalsDlg.cpp b/MissionEditor/GlobalsDlg.cpp new file mode 100644 index 0000000..8c07264 --- /dev/null +++ b/MissionEditor/GlobalsDlg.cpp @@ -0,0 +1,210 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// GlobalsDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "GlobalsDlg.h" +#include "mapdata.h" +#include "variables.h" +#include "inlines.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CGlobalsDlg + + +CGlobalsDlg::CGlobalsDlg(CWnd* pParent /*=NULL*/) + : CDialog(CGlobalsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CGlobalsDlg) + m_Description = _T(""); + //}}AFX_DATA_INIT +} + + +void CGlobalsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CGlobalsDlg) + DDX_Control(pDX, IDC_VALUE, m_Value); + DDX_Control(pDX, IDC_GLOBAL, m_Global); + DDX_Text(pDX, IDC_DESCRIPTION, m_Description); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CGlobalsDlg, CDialog) + //{{AFX_MSG_MAP(CGlobalsDlg) + ON_EN_CHANGE(IDC_DESCRIPTION, OnChangeDescription) + ON_CBN_SELCHANGE(IDC_GLOBAL, OnSelchangeGlobal) + ON_CBN_SELCHANGE(IDC_VALUE, OnSelchangeValue) + ON_CBN_EDITCHANGE(IDC_VALUE, OnEditchangeValue) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CGlobalsDlg + +void CGlobalsDlg::OnOK() +{ + + // CDialog::OnOK(); +} + +void CGlobalsDlg::OnCancel() +{ + // TODO: Zusätzlichen Bereinigungscode hier einfĂ¼gen + + CDialog::OnCancel(); +} + +void CGlobalsDlg::UpdateDialog() +{ + int oldsel=m_Global.GetCurSel(); + if(oldsel<0) oldsel=0; + + while(m_Global.DeleteString(0)!=CB_ERR); + + int i; + BOOL bFailFind=FALSE; + CIniFile& ini=Map->GetIniFile(); + for(i=0;i<100;i++) + { + char c[50]; + itoa(i,c,10); + CString added=c; + added+=" "; + + if(ini.sections["VariableNames"].FindName(c)>=0) + { + added+=ini.sections["VariableNames"].values[c]; + } + else + { + bFailFind=TRUE; + added+=" No name"; + } + + m_Global.SetItemData(m_Global.AddString(added),i); + + if(bFailFind) break; + } + + m_Global.SetCurSel(oldsel); + OnSelchangeGlobal(); +} + +void CGlobalsDlg::OnChangeDescription() +{ + CIniFile& ini=Map->GetIniFile(); + + int cursel=m_Global.GetCurSel(); + if(cursel<0) return; + int curglob=m_Global.GetItemData(cursel); + + + + char c[50]; + itoa(curglob, c, 10); + + UpdateData(TRUE); + + if(m_Description.Find(",")>=0) m_Description.SetAt(m_Description.Find(","), 0); + + if(ini.sections["VariableNames"].values[c].GetLength()==0) ini.sections["VariableNames"].values[c]="text,0"; + ini.sections["VariableNames"].values[c]=SetParam(ini.sections["VariableNames"].values[c], 0, m_Description); + + // do not remove, Tiberian Sun seems to don´t like probably unused global numbers + //if(m_Description.GetLength()==0) + // ini.sections["VariableNames"].values.erase(c); + + UpdateDialog(); + +} + +void CGlobalsDlg::OnSelchangeGlobal() +{ + CIniFile& ini=Map->GetIniFile(); + + int cursel=m_Global.GetCurSel(); + if(cursel<0) return; + int curglob=m_Global.GetItemData(cursel); + + char c[50]; + itoa(curglob, c, 10); + + if(ini.sections["VariableNames"].FindName(c)>=0) + { + m_Description=GetParam(ini.sections["VariableNames"].values[c],0); + m_Value.SetWindowText(GetParam(ini.sections["VariableNames"].values[c],1)); + } + else + m_Description=""; + + UpdateData(FALSE); +} + +BOOL CGlobalsDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + UpdateDialog(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} + +void CGlobalsDlg::OnSelchangeValue() +{ + +} + +void CGlobalsDlg::OnEditchangeValue() +{ + CIniFile& ini=Map->GetIniFile(); + CString str; + m_Value.GetWindowText(str); + if(str.GetLength()==0) return; + int cursel=m_Global.GetCurSel(); + if(cursel<0) return; + int curglob=m_Global.GetItemData(cursel); + + char c[50]; + itoa(curglob, c, 10); + + if(ini.sections["VariableNames"].FindName(c)<0) return; + + + UpdateData(TRUE); + + str=GetParam(str, 0); + TruncSpace(str); + ini.sections["VariableNames"].values[c]=SetParam(ini.sections["VariableNames"].values[c], 1, str); + + UpdateDialog(); +} diff --git a/MissionEditor/GlobalsDlg.h b/MissionEditor/GlobalsDlg.h new file mode 100644 index 0000000..0aaff16 --- /dev/null +++ b/MissionEditor/GlobalsDlg.h @@ -0,0 +1,75 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_GLOBALSDLG_H__A8AAF461_9DE3_11D4_9C87_A7C4798A5242__INCLUDED_) +#define AFX_GLOBALSDLG_H__A8AAF461_9DE3_11D4_9C87_A7C4798A5242__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// GlobalsDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CGlobalsDlg + +class CGlobalsDlg : public CDialog +{ +// Konstruktion +public: + void UpdateDialog(); + CGlobalsDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CGlobalsDlg) + enum { IDD = IDD_GLOBALS }; + CMyComboBox m_Value; + CComboBox m_Global; + CString m_Description; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CGlobalsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CGlobalsDlg) + virtual void OnOK(); + virtual void OnCancel(); + afx_msg void OnChangeDescription(); + afx_msg void OnSelchangeGlobal(); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeValue(); + afx_msg void OnEditchangeValue(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_GLOBALSDLG_H__A8AAF461_9DE3_11D4_9C87_A7C4798A5242__INCLUDED_ diff --git a/MissionEditor/Houses.cpp b/MissionEditor/Houses.cpp new file mode 100644 index 0000000..d7dd396 --- /dev/null +++ b/MissionEditor/Houses.cpp @@ -0,0 +1,826 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Houses.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "Houses.h" +#include "resource.h" +#include "finalsundlg.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" +#include "newra2housedlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Eigenschaftenseite CHouses + +IMPLEMENT_DYNCREATE(CHouses, CDialog) + +CHouses::CHouses() : CDialog(CHouses::IDD) +{ + //{{AFX_DATA_INIT(CHouses) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Elementinitialisierung ein + //}}AFX_DATA_INIT +} + +CHouses::~CHouses() +{ +} + +void CHouses::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CHouses) + DDX_Control(pDX, IDC_HUMANPLAYER, m_HumanPlayer); + DDX_Control(pDX, IDC_TECHLEVEL, m_TechLevel); + DDX_Control(pDX, IDC_SIDE, m_Side); + DDX_Control(pDX, IDC_PLAYERCONTROL, m_PlayerControl); + DDX_Control(pDX, IDC_PERCENTBUILT, m_PercentBuilt); + DDX_Control(pDX, IDC_NODECOUNT, m_Nodecount); + DDX_Control(pDX, IDC_IQ, m_IQ); + DDX_Control(pDX, IDC_EDGE, m_Edge); + DDX_Control(pDX, IDC_CREDITS, m_Credits); + DDX_Control(pDX, IDC_COLOR, m_Color); + DDX_Control(pDX, IDC_ALLIES, m_Allies); + DDX_Control(pDX, IDC_ACTSLIKE, m_ActsLike); + DDX_Control(pDX, IDC_HOUSES, m_houses); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CHouses, CDialog) + //{{AFX_MSG_MAP(CHouses) + ON_CBN_SELCHANGE(IDC_HOUSES, OnSelchangeHouses) + ON_BN_CLICKED(IDC_PREPAREHOUSES, OnPreparehouses) + ON_WM_SHOWWINDOW() + ON_BN_CLICKED(IDC_ADDHOUSE, OnAddhouse) + ON_BN_CLICKED(IDC_DELETEHOUSE, OnDeletehouse) + ON_CBN_KILLFOCUS(IDC_IQ, OnKillfocusIq) + ON_CBN_KILLFOCUS(IDC_EDGE, OnKillfocusEdge) + ON_CBN_KILLFOCUS(IDC_SIDE, OnKillfocusSide) + ON_CBN_KILLFOCUS(IDC_COLOR, OnKillfocusColor) + ON_EN_KILLFOCUS(IDC_ALLIES, OnKillfocusAllies) + ON_EN_KILLFOCUS(IDC_CREDITS, OnKillfocusCredits) + ON_CBN_EDITCHANGE(IDC_ACTSLIKE, OnEditchangeActslike) + ON_CBN_KILLFOCUS(IDC_NODECOUNT, OnKillfocusNodecount) + ON_CBN_KILLFOCUS(IDC_TECHLEVEL, OnKillfocusTechlevel) + ON_CBN_KILLFOCUS(IDC_PERCENTBUILT, OnKillfocusPercentbuilt) + ON_CBN_KILLFOCUS(IDC_PLAYERCONTROL, OnKillfocusPlayercontrol) + ON_CBN_SELCHANGE(IDC_HUMANPLAYER, OnSelchangeHumanplayer) + ON_CBN_SELCHANGE(IDC_ACTSLIKE, OnSelchangeActslike) + ON_EN_SETFOCUS(IDC_ALLIES, OnSetfocusAllies) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CHouses + +void CHouses::UpdateDialog() +{ + while(this->m_houses.DeleteString(0)!=CB_ERR); + while(this->m_HumanPlayer.DeleteString(0)!=CB_ERR); + while(this->m_Color.DeleteString(0)!=CB_ERR); + while(this->m_ActsLike.DeleteString(0)!=CB_ERR); + + ListHouses(m_Side, FALSE, TRUE); + + int i; + for(i=0;iGetIniFile(); + + if(ini.sections.find(MAPHOUSES)==ini.sections.end() && ini.sections.size()>0) + { + // MessageBox("No houses do exist, if you want to use houses, you should use ""Prepare houses"" before doing anything else."); + } + else + { + m_HumanPlayer.AddString("None"); + m_HumanPlayer.SetCurSel(0); + for(i=0;iGetIniFile(); + + int cusel; + cusel=m_houses.GetCurSel(); + if(cusel==-1) return; + + CString name; + m_houses.GetLBText(cusel, name); + + name=TranslateHouse(name); + + CIniFileSection& s=ini.sections[(LPCTSTR)name]; + + // ListHouses(m_ActsLike, TRUE); + +#ifndef RA2_MODE + m_ActsLike.SetWindowText(s.values["ActsLike"]); +#endif + m_Allies.SetWindowText(TranslateHouse(s.values["Allies"], TRUE)); + m_Color.SetWindowText(s.values["Color"]); + m_Credits.SetWindowText(s.values["Credits"]); + m_Edge.SetWindowText(s.values["Edge"]); + m_IQ.SetWindowText(s.values["IQ"]); + m_Nodecount.SetWindowText(s.values["NodeCount"]); + m_PercentBuilt.SetWindowText(s.values["PercentBuilt"]); + m_PlayerControl.SetWindowText(s.values["PlayerControl"]); +#ifndef RA2_MODE + m_Side.SetWindowText(s.values["Side"]); +#else + m_Side.SetWindowText(TranslateHouse(s.values["Country"], TRUE)); +#endif + m_TechLevel.SetWindowText(s.values["TechLevel"]); + +} + +void CHouses::OnPreparehouses() +{ + CIniFile& ini=Map->GetIniFile(); + +#ifdef RA2_MODE + if(Map->IsMultiplayer()) + { + ini.sections["Basic"].values["MultiplayerOnly"]="1"; + + int i; + for (i=0;i0) + { + MessageBox("There are already houses in your map. You need to delete these first."); + return; + } + } + + int i; + for(i=0;iGetIniFile(); + + if(ini.sections.find(name)!=ini.sections.end()) + { + MessageBox(((CString)"Sorry this name is not available. " + name + (CString)" is already used in the map file. You need to use another name.")); + return; + } + if(ini.sections.find(TranslateHouse(name))!=ini.sections.end()) + { + MessageBox(((CString)"Sorry this name is not available. " + name + (CString)" is already used in the map file. You need to use another name.")); + return; + } +#ifdef RA2_MODE + CNewRA2HouseDlg dlg; + if(dlg.DoModal()==IDCANCEL) return; +#endif + + int c; + + //okay, get a free slot + int pos=-1; +#ifdef RA2_MODE + int pos2=-1; +#endif + for(c=0;c>-1;c++) + { + char k[50]; + itoa(c,k,10); + if(ini.sections[MAPHOUSES].values.find(k)==ini.sections[MAPHOUSES].values.end()) + pos=c; + if(pos!=-1) break; + } +#ifdef RA2_MODE + for(c=0;c>-1;c++) + { + char k[50]; + itoa(c,k,10); + if(ini.sections[HOUSES].values.find(k)==ini.sections[HOUSES].values.end()) + pos2=c; + if(pos2!=-1) break; + } +#endif + + char k[50]; + itoa(pos,k,10); + + ini.sections[MAPHOUSES].values[k]=TranslateHouse(name); + + CString country; + country=name; + country.Replace(" House", ""); + country.Replace("House",""); + if(country.Find(" ")>=0) country.Replace(" ", "_"); //=country.Left(country.Find(" ")); + +#ifdef RA2_MODE + itoa(pos2, k, 10); + ini.sections[HOUSES].values[k]=country; +#endif + + ini.sections[TranslateHouse(name)].values["IQ"]="0"; + ini.sections[TranslateHouse(name)].values["Edge"]="West"; + ini.sections[TranslateHouse(name)].values["Allies"]=TranslateHouse(name); + + CString side=name; +#ifdef RA2_MODE + side=rules.sections[TranslateHouse(dlg.m_Country)].values["Side"]; +#endif + + if(strstr(name, "Nod")!=NULL) + { +#ifndef RA2_MODE + ini.sections[TranslateHouse(name)].values["Side"]="Nod"; +#endif + ini.sections[TranslateHouse(name)].values["Color"]="DarkRed"; + if(name!="Nod") ini.sections[name].values["Allies"]+=",Nod"; + } + else + { +#ifndef RA2_MODE + ini.sections[TranslateHouse(name)].values["Side"]="GDI"; +#endif + ini.sections[TranslateHouse(name)].values["Color"]="Gold"; + if(name!="GDI") ini.sections[TranslateHouse(name)].values["Allies"]+=",GDI"; + } + ini.sections[TranslateHouse(name)].values["Credits"]="0"; +#ifndef RA2_MODE + ini.sections[TranslateHouse(name)].values["ActsLike"]="0"; +#else + ini.sections[TranslateHouse(name)].values["Country"]=TranslateHouse(country); +#endif + ini.sections[TranslateHouse(name)].values["NodeCount"]="0"; + ini.sections[TranslateHouse(name)].values["TechLevel"]="10"; + ini.sections[TranslateHouse(name)].values["PercentBuilt"]="100"; + ini.sections[TranslateHouse(name)].values["PlayerControl"]="no"; + +#ifdef RA2_MODE + dlg.m_Country=TranslateHouse(dlg.m_Country); // just to make sure... + country=TranslateHouse(country); + ini.sections[country].values["ParentCountry"]=dlg.m_Country; + ini.sections[country].values["Name"]=country; + ini.sections[country].values["Suffix"]=rules.sections[dlg.m_Country].values["Suffix"]; + ini.sections[country].values["Prefix"]=rules.sections[dlg.m_Country].values["Prefix"]; + ini.sections[country].values["Color"]=rules.sections[dlg.m_Country].values["Color"]; + ini.sections[country].values["Side"]=rules.sections[dlg.m_Country].values["Side"]; + ini.sections[country].values["SmartAI"]=rules.sections[dlg.m_Country].values["SmartAI"]; + ini.sections[country].values["CostUnitsMult"]="1"; +#endif + + int cusel=m_houses.GetCurSel(); + UpdateDialog(); + ((CFinalSunDlg*)theApp.m_pMainWnd)->UpdateDialogs(); + if(cusel!=-1)m_houses.SetCurSel(cusel); +} + +void CHouses::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialog::OnShowWindow(bShow, nStatus); + + CIniFile& ini=Map->GetIniFile(); + + if(bShow) + { + if(ini.sections.find(MAPHOUSES)==ini.sections.end() && ini.sections.size()>0) + { +#ifndef RA2_MODE + MessageBox("No houses do exist, if you want to use houses, you should use ""Prepare houses"" before doing anything else. Note that in a multiplayer map independent computer players cannot be created by using the names GDI and Nod for the house. Just use something like GDI_AI."); +#else + MessageBox("No houses do exist, if you want to use houses, you should use ""Prepare houses"" before doing anything else."); + +#endif + } + } + else + { + // call all KillFocus ! + OnKillfocusIq(); + OnEditchangeActslike(); + OnKillfocusAllies(); + OnKillfocusColor(); + OnKillfocusCredits(); + OnKillfocusEdge(); + OnKillfocusNodecount(); + OnKillfocusPercentbuilt(); + OnKillfocusPlayercontrol(); + OnKillfocusSide(); + OnKillfocusTechlevel(); + } + +} + +void CHouses::OnAddhouse() +{ + CString name=InputBox(GetLanguageStringACP("AddHouse"),GetLanguageStringACP("AddHouseCap")); + if(name.GetLength()==0) return; + + name=GetHouseSectionName(name); + //name=TranslateHouse(name); + AddHouse(name); +} + +void CHouses::OnDeletehouse() +{ + CIniFile& ini=Map->GetIniFile(); + + int cusel; + cusel=m_houses.GetCurSel(); + if(cusel==-1) return; + + CString name; + CString uiname; + m_houses.GetLBText(cusel, name); + + uiname=name; + name=TranslateHouse(name); + + CString str=GetLanguageStringACP("DeleteHouse"); + str=TranslateStringVariables(1, str, uiname); + if(MessageBox(str,GetLanguageStringACP("DeleteHouseCap"),MB_YESNO)==IDNO) return; + + ini.sections.erase((LPCTSTR)name); + + int i; + for(i=0;iUpdateDialogs(); + UpdateDialog(); +} + +void CHouses::OnKillfocusIq() +{ + CIniFile& ini=Map->GetIniFile(); + + SetMainStatusBarReady(); + + int cusel; + cusel=m_houses.GetCurSel(); + if(cusel==-1) return; + + CString name; + m_houses.GetLBText(cusel, name); + name=TranslateHouse(name); + + CIniFileSection& s=ini.sections[(LPCTSTR)name]; + + CString t; + m_IQ.GetWindowText(t); + s.values["IQ"]=t; +} + +void CHouses::OnKillfocusEdge() +{ + CIniFile& ini=Map->GetIniFile(); + + SetMainStatusBarReady(); + + int cusel; + cusel=m_houses.GetCurSel(); + if(cusel==-1) return; + + CString name; + m_houses.GetLBText(cusel, name); + name=TranslateHouse(name); + + CIniFileSection& s=ini.sections[(LPCTSTR)name]; + + CString t; + m_Edge.GetWindowText(t); + s.values["Edge"]=t; +} + +void CHouses::OnKillfocusSide() +{ + CIniFile& ini=Map->GetIniFile(); + + SetMainStatusBarReady(); + + int cusel; + cusel=m_houses.GetCurSel(); + if(cusel==-1) return; + + CString name; + m_houses.GetLBText(cusel, name); + name=TranslateHouse(name); + + CIniFileSection& s=ini.sections[(LPCTSTR)name]; + + CString t; + m_Side.GetWindowText(t); + t=TranslateHouse(t); +#ifndef RA2_MODE + s.values["Side"]=t; +#else + s.values["Country"]=t; +#endif +} + +void CHouses::OnKillfocusColor() +{ + CIniFile& ini=Map->GetIniFile(); + + SetMainStatusBarReady(); + + int cusel; + cusel=m_houses.GetCurSel(); + if(cusel==-1) return; + + CString name; + m_houses.GetLBText(cusel, name); + name=TranslateHouse(name); + + CIniFileSection& s=ini.sections[(LPCTSTR)name]; + + CString t; + m_Color.GetWindowText(t); + s.values["Color"]=t; + + //Map->UpdateIniFile(MAPDATA_UPDATE_FROM_INI); + // MW fix: Only update structures + // this recalculates the colors + Map->UpdateStructures(FALSE); + // and minimap + Map->RedrawMinimap(); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->RedrawWindow(); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_minimap.RedrawWindow(); +} + +void CHouses::OnKillfocusAllies() +{ + CIniFile& ini=Map->GetIniFile(); + + SetMainStatusBarReady(); + + int cusel; + cusel=m_houses.GetCurSel(); + if(cusel==-1) return; + + CString name; + m_houses.GetLBText(cusel, name); + name=TranslateHouse(name); + + CIniFileSection& s=ini.sections[(LPCTSTR)name]; + + CString t; + m_Allies.GetWindowText(t); + t=TranslateHouse(t); + s.values["Allies"]=t; +} + +void CHouses::OnKillfocusCredits() +{ + CIniFile& ini=Map->GetIniFile(); + + SetMainStatusBarReady(); + + int cusel; + cusel=m_houses.GetCurSel(); + if(cusel==-1) return; + + CString name; + m_houses.GetLBText(cusel, name); + name=TranslateHouse(name); + + CIniFileSection& s=ini.sections[(LPCTSTR)name]; + + CString t; + m_Credits.GetWindowText(t); + s.values["Credits"]=t; +} + +void CHouses::OnEditchangeActslike() +{ + CIniFile& ini=Map->GetIniFile(); + + SetMainStatusBarReady(); + + int cusel; + cusel=m_houses.GetCurSel(); + if(cusel==-1) return; + + CString name; + m_houses.GetLBText(cusel, name); + name=TranslateHouse(name); + + + + CIniFileSection& s=ini.sections[(LPCTSTR)name]; + + CString t; + m_ActsLike.GetWindowText(t); + TruncSpace(t); + t=TranslateHouse(t); + s.values["ActsLike"]=t; +} + +void CHouses::OnKillfocusNodecount() +{ + CIniFile& ini=Map->GetIniFile(); + + SetMainStatusBarReady(); + + int cusel; + cusel=m_houses.GetCurSel(); + if(cusel==-1) return; + + CString name; + m_houses.GetLBText(cusel, name); + name=TranslateHouse(name); + + CIniFileSection& s=ini.sections[(LPCTSTR)name]; + + CString t; + m_Nodecount.GetWindowText(t); + s.values["NodeCount"]=t; +} + +void CHouses::OnKillfocusTechlevel() +{ + CIniFile& ini=Map->GetIniFile(); + + SetMainStatusBarReady(); + + int cusel; + cusel=m_houses.GetCurSel(); + if(cusel==-1) return; + + CString name; + m_houses.GetLBText(cusel, name); + name=TranslateHouse(name); + + CIniFileSection& s=ini.sections[(LPCTSTR)name]; + + CString t; + m_TechLevel.GetWindowText(t); + s.values["TechLevel"]=t; +} + +void CHouses::OnKillfocusPercentbuilt() +{ + CIniFile& ini=Map->GetIniFile(); + + SetMainStatusBarReady(); + + int cusel; + cusel=m_houses.GetCurSel(); + if(cusel==-1) return; + + CString name; + m_houses.GetLBText(cusel, name); + name=TranslateHouse(name); + + CIniFileSection& s=ini.sections[(LPCTSTR)name]; + + CString t; + m_PercentBuilt.GetWindowText(t); + s.values["PercentBuilt"]=t; +} + +void CHouses::OnKillfocusPlayercontrol() +{ + CIniFile& ini=Map->GetIniFile(); + + SetMainStatusBarReady(); + + int cusel; + cusel=m_houses.GetCurSel(); + if(cusel==-1) return; + + CString name; + m_houses.GetLBText(cusel, name); + name=TranslateHouse(name); + + CIniFileSection& s=ini.sections[(LPCTSTR)name]; + + CString t; + m_PlayerControl.GetWindowText(t); + s.values["PlayerControl"]=t; +} + +void CHouses::OnSelchangeHumanplayer() +{ + CIniFile& ini=Map->GetIniFile(); + + CString pl; + m_HumanPlayer.GetLBText(m_HumanPlayer.GetCurSel(),pl); + pl=TranslateHouse(pl); + + if(pl.GetLength()==0 || pl=="None") + { + ini.sections["Basic"].values.erase("Player"); + } + else + { + ini.sections["Basic"].values["Player"]=(LPCTSTR)pl; + } +} + +void CHouses::OnSelchangeActslike() +{ + CIniFile& ini=Map->GetIniFile(); + + int cusel; + cusel=m_houses.GetCurSel(); + if(cusel==-1) return; + + CString name; + m_houses.GetLBText(cusel, name); + name=TranslateHouse(name); + + + + CIniFileSection& s=ini.sections[(LPCTSTR)name]; + + CString t; + m_ActsLike.GetLBText(m_ActsLike.GetCurSel(),t); + TruncSpace(t); + t=TranslateHouse(t); + s.values["ActsLike"]=t; +} + +void CHouses::UpdateStrings() +{ + SetDlgItemText(IDC_DESC, GetLanguageStringACP("HousesDesc")); + SetDlgItemText(IDC_LPLAYER, GetLanguageStringACP("HousesPlayerHouse")); + SetDlgItemText(IDC_LHOUSE, GetLanguageStringACP("HousesHouse")); + SetDlgItemText(IDC_LIQ, GetLanguageStringACP("HousesIQ")); + SetDlgItemText(IDC_LEDGE, GetLanguageStringACP("HousesEdge")); + SetDlgItemText(IDC_LSIDE, GetLanguageStringACP("HousesSide")); + SetDlgItemText(IDC_LCOLOR, GetLanguageStringACP("HousesColor")); + SetDlgItemText(IDC_LALLIES, GetLanguageStringACP("HousesAllies")); + SetDlgItemText(IDC_LCREDITS, GetLanguageStringACP("HousesCredits")); + SetDlgItemText(IDC_LACTSLIKE, GetLanguageStringACP("HousesActsLike")); + SetDlgItemText(IDC_LNODECOUNT, GetLanguageStringACP("HousesNodeCount")); + SetDlgItemText(IDC_LTECHLEVEL, GetLanguageStringACP("HousesTechlevel")); + SetDlgItemText(IDC_LBUILDACTIVITY, GetLanguageStringACP("HousesBuildActivity")); + SetDlgItemText(IDC_LPLAYERCONTROL, GetLanguageStringACP("HousesPlayerControl")); + + SetDlgItemText(IDC_PREPAREHOUSES, GetLanguageStringACP("HousesPrepareHouses")); + SetDlgItemText(IDC_ADDHOUSE, GetLanguageStringACP("HousesAddHouse")); + SetDlgItemText(IDC_DELETEHOUSE, GetLanguageStringACP("HousesDeleteHouse")); + + SetWindowText(TranslateStringACP(HOUSES)); +} + +void CHouses::OnSetfocusAllies() +{ + SetMainStatusBar(GetLanguageStringACP("HousesAlliesHelp")); +} + +void CHouses::PostNcDestroy() +{ + CDialog::PostNcDestroy(); +} diff --git a/MissionEditor/Houses.h b/MissionEditor/Houses.h new file mode 100644 index 0000000..98ffd5e --- /dev/null +++ b/MissionEditor/Houses.h @@ -0,0 +1,104 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_HOUSES_H__80D09600_8932_11D3_B63B_A583BFBD8C41__INCLUDED_) +#define AFX_HOUSES_H__80D09600_8932_11D3_B63B_A583BFBD8C41__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Houses.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CHouses + +class CHouses : public CDialog +{ + DECLARE_DYNCREATE(CHouses) + +// Konstruktion +public: + void UpdateStrings(); + void AddHouse(const char* name); + void UpdateDialog(); + CHouses(); + ~CHouses(); + +// Dialogfelddaten + //{{AFX_DATA(CHouses) + enum { IDD = IDD_HOUSES }; + CComboBox m_HumanPlayer; + CComboBox m_TechLevel; + CComboBox m_Side; + CComboBox m_PlayerControl; + CComboBox m_PercentBuilt; + CComboBox m_Nodecount; + CComboBox m_IQ; + CComboBox m_Edge; + CEdit m_Credits; + CComboBox m_Color; + CEdit m_Allies; + CComboBox m_ActsLike; + CComboBox m_houses; + //}}AFX_DATA + + +// Ăœberschreibungen + // Der Klassen-Assistent generiert virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CHouses) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// Implementierung +protected: + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CHouses) + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeHouses(); + afx_msg void OnPreparehouses(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + afx_msg void OnAddhouse(); + afx_msg void OnDeletehouse(); + afx_msg void OnKillfocusIq(); + afx_msg void OnKillfocusEdge(); + afx_msg void OnKillfocusSide(); + afx_msg void OnKillfocusColor(); + afx_msg void OnKillfocusAllies(); + afx_msg void OnKillfocusCredits(); + afx_msg void OnEditchangeActslike(); + afx_msg void OnKillfocusNodecount(); + afx_msg void OnKillfocusTechlevel(); + afx_msg void OnKillfocusPercentbuilt(); + afx_msg void OnKillfocusPlayercontrol(); + afx_msg void OnSelchangeHumanplayer(); + afx_msg void OnSelchangeActslike(); + afx_msg void OnSetfocusAllies(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_HOUSES_H__80D09600_8932_11D3_B63B_A583BFBD8C41__INCLUDED_ diff --git a/MissionEditor/ImportINI.cpp b/MissionEditor/ImportINI.cpp new file mode 100644 index 0000000..d42f3e9 --- /dev/null +++ b/MissionEditor/ImportINI.cpp @@ -0,0 +1,139 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// ImportINI.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "ImportINI.h" +#include "mapdata.h" +#include "variables.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CImportINI + + +CImportINI::CImportINI(CWnd* pParent /*=NULL*/) + : CDialog(CImportINI::IDD, pParent) +{ + //{{AFX_DATA_INIT(CImportINI) + //}}AFX_DATA_INIT + m_inicount=0; +} + + +void CImportINI::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CImportINI) + DDX_Control(pDX, IDC_AVAILABLE, m_Available); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CImportINI, CDialog) + //{{AFX_MSG_MAP(CImportINI) + ON_BN_CLICKED(IDC_ALLSECTIONS, OnAllsections) + ON_BN_CLICKED(IDC_SPECIFYSECTIONS, OnSpecifysections) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CImportINI + +void CImportINI::OnAllsections() +{ + this->m_Available.EnableWindow(FALSE); + //this->m_Sections.EnableWindow(FALSE); +} + +void CImportINI::OnSpecifysections() +{ + this->m_Available.EnableWindow(); + //this->m_Sections.EnableWindow(); +} + +BOOL CImportINI::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CButton* all; + all=(CButton*)GetDlgItem(IDC_ALLSECTIONS); + all->SetCheck(1); + + this->OnAllsections(); + + CIniFile inifile; + inifile.LoadFile(this->m_FileName); + + if(inifile.sections.size()<1){MessageBox("File does not have any ini content, abort.","Error");EndDialog(IDCANCEL);return TRUE;} + + m_inicount=inifile.sections.size(); + + int i; + for(i=0;iIsMapSection(*inifile.GetSectionName(i))) + m_Available.InsertString(-1, *inifile.GetSectionName(i)); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} + +void CImportINI::OnOK() +{ + CIniFile& ini=Map->GetIniFile(); + + CButton* all; + all=(CButton*)GetDlgItem(IDC_ALLSECTIONS); + + if(all->GetCheck()) + { + // all... + ini.InsertFile(m_FileName, NULL); + } + else + { + // only the chosen sections + + int i; + for(i=0;i0) + { + // ok the user wants to add that section! + CString name; + m_Available.GetText(i, name); + + ini.InsertFile(m_FileName, (char*)(LPCTSTR)name); + } + } + } + + CDialog::OnOK(); +} diff --git a/MissionEditor/ImportINI.h b/MissionEditor/ImportINI.h new file mode 100644 index 0000000..1987406 --- /dev/null +++ b/MissionEditor/ImportINI.h @@ -0,0 +1,72 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_IMPORTINI_H__9DC7B324_6DF2_11D3_99E1_D14A1D4DCF07__INCLUDED_) +#define AFX_IMPORTINI_H__9DC7B324_6DF2_11D3_99E1_D14A1D4DCF07__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ImportINI.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CImportINI + +class CImportINI : public CDialog +{ +// Konstruktion +public: + CString m_FileName; + CImportINI(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CImportINI) + enum { IDD = IDD_IMPORTINI }; + CListBox m_Available; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CImportINI) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CImportINI) + afx_msg void OnAllsections(); + afx_msg void OnSpecifysections(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + WORD m_inicount; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_IMPORTINI_H__9DC7B324_6DF2_11D3_99E1_D14A1D4DCF07__INCLUDED_ diff --git a/MissionEditor/Infantry.cpp b/MissionEditor/Infantry.cpp new file mode 100644 index 0000000..7b6f971 --- /dev/null +++ b/MissionEditor/Infantry.cpp @@ -0,0 +1,173 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Infantrie.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "Infantry.h" +#include "functions.h" +#include "mapdata.h" +#include "variables.h" + + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CInfantrie + + +CInfantrie::CInfantrie(CWnd* pParent /*=NULL*/) + : CDialog(CInfantrie::IDD, pParent) +{ + //{{AFX_DATA_INIT(CInfantrie) + m_direction = _T(""); + m_house = _T(""); + m_flag1 = _T(""); + m_flag2 = _T(""); + m_flag3 = _T(""); + m_flag4 = _T(""); + m_action = _T(""); + m_tag = _T(""); + m_flag5 = _T(""); + //}}AFX_DATA_INIT + Init(); +} + + +void CInfantrie::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CInfantrie) + DDX_Control(pDX, IDC_STRENGTH, m_strength_ctrl); + DDX_CBString(pDX, IDC_DIRECTION, m_direction); + DDX_CBString(pDX, IDC_HOUSE, m_house); + DDX_Text(pDX, IDC_P1, m_flag1); + DDX_Text(pDX, IDC_P2, m_flag2); + DDX_Text(pDX, IDC_P3, m_flag3); + DDX_Text(pDX, IDC_P4, m_flag4); + DDX_CBString(pDX, IDC_STATE, m_action); + DDX_CBString(pDX, IDC_TAG, m_tag); + DDX_Text(pDX, IDC_P5, m_flag5); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CInfantrie, CDialog) + //{{AFX_MSG_MAP(CInfantrie) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CInfantrie + +BOOL CInfantrie::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // init the common (!) dialog things + int i; + CComboBox* house, *tag; + house=(CComboBox*)GetDlgItem(IDC_HOUSE); + tag=(CComboBox*)GetDlgItem(IDC_TAG); + + ListHouses(*house, FALSE); + ListTags(*tag, TRUE); + + + UpdateData(FALSE); + m_strength_ctrl.SetRange(0,256); + m_strength_ctrl.SetPos(atoi(m_strength)); + + + UpdateStrings(); + + return TRUE; +} + +void CInfantrie::OnOK() +{ + CDialog::OnOK(); + m_strength=GetText(&m_strength_ctrl); + + UpdateData(); + TruncSpace(m_tag); + m_house=TranslateHouse(m_house); + + + +} + +void CInfantrie::Init(CString house, CString strength, CString action, CString direction, CString tag, CString flag1, CString flag2, CString flag3, CString flag4, CString flag5) +{ + CIniFile& ini=Map->GetIniFile(); + + if(house=="") + { + /*m_house=*rules.sections[HOUSES].GetValue(0); + if(ini.sections.find(HOUSES)!=ini.sections.end()) + if(ini.sections[HOUSES].values.size()>0) + m_house=*ini.sections[HOUSES].GetValue(0);*/ + m_house=TranslateHouse(Map->GetHouseID(0), TRUE); + } + else + m_house=TranslateHouse(house, TRUE); + + + + m_flag1=flag1; + m_flag2=flag2; + m_flag3=flag3; + m_flag4=flag4; + m_flag5=flag5; + // m_pos=pos; + m_action=action; + m_strength=strength; + + m_tag=tag; + m_direction=direction; + +} + +void CInfantrie::UpdateStrings() +{ + SetWindowText(GetLanguageStringACP("InfCap")); + GetDlgItem(IDC_LHOUSE)->SetWindowText(GetLanguageStringACP("InfHouse")); + GetDlgItem(IDC_LDESC)->SetWindowText(GetLanguageStringACP("InfDesc")); + GetDlgItem(IDC_LSTRENGTH)->SetWindowText(GetLanguageStringACP("InfStrength")); + // GetDlgItem(IDC_LPOS)->SetWindowText(GetLanguageStringACP("InfPos")); + GetDlgItem(IDC_LSTATE)->SetWindowText(GetLanguageStringACP("InfState")); + GetDlgItem(IDC_LDIRECTION)->SetWindowText(GetLanguageStringACP("InfDirection")); + GetDlgItem(IDC_LTAG)->SetWindowText(GetLanguageStringACP("InfTag")); + GetDlgItem(IDC_LP1)->SetWindowText(GetLanguageStringACP("InfP1")); + GetDlgItem(IDC_LP2)->SetWindowText(GetLanguageStringACP("InfP2")); + GetDlgItem(IDC_LP3)->SetWindowText(GetLanguageStringACP("InfP3")); + GetDlgItem(IDC_LP4)->SetWindowText(GetLanguageStringACP("InfP4")); + GetDlgItem(IDC_LP5)->SetWindowText(GetLanguageStringACP("InfP5")); + + SetDlgItemText(IDOK, GetLanguageStringACP("OK")); + SetDlgItemText(IDCANCEL, GetLanguageStringACP("Cancel")); +} diff --git a/MissionEditor/Infantry.h b/MissionEditor/Infantry.h new file mode 100644 index 0000000..14ae9a8 --- /dev/null +++ b/MissionEditor/Infantry.h @@ -0,0 +1,79 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_INFANTRIE_H__F5A248C4_84A5_11D3_B63B_F881F458F743__INCLUDED_) +#define AFX_INFANTRIE_H__F5A248C4_84A5_11D3_B63B_F881F458F743__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Infantrie.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CInfantrie + +class CInfantrie : public CDialog +{ +// Konstruktion +public: + void UpdateStrings(); + CString m_strength; + void Init(CString house="", CString strength="256", CString action="Guard", CString direction="64", CString tag="None", CString p1="0", CString p2="-1", CString p3="0", CString p4="0", CString p5="0"); + CInfantrie(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CInfantrie) + enum { IDD = IDD_INFANTRY }; + CSliderCtrl m_strength_ctrl; + CString m_direction; + CString m_house; + CString m_flag1; + CString m_flag2; + CString m_flag3; + CString m_flag4; + CString m_action; + CString m_tag; + CString m_flag5; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CInfantrie) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CInfantrie) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_INFANTRIE_H__F5A248C4_84A5_11D3_B63B_F881F458F743__INCLUDED_ diff --git a/MissionEditor/Info.cpp b/MissionEditor/Info.cpp new file mode 100644 index 0000000..c8e19e1 --- /dev/null +++ b/MissionEditor/Info.cpp @@ -0,0 +1,129 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Info.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "Info.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CInfo + + +CInfo::CInfo(CWnd* pParent /*=NULL*/) + : CDialog(CInfo::IDD, pParent) +{ + //{{AFX_DATA_INIT(CInfo) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Elementinitialisierung ein + //}}AFX_DATA_INIT +} + + +void CInfo::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CInfo) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier DDX- und DDV-Aufrufe ein + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CInfo, CDialog) + //{{AFX_MSG_MAP(CInfo) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Zuordnungsmakros fĂ¼r Nachrichten ein + //}}AFX_MSG_MAP +// ON_EN_CHANGE(IDC_EDIT1, &CInfo::OnEnChangeEdit1) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CInfo + + + +BOOL CInfo::OnInitDialog() +{ + CDialog::OnInitDialog(); + +#ifdef YR_MODE + CStringA license = R"(FinalAlert 2: Yuri's Revenge Mission Editor +Copyright (C) 1999-2024 Electronic Arts, Inc. +Authored by Matthias Wagner + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see .)"; +#elif RA2_MODE + CStringA license = R"(FinalAlert 2 Mission Editor +Copyright (C) 1999-2024 Electronic Arts, Inc. +Authored by Matthias Wagner + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see .)"; +#else // TS_MODE + CStringA license = R"(FinalSun Mission Editor +Copyright (C) 1999-2024 Electronic Arts, Inc. +Authored by Matthias Wagner + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see .)"; +#endif + + license.Replace("\n", "\r\n"); + GetDlgItem(IDC_LICENSE_AND_COPYRIGHT)->SetWindowTextA(license); + + return TRUE; +} diff --git a/MissionEditor/Info.h b/MissionEditor/Info.h new file mode 100644 index 0000000..5d057ce --- /dev/null +++ b/MissionEditor/Info.h @@ -0,0 +1,68 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_INFO_H__3F820D60_6EB5_11D3_99E1_444553540000__INCLUDED_) +#define AFX_INFO_H__3F820D60_6EB5_11D3_99E1_444553540000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Info.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CInfo + +class CInfo : public CDialog +{ +// Konstruktion +public: + CInfo(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CInfo) + enum { IDD = IDD_INFO }; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CInfo) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CInfo) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Member-Funktionen ein + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: +// afx_msg void OnEnChangeEdit1(); + virtual BOOL OnInitDialog(); +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_INFO_H__3F820D60_6EB5_11D3_99E1_444553540000__INCLUDED_ diff --git a/MissionEditor/IniFile.cpp b/MissionEditor/IniFile.cpp new file mode 100644 index 0000000..b1b1e66 --- /dev/null +++ b/MissionEditor/IniFile.cpp @@ -0,0 +1,405 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// IniFile.cpp: Implementierung der Klasse CIniFile. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "IniFile.h" +#include +#include +#include + + + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#define new DEBUG_NEW +#endif + +using namespace std; + +bool SortDummy::operator()(const CString& x, const CString& y) const +{ + // the length is more important than spelling (numbers!!!)... + if (x.GetLength() < y.GetLength()) return true; + if (x.GetLength() == y.GetLength()) + { + if (x < y) return true; + } + + return false; + +} + +typedef map::iterator CIniI; +typedef map::iterator SI; +typedef map::iterator SII; + + +////////////////////////////////////////////////////////////////////// +// Konstruktion/Destruktion +////////////////////////////////////////////////////////////////////// + +CIniFile::CIniFile() +{ + Clear(); +} + +CIniFile::~CIniFile() +{ + sections.clear(); +} + +WORD CIniFile::LoadFile(const CString& filename, BOOL bNoSpaces) +{ + return LoadFile(std::string(filename.GetString()), bNoSpaces); +} + +WORD CIniFile::LoadFile(const std::string& filename, BOOL bNoSpaces) +{ + Clear(); + + if (filename.size() == NULL) return 1; + m_filename = filename; + + return(InsertFile(filename, NULL, bNoSpaces)); + +} + + +void CIniFile::Clear() +{ + + sections.clear(); +} + +CIniFileSection::CIniFileSection() +{ + values.clear(); + value_orig_pos.clear(); +}; + +CIniFileSection::~CIniFileSection() +{ + values.clear(); + value_orig_pos.clear(); +}; + +WORD CIniFile::InsertFile(const CString& filename, const char* Section, BOOL bNoSpaces) +{ + return InsertFile(std::string(filename.GetString()), Section, bNoSpaces); +} + +WORD CIniFile::InsertFile(const std::string& filename, const char* Section, BOOL bNoSpaces) +{ + if (filename.size() == 0) + return 1; + + fstream file; + + file.open(filename, ios::in); + if (!file.good()) + return 2; + + + //char cSec[256]; + //char cLine[4096]; + + //memset(cSec, 0, 256); + //memset(cLine, 0, 4096); + CString cSec; + std::string cLine; + + const auto npos = std::string::npos; + + while (!file.eof()) + { + std::getline(file, cLine); + + // strip to left side of newline or comment + cLine.erase(std::find_if(cLine.begin(), cLine.end(), [](const char c) { return c == '\r' || c == '\n' || c == ';'; }), cLine.end()); + + const auto openBracket = cLine.find('['); + const auto closeBracket = cLine.find(']'); + const auto equals = cLine.find('='); + + if (openBracket != npos && closeBracket != npos && openBracket < closeBracket && (equals == npos || equals > openBracket)) + { + if ((Section != nullptr) && cSec == Section) + return 0; // the section we want to insert is finished + + cSec = cLine.substr(openBracket + 1, closeBracket - openBracket - 1).c_str(); + } + else if (equals != npos && !cSec.IsEmpty()) + { + if (Section == NULL || cSec == Section) + { + // a value is set and we have a valid current section! + CString name = cLine.substr(0, equals).c_str(); + CString value = cLine.substr(equals + 1, cLine.size() - equals - 1).c_str(); + + int cuValueIndex = sections[cSec].values.size(); + + if (bNoSpaces) + { + name.Trim(); + value.Trim(); + } + + sections[cSec].values[name] = value; + sections[cSec].value_orig_pos[name] = cuValueIndex; + } + } + + } + + + + file.close(); + + return 0; +} + +const CIniFileSection* CIniFile::GetSection(std::size_t index) const +{ + if (index > sections.size() - 1) + return NULL; + + auto i = sections.cbegin(); + for (auto e = 0;e < index;e++) + i++; + + return &i->second; +} + +CIniFileSection* CIniFile::GetSection(std::size_t index) +{ + if (index > sections.size() - 1) + return NULL; + + CIniI i = sections.begin(); + for (auto e = 0;e < index;e++) + i++; + + return &i->second; +} + +const CIniFileSection* CIniFile::GetSection(const CString& section) const +{ + auto it = sections.find(section); + if (it == sections.end()) + return nullptr; + return &it->second; +} + +CIniFileSection* CIniFile::GetSection(const CString& section) +{ + auto it = sections.find(section); + if (it == sections.end()) + return nullptr; + return &it->second; +} + +const CString* CIniFileSection::GetValue(std::size_t index) const noexcept +{ + if (index > values.size() - 1) + return NULL; + + auto i = values.begin(); + for (auto e = 0;e < index;e++) + i++; + + return &i->second; +} + +CString* CIniFileSection::GetValue(std::size_t index) noexcept +{ + if (index > values.size() - 1) + return NULL; + + auto i = values.begin(); + for (auto e = 0;e < index;e++) + i++; + + return &i->second; +} + +CString CIniFileSection::GetValueByName(const CString& valueName, const CString& defaultValue) const +{ + auto it = values.find(valueName); + return (it == values.end()) ? defaultValue : it->second; +} + +const CString* CIniFile::GetSectionName(std::size_t index) const noexcept +{ + if (index > sections.size() - 1) + return NULL; + + auto i = sections.cbegin(); + for (auto e = 0; e < index; ++e) + i++; + + return &(i->first); +} + +CString& CIniFileSection::AccessValueByName(const CString& valueName) +{ + return values[valueName]; +} + +const CString* CIniFileSection::GetValueName(std::size_t index) const noexcept +{ + if (index > values.size() - 1) + return NULL; + + auto i = values.begin(); + for (auto e = 0; e < index; ++e) + i++; + + + return &(i->first); +} + +BOOL CIniFile::SaveFile(const CString& filename) const +{ + return SaveFile(std::string(filename.GetString())); +} + +BOOL CIniFile::SaveFile(const std::string& Filename) const +{ + fstream file; + + file.open(Filename, ios::out | ios::trunc); + + int i; + for (i = 0;i < sections.size();i++) + { + file << "[" << (LPCTSTR)*GetSectionName(i) << "]" << endl; + int e; + for (e = 0;e < GetSection(i)->values.size();e++) + { + file << (LPCTSTR) * (GetSection(i)->GetValueName(e)) << "=" << (LPCTSTR)*GetSection(i)->GetValue(e) << endl; + } + file << endl; + } + + file << endl; + + return TRUE; +} + + +int CIniFileSection::FindValue(CString sval) const noexcept +{ + int i; + auto it = values.cbegin(); + for (i = 0;i < values.size();i++) + { + if (sval == it->second) + return i; + it++; + } + return -1; +} + +int CIniFileSection::FindName(CString sval) const noexcept +{ + int i; + auto it = values.cbegin(); + for (i = 0;i < values.size();i++) + { + if (sval == it->first) + return i; + it++; + } + return -1; +} + +void CIniFile::DeleteLeadingSpaces(BOOL bValueNames, BOOL bValues) +{ + int i; + for (i = 0;i < sections.size();i++) + { + CIniFileSection& sec = *GetSection(i); + int e; + for (e = 0;e < sec.values.size();e++) + { + if (bValues) sec.GetValue(e)->TrimLeft(); + if (bValueNames) + { + CString value = *sec.GetValue(e); + CString name = *sec.GetValueName(e); + + sec.values.erase(name); + name.TrimLeft(); + sec.values[name] = value; + } + } + } +} + +void CIniFile::DeleteEndingSpaces(BOOL bValueNames, BOOL bValues) +{ + int i; + for (i = 0;i < sections.size();i++) + { + CIniFileSection& sec = *GetSection(i); + int e; + for (e = 0;e < sec.values.size();e++) + { + if (bValues) sec.GetValue(e)->TrimRight(); + if (bValueNames) + { + //CString& name=(CString&)*sec.GetValueName(e); + //name.TrimRight(); + CString value = *sec.GetValue(e); + CString name = *sec.GetValueName(e); + + sec.values.erase(name); + name.TrimRight(); + sec.values[name] = value; + } + } + } +} + +CString CIniFile::GetValueByName(const CString& sectionName, const CString& valueName, const CString& defaultValue) const +{ + auto section = GetSection(sectionName); + if (!section) + return defaultValue; + return section->GetValueByName(valueName, defaultValue); +} + +int CIniFileSection::GetValueOrigPos(int index) const noexcept +{ + if (index > value_orig_pos.size() - 1) + return -1; + + auto i = value_orig_pos.cbegin(); + for (int e = 0;e < index;e++) + i++; + + return i->second; +} + diff --git a/MissionEditor/IniFile.h b/MissionEditor/IniFile.h new file mode 100644 index 0000000..bc0b8b6 --- /dev/null +++ b/MissionEditor/IniFile.h @@ -0,0 +1,150 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// IniFile.h: Schnittstelle fĂ¼r die Klasse CIniFile. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_INIFILE_H__96455620_6528_11D3_99E0_DB2A1EF71411__INCLUDED_) +#define AFX_INIFILE_H__96455620_6528_11D3_99E0_DB2A1EF71411__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +#include +#include +#include +#include + + +using namespace std; + +class SortDummy +{ +public: + bool operator() (const CString&, const CString&) const; +}; + + + +class CIniFileSection +{ +public: + CIniFileSection(); + virtual ~CIniFileSection(); + + CString GetValueByName(const CString& name, const CString& defaultValue = CString()) const; + CString& AccessValueByName(const CString& name); + + auto begin() noexcept + { + return values.begin(); + } + + auto begin() const noexcept + { + return values.begin(); + } + + auto end() noexcept + { + return values.end(); + } + + auto end() const noexcept + { + return values.end(); + } + + [[deprecated("instead use iterators or for_each")]] + int GetValueOrigPos(int index) const noexcept; + + [[deprecated("instead use iterators or for_each")]] + int FindName(CString sval) const noexcept; + + [[deprecated("instead use iterators or for_each")]] + int FindValue(CString sval) const noexcept; + + [[deprecated("instead use iterators or for_each")]] + const CString* GetValueName(std::size_t index) const noexcept; + + [[deprecated("instead use iterators or for_each")]] + const CString* GetValue(std::size_t index) const noexcept; + + [[deprecated("instead use iterators or for_each")]] + CString* GetValue(std::size_t index) noexcept; + +public: + map values; + map value_orig_pos; +}; + +class CIniFile +{ +public: + void DeleteEndingSpaces(BOOL bValueNames, BOOL bValues); + void DeleteLeadingSpaces(BOOL bValueNames, BOOL bValues); + + const CString* GetSectionName(std::size_t Index) const noexcept; + const CIniFileSection* GetSection(std::size_t index) const; + CIniFileSection* GetSection(std::size_t index); + const CIniFileSection* GetSection(const CString& section) const; + CIniFileSection* GetSection(const CString& section); + CString GetValueByName(const CString& sectionName, const CString& valueName, const CString& defaultValue) const; + void Clear(); + WORD InsertFile(const CString& filename, const char* Section, BOOL bNoSpaces = FALSE); + WORD InsertFile(const std::string& filename, const char* Section, BOOL bNoSpaces = FALSE); + BOOL SaveFile(const CString& Filename) const; + BOOL SaveFile(const std::string& Filename) const; + WORD LoadFile(const CString& filename, BOOL bNoSpaces = FALSE); + WORD LoadFile(const std::string& filename, BOOL bNoSpaces = FALSE); + + + auto begin() noexcept + { + return sections.begin(); + } + + auto begin() const noexcept + { + return sections.begin(); + } + + auto end() noexcept + { + return sections.end(); + } + + auto end() const noexcept + { + return sections.end(); + } + + map sections; + CIniFile(); + virtual ~CIniFile(); + +private: + std::string m_filename; +}; + +#endif // !defined(AFX_INIFILE_H__96455620_6528_11D3_99E0_DB2A1EF71411__INCLUDED_) diff --git a/MissionEditor/InputBox.cpp b/MissionEditor/InputBox.cpp new file mode 100644 index 0000000..6ebbf6c --- /dev/null +++ b/MissionEditor/InputBox.cpp @@ -0,0 +1,119 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// InputBox.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "InputBox.h" +#include "functions.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +/* +InputBox(); + +Shows a inputbox with specified caption and text. +Returns the user input. If the user cancels, the user input is "". +*/ +CString InputBox(const char* Sentence, const char* Caption) +{ + CInputBox inp; + inp.SetCaption(Caption); + inp.SetSentence(Sentence); + char* res=(char*) inp.DoModal(); + CString cstr=res; + + return cstr; +} + +CInputBox::CInputBox(CWnd* pParent /*=NULL*/) + : CDialog(CInputBox::IDD, pParent) +{ + //{{AFX_DATA_INIT(CInputBox) + + //}}AFX_DATA_INIT +} + + +void CInputBox::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CInputBox) + + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CInputBox, CDialog) + //{{AFX_MSG_MAP(CInputBox) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + + +void CInputBox::OnOK() +{ + CString text; + GetDlgItem(IDC_VAL)->GetWindowText(text); + + if(text.GetLength()==0){EndDialog(NULL);}; + + char* str; + str=new(char[text.GetLength()]); + strcpy(str, (LPCTSTR)text); + EndDialog((int)str); +} + +void CInputBox::OnCancel() +{ + EndDialog(NULL); +} + +void CInputBox::SetCaption(CString Caption) +{ + m_Caption=Caption; +} + +void CInputBox::SetSentence(CString Sentence) +{ + m_Text=Sentence; +} + +BOOL CInputBox::OnInitDialog() +{ + CDialog::OnInitDialog(); + + SetWindowText(m_Caption); + SetDlgItemText(IDC_SENTENCE, m_Text); + + SetDlgItemText(IDOK, GetLanguageStringACP("OK")); + SetDlgItemText(IDCANCEL, GetLanguageStringACP("Cancel")); + + GetDlgItem(IDC_VAL)->SetFocus(); + + return FALSE; +} diff --git a/MissionEditor/InputBox.h b/MissionEditor/InputBox.h new file mode 100644 index 0000000..ddb6bb0 --- /dev/null +++ b/MissionEditor/InputBox.h @@ -0,0 +1,76 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_INPUTBOX_H__90BA0F00_6AD4_11D3_99E1_FA6209BA1804__INCLUDED_) +#define AFX_INPUTBOX_H__90BA0F00_6AD4_11D3_99E1_FA6209BA1804__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// InputBox.h : Header-Datei +// + +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CInputBox + +CString InputBox(const char* Sentence, const char* Caption); + +class CInputBox : public CDialog +{ +// Konstruktion +public: + void SetSentence(CString Sentence); + void SetCaption(CString Caption); + CInputBox(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CInputBox) + enum { IDD = IDD_INPUTBOX }; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CInputBox) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CInputBox) + virtual void OnOK(); + virtual void OnCancel(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + CString m_Text; + CString m_Caption; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_INPUTBOX_H__90BA0F00_6AD4_11D3_99E1_FA6209BA1804__INCLUDED_ diff --git a/MissionEditor/IsoPaintThread.cpp b/MissionEditor/IsoPaintThread.cpp new file mode 100644 index 0000000..3527a21 --- /dev/null +++ b/MissionEditor/IsoPaintThread.cpp @@ -0,0 +1,74 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// IsoPaintThread.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "IsoPaintThread.h" +#include "variables.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CIsoPaintThread + +IMPLEMENT_DYNCREATE(CIsoPaintThread, CWinThread) + +CIsoPaintThread::CIsoPaintThread() +{ +} + +CIsoPaintThread::~CIsoPaintThread() +{ +} + +BOOL CIsoPaintThread::InitInstance() +{ + // ZU ERLEDIGEN: Initialisierungen fĂ¼r jeden Thread hier durchfĂ¼hren + + while(TRUE) + { + // this worker thread just updates the main window + ((CFinalSunDlg*)theApp.GetMainWnd())->m_view.m_isoview->UpdateWindow(); + } + + return TRUE; +} + +int CIsoPaintThread::ExitInstance() +{ + // ZU ERLEDIGEN: Bereinigungen fĂ¼r jeden Thread hier durchfĂ¼hren + return CWinThread::ExitInstance(); +} + +BEGIN_MESSAGE_MAP(CIsoPaintThread, CWinThread) + //{{AFX_MSG_MAP(CIsoPaintThread) + // HINWEIS - Der Klassen-Assistent fĂ¼gt hier Zuordnungsmakros ein und entfernt diese. + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CIsoPaintThread diff --git a/MissionEditor/IsoPaintThread.h b/MissionEditor/IsoPaintThread.h new file mode 100644 index 0000000..69abef7 --- /dev/null +++ b/MissionEditor/IsoPaintThread.h @@ -0,0 +1,72 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_ISOPAINTTHREAD_H__13F04541_01CB_11D5_9C88_FB4495B57649__INCLUDED_) +#define AFX_ISOPAINTTHREAD_H__13F04541_01CB_11D5_9C88_FB4495B57649__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// IsoPaintThread.h : Header-Datei +// + + + +///////////////////////////////////////////////////////////////////////////// +// Thread CIsoPaintThread + +class CIsoPaintThread : public CWinThread +{ + DECLARE_DYNCREATE(CIsoPaintThread) +protected: + CIsoPaintThread(); // Dynamische Erstellung verwendet geschĂ¼tzten Konstruktor + +// Attribute +public: + +// Operationen +public: + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CIsoPaintThread) + public: + virtual BOOL InitInstance(); + virtual int ExitInstance(); + //}}AFX_VIRTUAL + +// Implementierung +protected: + virtual ~CIsoPaintThread(); + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CIsoPaintThread) + // HINWEIS - Der Klassen-Assistent fĂ¼gt hier Member-Funktionen ein und entfernt diese. + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_ISOPAINTTHREAD_H__13F04541_01CB_11D5_9C88_FB4495B57649__INCLUDED_ diff --git a/MissionEditor/IsoView.cpp b/MissionEditor/IsoView.cpp new file mode 100644 index 0000000..3e2830a --- /dev/null +++ b/MissionEditor/IsoView.cpp @@ -0,0 +1,6824 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* +ISOVIEW.CPP +Implementation of the isometric view. +*/ + +#include "stdafx.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +/* Includes */ +#include "FinalSun.h" +#include "IsoView.h" +#include "DynamicGraphDlg.h" +#include "infantry.h" +#include "building.h" +#include "unit.h" +#include "aircraft.h" +#include "waypointid.h" +#include "celltag.h" +#include "MyViewframe.h" +#include "inlines.h" +#include "macros.h" +#include "FinalSunDlg.h" +#include "loading.h" +#include "Structs.h" +#include "frontcliffmodifier.h" +#include "backcliffmodifier.h" +#include "LineDrawer.h" +#include "MapTool.h" +#include +#include +#include +#include "TextDrawer.h" + +/* -------- */ + +/* Externals */ +extern ACTIONDATA AD; +void GetNodeName(CString& name, int n); +/* --------- */ + +/* Overlay picture table (maximum overlay count=0xFF) */ +PICDATA* ovrlpics[0xFF][max_ovrl_img]; + +// cancel draw flag +BOOL bCancelDraw = FALSE; +BOOL bNoDraw = FALSE; + + +// this variable will be set to TRUE when the window has lost focus +// once the mouse is moved in the isoview again WITHOUT pressed button, it is set to FALSE again +BOOL bDoNotAllowScroll = FALSE; + + + +///////////////////////////////////////////////////////////////////////////// +// CIsoView + +IMPLEMENT_DYNCREATE(CIsoView, CScrollView) + +BOOL bNoThreadDraw = FALSE; +BOOL bDrawStats = TRUE; + +/*UINT PaintThreadProc( LPVOID pParam ) +{ + while(!bNoThreadDraw) + { + if(((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview!=NULL) ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->UpdateWindow(); + } + + return 0; // Thread erfolgreich ausgefĂ¼hrt +} +*/ + +class SurfaceLocker +{ +public: + SurfaceLocker(IDirectDrawSurface4* pDDS, LPRECT rect = nullptr) : + SurfaceLocker() + { + m_hasRect = rect != nullptr; + if (rect) + m_rect = *rect; + m_pDDS = pDDS; + m_ddsd.dwSize = sizeof(DDSURFACEDESC2); + m_ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; + } + + DDSURFACEDESC2* ensure_locked() + { + if (m_locked) + return &m_ddsd; + + if (m_pDDS->GetSurfaceDesc(&m_ddsd) != DD_OK) + return nullptr; + + if (m_pDDS->Lock(m_hasRect ? &m_rect : nullptr, &m_ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL) != DD_OK) + return nullptr; + + m_locked = true; + + if (!m_ddsd.lpSurface) + return nullptr; // probably does not happen in reality + + return &m_ddsd; + } + + void ensure_unlocked() + { + if (m_locked) + { + m_pDDS->Unlock(m_hasRect ? &m_rect : nullptr); + } + m_locked = false; + } + + ~SurfaceLocker() + { + ensure_unlocked(); + } + + SurfaceLocker(const SurfaceLocker& other) = delete; + SurfaceLocker& operator=(const SurfaceLocker& other) = delete; + +private: + SurfaceLocker() = default; + +private: + IDirectDrawSurface4* m_pDDS = nullptr; + DDSURFACEDESC2 m_ddsd = { 0 }; + RECT m_rect = { 0 }; + bool m_hasRect = false; + bool m_locked = false; +}; + + +CIsoView::CIsoView() +{ + srand(GetTickCount()); + m_bAltCliff = FALSE; + m_NoMove = FALSE; + b_IsLoading = FALSE; + m_viewOffset = ProjectedVec(0, 0); + dd = NULL; + dd_1 = NULL; + lpds = NULL; + lpdsBack = NULL; + lpdsBackHighRes = nullptr; + lpdsTemp = NULL; + pf = DDPIXELFORMAT{ 0 }; + line.left = 0; + line.top = 0; + line.right = 0; + line.bottom = 0; + m_menu.LoadMenu(IDR_MAPVIEW); + m_drag = FALSE; + // _map=NULL; + AD.reset(); + m_BrushSize_x = 1; + m_BrushSize_y = 1; + rscroll = FALSE; + m_zooming = false; + bThreadPainting = TRUE; + m_viewScale = Vec2(1.0f, 1.0f); + m_viewScaleControl = 1.0f; + updateFontScaled(); + //m_paintthread=new(CIsoPaintThread); + //m_paintthread->CreateThread(); + +} + +CIsoView::~CIsoView() +{ + // if(_map!=NULL) delete[] _map; + // _map=NULL; + //delete m_paintthread; + bNoThreadDraw = TRUE; +} + + +BEGIN_MESSAGE_MAP(CIsoView, CView) + //{{AFX_MSG_MAP(CIsoView) + ON_WM_SYSCOMMAND() + ON_WM_VSCROLL() + ON_WM_HSCROLL() + ON_WM_MOUSEMOVE() + ON_WM_RBUTTONUP() + ON_WM_LBUTTONDBLCLK() + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_MOVE() + ON_WM_SIZE() + ON_WM_CHAR() + ON_WM_DEADCHAR() + ON_WM_KEYDOWN() + ON_WM_KEYUP() + ON_WM_TIMER() + ON_WM_RBUTTONDOWN() + ON_WM_KILLFOCUS() + ON_WM_MOUSEWHEEL() + //}}AFX_MSG_MAP + ON_WM_MBUTTONDOWN() + ON_WM_MBUTTONUP() +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Zeichnung CIsoView + +void CIsoView::OnInitialUpdate() +{ + CView::OnInitialUpdate(); +} + + +struct CHANGEHEIGHTDATA +{ + int pos; + BOOL bNonMorpheable; + DWORD toHeight; +}; + + +DWORD WINAPI ChangeHeightThread( + LPVOID lpParameter // thread data +) +{ + CHANGEHEIGHTDATA* p = (CHANGEHEIGHTDATA*)lpParameter; + + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->ChangeTileHeight(p->pos, p->toHeight, p->bNonMorpheable); + + return 0; +} + +/* +dst must be surface data, src must be a 8 bit palette image +*/ +#ifdef NOSURFACES + +struct BlitRect +{ + short left; + short top; + short right; + short bottom; +}; + +__forceinline void BlitTerrain(void* dst, int x, int y, int dleft, int dtop, int dpitch, int dright, int dbottom, const SUBTILE& st)//BYTE* src, int swidth, int sheight) +{ + BYTE* src = st.pic; + const unsigned short swidth = st.wWidth; + const unsigned short sheight = st.wHeight; + + + if (src == NULL || dst == NULL) return; + + //x += 1; + //y += 1; + //y -= f_y; + + if (x + swidth < dleft || y + sheight < dtop) return; + if (x >= dright || y >= dbottom) return; + + + BlitRect blrect; + BlitRect srcRect; + srcRect.left = 0; + srcRect.top = 0; + srcRect.right = swidth; + srcRect.bottom = sheight; + blrect.left = x; + + + if (blrect.left < 0) + { + srcRect.left = 1 - blrect.left; + blrect.left = 1; + } + blrect.top = y; + if (blrect.top < 0) + { + srcRect.top = 1 - blrect.top; + blrect.top = 1; + } + blrect.right = (x + swidth); + if (x + swidth > dright) + { + srcRect.right = dright - x;//swidth-((x+swidth)-dright); + blrect.right = dright; + } + blrect.bottom = (y + sheight); + if (y + sheight > dbottom) + { + srcRect.bottom = dbottom - y;//sheight-((y+sheight)-dbottom); + blrect.bottom = dbottom; + } + + + short i, e; + + +#ifdef NOSURFACES_EXTRACT + int pos = 0; + if (!st.bNotExtracted) + { + for (e = srcRect.top;e < srcRect.bottom;e++) + { + short left = st.vborder[e].left; + short right = st.vborder[e].right; + + short realright = right; + //short realleft=left; + //short addx_s=0; + + if (right >= srcRect.right) right = srcRect.right - 1; + if (srcRect.left > 0) + { + pos += (realright - left + 1) * bpp; + continue; // just cancel. this area is used by object browser. saves some performance + //addx_s=srcRect.left; + //left=max(left, srcRect.left); + //left=//addx=left-srcRect.left; + } + + if (realright >= left) + { + if (/*left= srcRect.right) + { + pos += (realright - left + 1) * bpp; + continue; + } + + + void* dest = ((BYTE*)dst + (blrect.left + left) * bpp + (blrect.top + e) * dpitch); + + memcpy(dest, &st.pic[pos], bpp * (right - left + 1)); + pos += (realright - left + 1) * bpp; + } + } + } + else + +#endif + for (e = srcRect.top;e < srcRect.bottom;e++) + { + short& left = st.vborder[e].left; + short& right = st.vborder[e].right; + + auto l = max(left, srcRect.left); + auto r = min(right, static_cast(srcRect.right - 1)); + for (i = l;i <= r;i++) + { + //if (i < srcRect.left || i >= srcRect.right) + { + //dest+=bpp; + } + //else + { + + BYTE& val = src[i + e * swidth]; + if (val) + { + void* dest = ((BYTE*)dst + (blrect.left + i) * bpp + (blrect.top + e) * dpitch); + + memcpy(dest, &iPalIso[val], bpp); + } + } + } + + } + +} + + +__forceinline void BlitTerrainHalfTransp(void* dst, int x, int y, int dleft, int dtop, int dpitch, int dright, int dbottom, const SUBTILE& st)//BYTE* src, int swidth, int sheight) +{ + BYTE* src = st.pic; + const unsigned short swidth = st.wWidth; + const unsigned short sheight = st.wHeight; + + + if (src == NULL || dst == NULL) return; + + //x += 1; + //y += 1; + //y -= f_y; + + if (x + swidth < dleft || y + sheight < dtop) return; + if (x >= dright || y >= dbottom) return; + + + BlitRect blrect; + BlitRect srcRect; + srcRect.left = 0; + srcRect.top = 0; + srcRect.right = swidth; + srcRect.bottom = sheight; + blrect.left = x; + + + if (blrect.left < 0) + { + srcRect.left = 1 - blrect.left; + blrect.left = 1; + } + blrect.top = y; + if (blrect.top < 0) + { + srcRect.top = 1 - blrect.top; + blrect.top = 1; + } + blrect.right = (x + swidth); + if (x + swidth > dright) + { + srcRect.right = dright - x;//swidth-((x+swidth)-dright); + blrect.right = dright; + } + blrect.bottom = (y + sheight); + if (y + sheight > dbottom) + { + srcRect.bottom = dbottom - y;//sheight-((y+sheight)-dbottom); + blrect.bottom = dbottom; + } + + + short i, e; + + +#ifdef NOSURFACES_EXTRACT + int pos = 0; + if (!st.bNotExtracted) + { + int a = 0; + for (e = srcRect.top;e < srcRect.bottom;e += 1) + { + short left = st.vborder[e].left; + short right = st.vborder[e].right; + + short realright = right; + + if (right >= srcRect.right) right = srcRect.right - 1; + if (srcRect.left > 0) + { + pos += (realright - left + 1) * bpp; + continue; // just cancel. this area is used by object browser. saves some performance + } + + a++; + + if (realright >= left) + { + if (/*left= srcRect.right) + { + pos += (realright - left + 1) * bpp; + continue; + } + + + void* dest = ((BYTE*)dst + (blrect.left + left) * bpp + (blrect.top + e) * dpitch); + + //memcpy(dest, &st.pic[pos], bpp*(right-left+1)); + //pos+=(right-left+1)*bpp; + + for (i = left + a % 2;i <= right;i += 2) + { + if (i < srcRect.left || i >= srcRect.right) + { + //dest+=bpp; + } + else + { + + //BYTE& val=st.pic[pos+i*bpp]; + //if(val) + { + void* dest2 = (BYTE*)dest + (i - left) * bpp; //((BYTE*)dst+(blrect.left+i)*bpp+(blrect.top+e)*dpitch); + + memcpy(dest2, &st.pic[pos + (i - left) * bpp], bpp); + } + } + } + + pos += (realright - left + 1) * bpp; + } + } + } + else + +#endif + { + int a = 0; + for (e = srcRect.top;e < srcRect.bottom;e++) + { + short& left = st.vborder[e].left; + short& right = st.vborder[e].right; + + + a++; + + for (i = left + a % 2;i <= right;i += 2) + { + if (i < srcRect.left || i >= srcRect.right) + { + //dest+=bpp; + } + else + { + + BYTE& val = src[i + e * swidth]; + if (val) + { + void* dest = ((BYTE*)dst + (blrect.left + i) * bpp + (blrect.top + e) * dpitch); + + memcpy(dest, &iPalIso[val], bpp); + } + } + } + + + } + } + +} + + +const int houseColorMin = 0x10; +const int houseColorMax = 0x1f; +const int houseColorRelMax = houseColorMax - houseColorMin; + +inline void CalculateHouseColorPalette(int house_pal[houseColorRelMax + 1], const int* default_pal, const int* color = NULL) +{ + if (color) + { + if (bpp == 4) + { + for (int n = 0; n <= houseColorRelMax; ++n) + { + const int v = (houseColorRelMax - n); + auto src = reinterpret_cast(color); + auto bdest = reinterpret_cast(&house_pal[n]); + bdest[0] = src[0] * v / houseColorRelMax; + bdest[1] = src[1] * v / houseColorRelMax; + bdest[2] = src[2] * v / houseColorRelMax; + bdest[3] = src[3]; + } + } + else + { + // nowadays only 32 bit rendering should be used, so we take a shortcut here + for (int n = 0; n <= houseColorRelMax; ++n) + { + house_pal[n] = *color; + } + } + } + else + { + for (int n = 0; n <= houseColorRelMax; ++n) + { + house_pal[n] = default_pal[n + houseColorMin]; + } + } +} + + +/* +There is no need for newpal +*/ +__forceinline void BlitPic(void* dst, int x, int y, int dleft, int dtop, int dpitch, int dright, int dbottom, PICDATA& pd, int* color = NULL, int* newPal = NULL)//BYTE* src, int swidth, int sheight) +{ + ASSERT(pd.bType != PICDATA_TYPE_BMP); + + if (newPal == NULL) newPal = pd.pal; + + BYTE* src = (BYTE*)pd.pic; + int swidth = pd.wMaxWidth; + int sheight = pd.wMaxHeight; + + if (src == NULL || dst == NULL) return; + + //x += 1; + //y += 1; + //y -= f_y; + + if (x + swidth < dleft || y + sheight < dtop) return; + if (x >= dright || y >= dbottom) return; + + + RECT blrect; + RECT srcRect; + srcRect.left = 0; + srcRect.top = 0; + srcRect.right = swidth; + srcRect.bottom = sheight; + blrect.left = x; + if (blrect.left < 0) + { + srcRect.left = 1 - blrect.left; + //blrect.left=1; + } + blrect.top = y; + if (blrect.top < 0) + { + srcRect.top = 1 - blrect.top; + //blrect.top=1; + } + blrect.right = (x + swidth); + if (x + swidth > dright) + { + srcRect.right = swidth - ((x + swidth) - dright); + blrect.right = dright; + } + blrect.bottom = (y + sheight); + if (y + sheight > dbottom) + { + srcRect.bottom = sheight - ((y + sheight) - dbottom); + blrect.bottom = dbottom; + } + + + int i, e; + + // calculate a palette for given color for values 0x10 to 0x1f - we might move this outside + const int houseColorMin = 0x10; + const int houseColorMax = 0x1f; + const int houseColorRelMax = houseColorMax - houseColorMin; + int houseColors[houseColorRelMax + 1] = { 0 }; + CalculateHouseColorPalette(houseColors, newPal, color); + const BYTE* const pLighting = (bpp == 4 && pd.lighting && !pd.lighting->empty()) ? pd.lighting->data() : nullptr; + + for (e = srcRect.top;e < srcRect.bottom;e++) + { + int left = pd.vborder[e].left; + int right = pd.vborder[e].right; + + if (left < srcRect.left) + left = srcRect.left; + if (right >= srcRect.right) + right = srcRect.right - 1; + + for (i = left;i <= right;i++) + { + if (blrect.left + i < 0) + continue; + + const int spos = i + e * swidth; + BYTE val = src[spos]; + + if (val) + { + void* dest = ((BYTE*)dst + (blrect.left + i) * bpp + (blrect.top + e) * dpitch); + + if (dest >= dst) + { + int c; + if (!color || newPal != iPalUnit || val < houseColorMin || val > houseColorMax) + { + c = newPal[val]; + } + else + { + // Replace the original palette color with the house color + ASSERT(val >= houseColorMin && val <= houseColorMax); + const int v = (val - houseColorMin); + c = houseColors[v]; + } + if (pLighting) + { + // bpp == 4 + ASSERT(bpp == 4); + int l = pLighting[spos]; + BYTE* bc = reinterpret_cast(&c); + for (int i = 0; i < 4; ++i) + bc[i] = min(255, bc[i] * (200 + l * 300 / 255) / 255); // game seems to overbrighten and have a lot of ambient - if you change this, also change Loading.cpp shp lighting value so that shp light stays at 1.0 + //bc[i] = min(255, bc[i] * (0 + l * (255 - 0) / 255) / 255); + } + memcpy(dest, &c, bpp); + } + } + } + } +} + +__forceinline void BlitPicHalfTransp(void* dst, int x, int y, int dleft, int dtop, int dpitch, int dright, int dbottom, PICDATA& pd, int* color = NULL, int* newPal = NULL)//BYTE* src, int swidth, int sheight) +{ + ASSERT(pd.bType != PICDATA_TYPE_BMP); + + if (newPal == NULL) newPal = pd.pal; + + BYTE* src = (BYTE*)pd.pic; + int swidth = pd.wMaxWidth; + int sheight = pd.wMaxHeight; + + if (src == NULL || dst == NULL) return; + + //x += 1; + //y += 1; + //y -= f_y; + + if (x + swidth < dleft || y + sheight < dtop) return; + if (x >= dright || y >= dbottom) return; + + + RECT blrect; + RECT srcRect; + srcRect.left = 0; + srcRect.top = 0; + srcRect.right = swidth; + srcRect.bottom = sheight; + blrect.left = x; + if (blrect.left < 0) + { + srcRect.left = 1 - blrect.left; + //blrect.left=1; + } + blrect.top = y; + if (blrect.top < 0) + { + srcRect.top = 1 - blrect.top; + //blrect.top=1; + } + blrect.right = (x + swidth); + if (x + swidth > dright) + { + srcRect.right = swidth - ((x + swidth) - dright); + blrect.right = dright; + } + blrect.bottom = (y + sheight); + if (y + sheight > dbottom) + { + srcRect.bottom = sheight - ((y + sheight) - dbottom); + blrect.bottom = dbottom; + } + + + int i, e; + + + + + for (e = srcRect.top;e < srcRect.bottom;e++) + { + + + int left = pd.vborder[e].left; + int right = pd.vborder[e].right; + if (left < srcRect.left) left = srcRect.left; + if (right >= srcRect.right) right = srcRect.right - 1; + + int a = e % 2 + left % 2; + + for (i = left + a;i <= right;i += 2) + { + //a++; + + if (blrect.left + i < 0) continue; + //if(a%2) continue; + + BYTE& val = src[i + e * swidth]; + //0x10-0x1f, + if (val) + { + void* dest = ((BYTE*)dst + (blrect.left + i) * bpp + (blrect.top + e) * dpitch); + //*dest=newPal[val]; + if (dest >= dst) + { + if (!color || newPal != iPalUnit || val < 0x10 || val>0x1f) + { + memcpy(dest, &newPal[val], bpp); + } + else + { + //int col=0; + memcpy(dest, color, bpp); + } + } + } + } + } +} +#endif + + + + +///////////////////////////////////////////////////////////////////////////// +// Diagnose CIsoView + +#ifdef _DEBUG +void CIsoView::AssertValid() const +{ + CView::AssertValid(); +} + +void CIsoView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} +#endif //_DEBUG + +/////////////updateFontScaled//////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CIsoView + +void CIsoView::updateFontScaled() +{ + auto dc = CDC::FromHandle(::GetDC(NULL)); + m_fontDefaultHeight = -MulDiv(12, dc->GetDeviceCaps(LOGPIXELSY), 72); + m_Font9Height = -MulDiv(9, dc->GetDeviceCaps(LOGPIXELSY), 72); + + if (dd) + { + m_textDefault.reset(new TextDrawer(dd, m_fontDefaultHeight, RGB(0,0,0), RGB(255, 255, 255))); + m_text9.reset(new TextDrawer(dd, m_Font9Height, RGB(0, 0, 0), RGB(255, 255, 255))); + m_textScaled.reset(new TextDrawer(dd, m_fontDefaultHeight / m_viewScale.y, RGB(0, 0, 0), RGB(255, 255, 255))); + m_text9Scaled.reset(new TextDrawer(dd, m_Font9Height / m_viewScale.y, RGB(0, 0, 0), RGB(255, 255, 255))); + m_textBlue.reset(new TextDrawer(dd, m_fontDefaultHeight, RGB(0, 0, 255), RGB(255, 255, 255))); + m_textBlueScaled.reset(new TextDrawer(dd, m_fontDefaultHeight / m_viewScale.y, RGB(0, 0, 255), RGB(255, 255, 255))); + m_textBlue9.reset(new TextDrawer(dd, m_Font9Height, RGB(0, 0, 255), RGB(255, 255, 255))); + m_textBlue9Scaled.reset(new TextDrawer(dd, m_Font9Height / m_viewScale.y, RGB(0, 0, 255), RGB(255, 255, 255))); + } +} + +BOOL CIsoView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) +{ + + BOOL r = CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext); + + this->SetScrollRange(SB_HORZ, 0, 1, TRUE); + this->SetScrollRange(SB_VERT, 0, 1, TRUE); + + // AfxBeginThread(PaintThreadProc, 0, 0, 0xFFFF); + + return r; +} + +void CIsoView::OnSysCommand(UINT nID, LPARAM lParam) +{ + // TODO: Code fĂ¼r die Behandlungsroutine fĂ¼r Nachrichten hier einfĂ¼gen und/oder Standard aufrufen + if (nID == SC_CLOSE) + { + // ok now just hide the window + ShowWindow(SW_HIDE); + return; + } + + CView::OnSysCommand(nID, lParam); +} + +inline int GetScrPos(CWnd* pOwner, UINT nSB, UINT nSBCode, UINT& nPos) +{ + SCROLLINFO scr; + scr.cbSize = sizeof(SCROLLINFO); + scr.fMask = SIF_ALL; + + pOwner->GetScrollInfo(nSB, &scr); + + switch (nSBCode) + { + case SB_LEFT: + { + nPos = scr.nMin; + break; + } + case SB_RIGHT: + { + nPos = scr.nMax; + break; + } + case SB_THUMBTRACK: + case SB_THUMBPOSITION: + { + break; + } + case SB_LINELEFT: + { + nPos = scr.nPos - 1; + break; + } + case SB_LINERIGHT: + { + nPos = scr.nPos + 1; + break; + } + case SB_PAGELEFT: + { + nPos = scr.nPos - 5; + break; + } + case SB_PAGERIGHT: + { + nPos = scr.nPos + 5; + break; + } + } + + return nPos; + +} + +void CIsoView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) +{ + if (nSBCode == SB_ENDSCROLL || nSBCode == SB_THUMBTRACK) return; + + + nPos = GetScrPos(this, SB_VERT, nSBCode, nPos); + + this->SetScrollPos(SB_VERT, nPos, TRUE); + + m_viewOffset.y = (nPos + Map->GetWidth() / 2 - 4) * f_y; + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + CMyViewFrame& dlg = *(CMyViewFrame*)owner; + dlg.m_minimap.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); +} + +void CIsoView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) +{ + if (nSBCode == SB_ENDSCROLL || nSBCode == SB_THUMBTRACK) return; + + + + nPos = GetScrPos(this, SB_HORZ, nSBCode, nPos); + + RECT r; + GetWindowRect(&r); + m_viewOffset.x = (nPos + Map->GetHeight() / 2 - 1) * f_x; + + this->SetScrollPos(SB_HORZ, nPos, TRUE); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + CMyViewFrame& dlg = *(CMyViewFrame*)owner; + dlg.m_minimap.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); +} + +/* +This function is called when any data has been changed in another dialog. +It is used to initialize and update the dialog. +*/ +void CIsoView::UpdateDialog(BOOL bRepos) +{ + OutputDebugString("Isoview updated\n"); + + UpdateOverlayPictures(); + + + if (bRepos && Map->GetIsoSize() != 0) + { + m_viewScale = Vec2(1.0f, 1.0f); + m_viewScaleControl = 1.0f; + auto r = GetScaledDisplayRect(); + UpdateScrollRanges(); + SetScroll((Map->GetIsoSize() / 2 - r.right / f_x / 2) * f_x, (Map->GetIsoSize() / 2 - r.bottom / f_y / 2) * f_y); + } + + RedrawWindow(NULL, NULL, RDW_INVALIDATE); + +} + +void CIsoView::UpdateScrollRanges() +{ + auto r = GetScaledDisplayRect(); + SetScrollRange(SB_HORZ, 0, Map->GetWidth() - r.right / f_x + 4, TRUE); + SetScrollRange(SB_VERT, 0, Map->GetHeight() - r.bottom / f_y + 6, TRUE); +} + +BOOL CIsoView::PreCreateWindow(CREATESTRUCT& cs) +{ + // we overwrite that, because in debug version its necessary that a view is a child window! + + // save the old style and let CView::PreCreateWindow() think we are using a child window, then restore old style. + int ostyle = cs.style; + cs.style |= WS_CHILD | WS_VSCROLL | WS_HSCROLL; + + BOOL bres = CView::PreCreateWindow(cs); + cs.style = ostyle; + + return bres; + +} + + +void CIsoView::OnMouseMove(UINT nFlags, CPoint point) +{ + if (b_IsLoading) return; + + static BOOL isMoving = FALSE; + + CIniFile& ini = Map->GetIniFile(); + + cur_x_mouse = point.x; + cur_y_mouse = point.y; + + if (!(nFlags & MK_RBUTTON)) bDoNotAllowScroll = FALSE; + + if (rscroll) + { + if (!(nFlags & MK_RBUTTON)) + { + ReleaseCapture(); + KillTimer(11); + rscroll = FALSE; + ShowCursor(TRUE); + + CMyViewFrame& dlg = *(CMyViewFrame*)owner; + dlg.m_minimap.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + } + else + { + + isMoving = FALSE; + return; + } + } + + if (!bDoNotAllowScroll && (nFlags & MK_RBUTTON) && !rscroll) // check if scroll should start + { + if (abs(point.x - rclick_x) > 2 || abs(point.y - rclick_y) > 2) + { + // yes, begin scrolling! + + rscroll = TRUE; + SetTimer(11, 25, NULL); + SetCapture(); + //while(ShowCursor(FALSE)>0); + isMoving = FALSE; + return; + } + } + + if ((nFlags & MK_MBUTTON) == 0) + m_zooming = false; + + if (!bDoNotAllowScroll && m_zooming) + { + if ((nFlags & MK_MBUTTON) == MK_MBUTTON) + { + auto diff = point - m_MButtonMoveZooming; + m_MButtonMoveZooming = point; + Zoom(m_MButtonDown, -diff.cy / 1000.0f); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + return; + } + } + + m_moved = TRUE; + + if (b_IsLoading == TRUE) return; + if (Map->GetIsoSize() == 0 || isMoving == TRUE || m_zooming) return; + + isMoving = TRUE; + + // SetError(TranslateStringACP("Ready")); + + RECT r; + //GetClientRect(&r); + //ClientToScreen(&r); + GetWindowRect(&r); + + const auto viewOffsetWR = m_viewOffset + ProjectedVec(r.left, r.top); + const auto projCoords = GetProjectedCoordinatesFromClientCoordinates(point); + const MapCoords mapCoords = GetMapCoordinatesFromClientCoordinates(point, (nFlags & MK_CONTROL) == MK_CONTROL); + m_cellCursor = MapCoords(-1, -1); + const int x = mapCoords.x; // compat + const int y = mapCoords.y; + + int mapwidth = Map->GetWidth(); + int mapheight = Map->GetHeight(); + + BOOL bOutside = FALSE; + + if (AD.mode != ACTIONMODE_COPY && AD.mode != ACTIONMODE_PASTE) + { + if (x < 1 || y < 1 || x + ymapwidth + mapheight * 2 || (y + 1 > mapwidth && x - 1 < y - mapwidth) || (x + 1 > mapwidth && y + mapwidth - 1 < x)) + { + isMoving = FALSE; + return; + } + } + else + { + if (x < 1 || y < 1 || x >= mapwidth + mapheight - 1 || y >= mapwidth + mapheight - 1) + { + bOutside = TRUE; + if (AD.mode == ACTIONMODE_COPY || AD.mode == ACTIONMODE_PASTE) + { + isMoving = FALSE; + return; + } + } + } + + + + if (lpdsBack) + // reset back buffer to last DrawMap() + lpdsBack->BltFast(0, 0, lpdsTemp, NULL, DDBLTFAST_WAIT); + //lpdsBack->Blt(NULL, lpdsTemp, NULL, 0, 0); + + //int cell_x = x; + //int cell_y = y; + + { + // Preview rendering + if (AD.mode == ACTIONMODE_SETTILE && !((nFlags & MK_LBUTTON) && !(nFlags & MK_CONTROL) && (nFlags & MK_SHIFT))) + { + // No placement, just preview + + bCancelDraw = TRUE; + + int i, e, f, n; + int p = 0; + //FIELDDATA oldData[36][36][10][10]; + int width = (*tiledata)[AD.type].cx; + int height = (*tiledata)[AD.type].cy; + int pos = x - width + 1 + (y - height + 1) * Map->GetIsoSize(); + int startheight = Map->GetHeightAt(x + y * Map->GetIsoSize()) + AD.z_data; + int ground = (Map->GetFielddataAt(x + y * Map->GetIsoSize()))->wGround; + if (ground == 0xFFFF) ground = 0; + startheight -= (*tiledata)[ground].tiles[Map->GetFielddataAt(x + y * Map->GetIsoSize())->bSubTile].bZHeight; + TILEDATA td = (*tiledata)[AD.type]; + + Map->TakeSnapshot(TRUE, x - width - 4, y - height - 4, x - width + m_BrushSize_x * width + 7, y - height + m_BrushSize_y * height + 7); + int cur_pos = pos; + int isosize = Map->GetIsoSize(); + int height_add = height * isosize; + char c[50]; + itoa(AD.data, c, 10); + for (f = 0;f < m_BrushSize_x;f++) + { + for (n = 0;n < m_BrushSize_y;n++) + { + + int tile = AD.type; + + if (AD.data == 1) + { + int n = rand() * 5 / RAND_MAX; + tile += n; + } + + + + cur_pos = pos + f * width + n * height_add; + p = 0; + for (i = 0;i < td.cx;i++) + { + for (e = 0;e < td.cy;e++) + { + if (x - width + 1 + f * width + i >= Map->GetIsoSize() || + y - height + 1 + n * height + e >= Map->GetIsoSize()) + { + } + else + if (td.tiles[p].pic != NULL) + { + int mypos = cur_pos + i + e * isosize; + + Map->SetHeightAt(mypos, startheight + td.tiles[p].bZHeight); + Map->SetTileAt(mypos, tile, p); + + + + } + p++; + + } + } + + + } + } + + if (!((nFlags & MK_CONTROL) && (nFlags & MK_SHIFT))) + { + if (!theApp.m_Options.bDisableAutoShore) Map->CreateShore(x - width - 2, y - height - 2, x - width + td.cx * m_BrushSize_x + 5, y - height + td.cy * m_BrushSize_y + 5, FALSE); + + for (f = 0;f < m_BrushSize_x;f++) + { + for (n = 0;n < m_BrushSize_y;n++) + { + cur_pos = pos + f * width + n * height_add; + p = 0; + for (i = -1;i < td.cx + 1;i++) + { + for (e = -1;e < td.cy + 1;e++) + { + Map->SmoothAllAt(cur_pos + i + (e)*isosize); + } + } + + + } + } + } + + + + bCancelDraw = FALSE; + DrawMap(); + + + Map->Undo(); + + m_drag = FALSE; + + } + else if (m_drag && AD.mode == ACTIONMODE_CLIFFFRONT) + { + RECT affect; + if (m_mapx < x) affect.left = m_mapx - 2; else affect.left = x - 2; + if (m_mapx < x) affect.right = x + 2; else affect.right = m_mapx + 2; + if (m_mapy < y) affect.top = m_mapy - 2; else affect.top = y - 2; + if (m_mapy < y) affect.bottom = y + 2; else affect.bottom = m_mapy + 2; + + //Map->TakeSnapshot(); + Map->TakeSnapshot(TRUE, affect.left, affect.top, affect.right, affect.bottom); + CFrontCliffModifier f; + BOOL bAlt = FALSE; + if (Map->GetTheater() == THEATER3 && m_bAltCliff) + bAlt = TRUE; + f.PlaceCliff(m_mapx, m_mapy, x, y, bAlt); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + //Map->TakeSnapshot(); + Map->TakeSnapshot(TRUE, affect.left, affect.top, affect.right, affect.bottom); + Map->Undo(); + Map->Undo(); + } + else if (m_drag && AD.mode == ACTIONMODE_CLIFFBACK) + { + RECT affect; + if (m_mapx < x) affect.left = m_mapx - 2; else affect.left = x - 2; + if (m_mapx < x) affect.right = x + 2; else affect.right = m_mapx + 2; + if (m_mapy < y) affect.top = m_mapy - 2; else affect.top = y - 2; + if (m_mapy < y) affect.bottom = y + 2; else affect.bottom = m_mapy + 2; + + //Map->TakeSnapshot(); + Map->TakeSnapshot(TRUE, affect.left, affect.top, affect.right, affect.bottom); + CBackCliffModifier f; + BOOL bAlt = FALSE; + if (Map->GetTheater() == THEATER3 && m_bAltCliff) + bAlt = TRUE; + f.PlaceCliff(m_mapx, m_mapy, x, y); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + //Map->TakeSnapshot(); + Map->TakeSnapshot(TRUE, affect.left, affect.top, affect.right, affect.bottom); + Map->Undo(); + Map->Undo(); + } + else if (AD.mode == ACTIONMODE_COPY && m_drag) + { + last_succeeded_operation = 80301; //bugtracing once more + + int x1, x2, y1, y2; + if (m_mapx < x) + { + x1 = m_mapx; + x2 = x; + } + else + { + x1 = x; + x2 = m_mapx; + } + if (m_mapy < y) + { + y1 = m_mapy; + y2 = y; + } + else + { + y1 = y; + y2 = m_mapy; + } + + DDSURFACEDESC2 ddsd; + ZeroMemory(&ddsd, sizeof(ddsd)); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; + + lpdsBack->GetSurfaceDesc(&ddsd); + + + lpdsBack->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL); + + int i, e; + int isosize = Map->GetIsoSize(); + for (i = 0;i < x2 - x1 + 1;i++) + { + for (e = 0;e < y2 - y1 + 1;e++) + { + last_succeeded_operation = 80302; + int x_s = x1 + i; + int y_s = y1 + e; + + if (x_s < 0 || y_s < 0 || x_s >= isosize || y_s >= isosize) continue; + + if (theApp.m_Options.bFlat) ToPhys(&x_s, &y_s); else ToPhys3d(&x_s, &y_s); + x_s -= m_viewOffset.x; + y_s -= m_viewOffset.y; + + last_succeeded_operation = 80305; + DrawCell(ddsd.lpSurface, ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch, x_s, y_s, 1, 1, m_color_converter->GetColor(255, 0, 0)); + last_succeeded_operation = 80303; + } + } + + lpdsBack->Unlock(NULL); + + BlitBackbufferToHighRes(); + RenderUIOverlay(); + FlipHighResBuffer(); + last_succeeded_operation = 80304; + } + else if (AD.mode == ACTIONMODE_PASTE) + { + Map->TakeSnapshot(); + Map->Paste(x, y, AD.z_data); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + Map->Undo(); + } + else if ((AD.mode == ACTIONMODE_PLACE || AD.mode == ACTIONMODE_RANDOMTERRAIN) && (nFlags & ~MK_CONTROL) == 0 && AD.type != 7 && (AD.type != 6 || (AD.type == 6 && ((AD.data >= 30 && AD.data <= 33) || AD.data == 2 || AD.data == 3)))) // everything placing but not overlay! + { + FIELDDATA oldData[32][32]; + INFANTRY infData[SUBPOS_COUNT][32][32]; + int i, e; + + //if(AD.type!=1 || Map->GetInfantryCountAt(x+y*Map->GetIsoSize())==0) + { + for (i = 0;i < 32;i++) + { + for (e = 0;e < 32;e++) + { + oldData[i][e] = *Map->GetFielddataAt(i + x + (e + y) * Map->GetIsoSize()); + int z; + for (z = 0;z < SUBPOS_COUNT;z++) + if (oldData[i][e].infantry[z] > -1) + Map->GetInfantryData(oldData[i][e].infantry[z], &infData[z][i][e]); + } + } + + PlaceCurrentObjectAt(x, y); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + for (i = 0;i < 32;i++) + { + for (e = 0;e < 32;e++) + { + DWORD dwPos = i + x + (e + y) * Map->GetIsoSize(); + FIELDDATA cur_field; + cur_field = *Map->GetFielddataAt(dwPos); + + if (cur_field.aircraft != oldData[i][e].aircraft) + Map->DeleteAircraft(cur_field.aircraft); + int z; + for (z = 0;z < SUBPOS_COUNT;z++) + if (cur_field.infantry[z] != oldData[i][e].infantry[z]) + { + Map->DeleteInfantry(cur_field.infantry[z]); + } + + if (cur_field.node.index != oldData[i][e].node.index) + { + CString house; + int id = Map->GetNodeAt(dwPos, house); + Map->DeleteNode(house, id); + } + if (cur_field.structure != oldData[i][e].structure) + Map->DeleteStructure(cur_field.structure); + if (cur_field.terrain != oldData[i][e].terrain) + Map->DeleteTerrain(cur_field.terrain); +#ifdef SMUDGE_SUPP + if (cur_field.smudge != oldData[i][e].smudge) + Map->DeleteSmudge(cur_field.smudge); +#endif + if (cur_field.unit != oldData[i][e].unit) + Map->DeleteUnit(cur_field.unit); + + if (cur_field.overlay != oldData[i][e].overlay) + Map->SetOverlayAt(dwPos, oldData[i][e].overlay); + if (cur_field.overlaydata != oldData[i][e].overlaydata) + Map->SetOverlayDataAt(dwPos, oldData[i][e].overlaydata); + + Map->SetFielddataAt(dwPos, &oldData[i][e]); + } + } + } + //else + // RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + } + else + { + + SurfaceLocker locker(lpdsBack); + auto desc = locker.ensure_locked(); + if (desc) + DrawCellCursor(mapCoords, *desc); + m_cellCursor = mapCoords; + //RedrawWindow(NULL, NULL, RDW_INVALIDATE); + locker.ensure_unlocked(); + + BlitBackbufferToHighRes(); + RenderUIOverlay(); + FlipHighResBuffer(); + } + } + + + + + + + // display the coordinates + char c[50]; + CString cap; + itoa(x, c, 10); + cap += c; + cap += " / "; + itoa(y, c, 10); + cap += c; + cap += " - "; + itoa(Map->GetHeightAt(x + y * Map->GetIsoSize()), c, 10); + cap += c; + + CStatusBarCtrl& stat = ((CMyViewFrame*)owner)->m_statbar.GetStatusBarCtrl(); + stat.SetText(cap, 1, 0); + + + // drag + if (m_drag && AD.mode == 0) + { + RedrawWindow(NULL, NULL, RDW_INVALIDATE); + + CPaintDC dc(this); + dc.SetROP2(R2_NOT); + + const auto renderOffset = CPoint(f_x / 2 / m_viewScale.x, f_y / 2 / m_viewScale.y); + const auto from = GetClientCoordinates(MapCoords(m_mapx, m_mapy)) + renderOffset; + const auto to = GetClientCoordinates(mapCoords) + renderOffset; + + dc.MoveTo(from.x, from.y); + dc.LineTo(to.x, to.y); + } + else if (AD.mode == ACTIONMODE_SETTILE && (nFlags & MK_LBUTTON) && ((nFlags & MK_SHIFT) || Map->hasLat(AD.type)) && !(nFlags & MK_CONTROL)) + { + // Sound(SOUND_LAYDOWNTILE); // too many sounds + + PlaceTile(x, y, nFlags); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + isMoving = FALSE; + return; + } + else if ((nFlags & MK_LBUTTON) && (nFlags & MK_SHIFT) && AD.mode == ACTIONMODE_HEIGHTEN) + { + OnLButtonDown(nFlags, point); + isMoving = FALSE; + return; + } + else if ((nFlags & MK_LBUTTON) && (nFlags & MK_SHIFT) && AD.mode == ACTIONMODE_LOWER) + { + OnLButtonDown(nFlags, point); + isMoving = FALSE; + return; + } + + else if ((nFlags == MK_LBUTTON) && AD.mode == ACTIONMODE_FLATTENGROUND) + { + m_TileChangeCount = 0; + + // if(abs(m_FlattenLastX-x)<2 && abs(m_FlattenLastY-y)<2) //ReachableFrom(x+y*Map->GetIsoSize(), m_mapx+m_mapy*Map->GetIsoSize())) + int ground = Map->GetFielddataAt(x + (y)*Map->GetIsoSize())->wGround; + if (ground == 0xFFFF) ground = 0; + + //if((*tiledata)[ground].bMorphable) + { + + int left = -m_BrushSize_x / 2; + int right = m_BrushSize_x / 2 + 1; + int top = -m_BrushSize_y / 2; + int bottom = m_BrushSize_y / 2 + 1; + + BOOL doNotSave = FALSE; + int n, m; + int isosize = Map->GetIsoSize(); + + for (m = left;m < right;m++) + { + for (n = top;n < bottom;n++) + { + int pos = x + m + (y + n) * isosize; + + int ground = Map->GetFielddataAt(pos)->wGround; + if (ground == 0xFFFF) ground = 0; + /*int ground1=Map->GetFielddataAt(pos-m)->wGround; + if(ground1==0xFFFF) ground=0; + int ground2=Map->GetFielddataAt(pos-n*isosize)->wGround; + if(ground2==0xFFFF) ground=0;*/ + + + + if (!(*tiledata)[ground].bMorphable) + { + + { + if (n <= 0 /*&& !(*tiledata)[ground1].bMorphable*/) top = n + 1; + if (m <= 0 /*&& !(*tiledata)[ground2].bMorphable*/) left = m + 1; + if (n > 0 /*&& !(*tiledata)[ground1].bMorphable*/) bottom = n; + if (m > 0 /*&& !(*tiledata)[ground2].bMorphable*/) right = m; + } + + } + + if (n < top) + { + m = left; + n = top; + } + if (m < left) + { + n = top; + m = left; + } + } + } + + m_funcRect.left = x; + m_funcRect.top = y; + m_funcRect.bottom = y; + m_funcRect.right = x; + + for (m = left;m < right;m++) + { + for (n = top;n < bottom;n++) + { + int ground = Map->GetFielddataAt(x + m + (y + n) * Map->GetIsoSize())->wGround; + if (ground == 0xFFFF) ground = 0; + + + + if ((*tiledata)[ground].bMorphable) + { + int i; + int max = isosize * isosize; + for (i = 0;i < max;i++) + Map->SetReserved(i, 0); + + + // do not make any slopes yet, we do this once we´re finished with the whole area! + // helps to speed up performance! + ChangeTileHeight(x + m + (y + n) * isosize, m_FlattenHeight, FALSE, FALSE, TRUE); + + + + } + else + { + if (n == 0 && m == 0) + doNotSave = TRUE; + + + } + + } + + } + + /* + Some trick for improving performance is using the m_funcRect parameter to get + the area that any ChangeTileHeight() calls affected. + */ + ASSERT(m_funcRect.left <= m_funcRect.right); + ASSERT(m_funcRect.top <= m_funcRect.bottom); + for (m = m_funcRect.left - 1;m <= m_funcRect.right + 1;m++) + for (n = m_funcRect.top - 1;n <= m_funcRect.bottom + 1;n++) + Map->CreateSlopesAt(m + n * isosize); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + if (!doNotSave) + { + m_FlattenLastX = x; + m_FlattenLastY = y; + } + } + } + else if ((nFlags & MK_LBUTTON) && (nFlags & MK_SHIFT) && AD.mode == ACTIONMODE_HEIGHTENTILE) + { + OnLButtonDown(nFlags, point); + } + else if ((nFlags & MK_LBUTTON) && (nFlags & MK_SHIFT) && AD.mode == ACTIONMODE_LOWERTILE) + { + OnLButtonDown(nFlags, point); + } + else if ((nFlags == MK_LBUTTON) && AD.mode == ACTIONMODE_WAYPOINT) // waypoints + { + if (AD.type == 1) + { + //delete waypoint + int w = Map->GetWaypointAt(x + y * Map->GetIsoSize()); + if (w < 0) + { + isMoving = FALSE; + return; + } + + Map->DeleteWaypoint(w); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (AD.type == 0) + { + int n = Map->GetWaypointAt(x + y * Map->GetIsoSize()); + if (n >= 0) + { + isMoving = FALSE; + return; + } + + Map->AddWaypoint("", x + y * Map->GetIsoSize()); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (AD.type >= 3) + { + int n = Map->GetWaypointAt(x + y * Map->GetIsoSize()); + if (n >= 0) + { + isMoving = FALSE; + return; + } + + char c[50]; + int max = AD.type - 3; + + // MW April 8th: place waypoints before selected one if they are not there! + // makes the user aware that he is doing something he should not do. + // he should not skip starting locations + // this logic is here to make sure there are no random starting points. + // I do not want to change this when saving the map, as triggers may rely on the + // actual starting position! + int i; + int e; + int notfound = -1; + for (e = 0;e < max;e++) + { + BOOL bFound = FALSE; + + for (i = 0;i < Map->GetWaypointCount();i++) + { + CString id; + DWORD pos; + Map->GetWaypointData(i, &id, &pos); + if (atoi(id) == e) bFound = TRUE; + if (bFound) break; + } + if (!bFound) + { + notfound = e; + break; + } + } + + if (notfound >= 0) max = notfound; + + AD.type = 3 + max; + + itoa(max, c, 10); + + if (!Map->IsMultiplayer()) + { + Map->AddWaypoint("99", x + (y + 1) * Map->GetIsoSize()); + Map->AddWaypoint("98", x + (y)*Map->GetIsoSize()); + } + else + { + Map->AddWaypoint(c, x + y * Map->GetIsoSize()); + } + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + + } + else if ((nFlags == MK_LBUTTON) && AD.mode == ACTIONMODE_CELLTAG) // celltags + { + if (AD.type == 1) + { + int n = Map->GetCelltagAt(x + y * Map->GetIsoSize()); + if (n < 0) + { + isMoving = FALSE; + return; + } + Map->DeleteCelltag(n); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (AD.type == 4) + { + Map->AddCelltag(AD.data_s, x + y * Map->GetIsoSize()); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + } + else if ((nFlags == MK_LBUTTON) && AD.mode == ACTIONMODE_NODE) // nodes + { + if (AD.type == 1) // create node, delete building + { + int n = Map->GetStructureAt(x + y * Map->GetIsoSize()); + if (n < 0) + { + isMoving = FALSE; + return; + } + + STDOBJECTDATA sod; + Map->GetStdStructureData(n, &sod); + + CString tmp; + if (Map->GetNodeAt(atoi(sod.x) + atoi(sod.y) * Map->GetIsoSize(), tmp) >= 0) + { + SetError("You cannot place a node on another node"); + { + isMoving = FALSE; + return; + }; + } + + Map->DeleteStructure(n); + + NODE node; + node.x = sod.x; + node.y = sod.y; + node.house = sod.house; + node.type = sod.type; + + Map->AddNode(&node, 0); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + } + else if (AD.type == 0) // create node, don´t delete building + { + int n = Map->GetStructureAt(x + y * Map->GetIsoSize()); + if (n < 0) + { + isMoving = FALSE; + return; + } + + STDOBJECTDATA sod; + Map->GetStdStructureData(n, &sod); + + CString tmp; + if (Map->GetNodeAt(atoi(sod.x) + atoi(sod.y) * Map->GetIsoSize(), tmp) >= 0) + { + SetError("You cannot place a node on another node"); + { + isMoving = FALSE; + return; + }; + } + + NODE node; + node.x = sod.x; + node.y = sod.y; + node.type = sod.type; + node.house = sod.house; + + Map->AddNode(&node, 0); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + } + else if (AD.type == 2) // delete node + { + CString owner; + int n = Map->GetNodeAt(x + y * Map->GetIsoSize(), owner); + if (n < 0) + { + isMoving = FALSE; + return; + } + Map->DeleteNode(owner, n); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + } + } + else if ((nFlags == MK_LBUTTON) && AD.mode == ACTIONMODE_ERASEFIELD) + { + int h; + DWORD dwPos = x + y * Map->GetIsoSize(); + h = Map->GetInfantryAt(dwPos); + if (h > -1) + { + Map->DeleteInfantry(h); + } + + h = Map->GetUnitAt(dwPos); + if (h > -1) + { + Map->DeleteUnit(h); + } + + h = Map->GetStructureAt(dwPos); + if (h > -1) + { + Map->DeleteStructure(h); + } + + h = Map->GetAirAt(dwPos); + if (h > -1) + { + Map->DeleteAircraft(h); + } + + h = Map->GetTerrainAt(dwPos); + if (h > -1) + { + Map->DeleteTerrain(h); + } + +#ifdef SMUDGE_SUPP + const FIELDDATA& fd = *Map->GetFielddataAt(dwPos); + h = fd.smudge; + if (h > -1) + { + Map->DeleteSmudge(h); + } +#endif + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + } + else if (AD.mode == ACTIONMODE_MAPTOOL) + { + if (AD.tool) + AD.tool->onMouseMove(projCoords, mapCoords, MapToolMouseFlagsFromWin32(nFlags)); + } + else if ((nFlags & MK_LBUTTON) == MK_LBUTTON && (AD.mode == ACTIONMODE_PLACE || AD.mode == ACTIONMODE_RANDOMTERRAIN)) + { + // ADD OBJECTS + + if (AD.mode == ACTIONMODE_PLACE && AD.type == 6) Map->TakeSnapshot(); + + if (AD.mode == ACTIONMODE_PLACE && AD.type == 6 && AD.data == 5) // bridges + { + + + // calculate the x and y value... + int x = mapCoords.x; + int y = mapCoords.y; + + if (abs(x - m_mapx) >= abs(y - m_mapy)) + { + // it´s from bottom left to top right + y = m_mapy; + } + else + { + // from bottom right to top left + x = m_mapx; + } + + // draw a line + + int px1, py1, px2, py2; + px1 = m_mapx; + py1 = m_mapy; + px2 = x; + py2 = y; + if (theApp.m_Options.bFlat) + ToPhys(&px1, &py1); + else + ToPhys3d(&px1, &py1); + if (theApp.m_Options.bFlat) + ToPhys(&px2, &py2); + else + ToPhys3d(&px2, &py2); + px1 += f_x / 2 - m_viewOffset.x - r.left; + py1 += f_y / 2 - m_viewOffset.y - r.top; + px2 += f_x / 2 - m_viewOffset.x - r.left; + py2 += f_y / 2 - m_viewOffset.y - r.top; + + CRect r; + GetWindowRect(r); + px1 += r.left; + px2 += r.left; + py1 += r.top; + py2 += r.top; + + + HDC dc; + lpdsBack->GetDC(&dc); + + POINT p; + MoveToEx(dc, px1, py1, &p); + LineTo(dc, px2, py2); + + lpdsBack->ReleaseDC(dc); + + BlitBackbufferToHighRes(); + RenderUIOverlay(); + FlipHighResBuffer(); + //lpds->Blt(NULL, lpdsBack, NULL, 0, 0); + + } + else + { + PlaceCurrentObjectAt(x, y); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + + + if (AD.mode == ACTIONMODE_PLACE && AD.type == 6) + { + Map->TakeSnapshot(); + Map->Undo(); + } + + + } + + UpdateStatusBar(x, y); + + + isMoving = FALSE; + + + + CView::OnMouseMove(nFlags, point); +} + + + +void CIsoView::DrawCellCursor(const MapCoords& mapCoords, const DDSURFACEDESC2& desc) +{ + ProjectedVec drawOffset(0*4, 0*3); + ProjectedCoords drawCoords2d = GetRenderTargetCoordinates(mapCoords, 0) + drawOffset; + ProjectedCoords drawCoords = GetRenderTargetCoordinates(mapCoords) + drawOffset; + + static const COLORREF _cell_hilight_colors[16] = { + RGB(255, 255, 255), // level 0 + RGB( 170, 0, 170), // level 1 + RGB(0, 170, 170), // level 2 + RGB(0, 170, 0), // level 3 + RGB(90, 255, 90), // level 4 + RGB(255, 255, 90), // level 5 + RGB(255, 50, 50), // level 6 + RGB(170, 85, 0), // level 7 + RGB(170, 0, 0), // level 8 + RGB(85, 255, 255), // level 9 + RGB(80, 80, 255), // level 10 + RGB(0, 0, 170), // level 11 + RGB(0, 0, 0), // level 12 + RGB(85,85 ,85), // level 13 + RGB(170, 170, 170), // level 14 + RGB(255, 255, 255) // level 15 + }; + + const FIELDDATA& m = *Map->GetFielddataAt(mapCoords.x + mapCoords.y * Map->GetIsoSize()); + int tileheight = m.bHeight; + int new_tileheight = std::clamp(tileheight, 0, 16); + + DrawCell(desc.lpSurface, desc.dwWidth, desc.dwHeight, desc.lPitch, drawCoords.x, drawCoords.y, 1, 1, m_color_converter->GetColor(_cell_hilight_colors[new_tileheight]), false, true, m_color_converter->GetColor(60, 60, 255)); + + LineDrawer l(desc.lpSurface, bpp, desc.dwWidth, desc.dwHeight, desc.lPitch); + + POINT p1, p2, p3, p4; + p2.x = drawCoords2d.x + 1 * f_x / 2 + f_x / 2; + p2.y = drawCoords2d.y + 1 * f_y / 2; + p3.x = drawCoords2d.x + 1 * f_x / 2 - 1 * f_x / 2 + f_x / 2 - 1; + p3.y = drawCoords2d.y + 1 * f_y / 2 + 1 * f_y / 2 - 1; + p4.x = drawCoords2d.x - 1 * f_x / 2 + f_x / 2 - 1; + p4.y = drawCoords2d.y + 1 * f_y / 2 - 1; + + POINT p5, p6, p7, p8; + p6.x = drawCoords.x + 1 * f_x / 2 + f_x / 2; + p6.y = drawCoords.y + 1 * f_y / 2; + p7.x = drawCoords.x + 1 * f_x / 2 - 1 * f_x / 2 + f_x / 2 - 1; + p7.y = drawCoords.y + 1 * f_y / 2 + 1 * f_y / 2 - 1; + p8.x = drawCoords.x - 1 * f_x / 2 + f_x / 2 - 1; + p8.y = drawCoords.y + 1 * f_y / 2 - 1; + + auto col = m_color_converter->GetColor(60, 60, 60); + if (drawCoords2d != drawCoords) + { + for (int y = 0; y < 2; ++y) + { + l.MoveTo(p2.x + 1, p2.y + y); + l.LineTo(p6.x + 1, p6.y + y, col, LineStyle::Dotted_4); + l.MoveTo(p3.x, p3.y + 1 + y); + l.LineTo(p7.x, p7.y + 1 + y, col, LineStyle::Dotted_4); + l.MoveTo(p4.x - 1, p4.y + y); + l.LineTo(p8.x - 1, p8.y + y, col, LineStyle::Dotted_4); + + l.MoveTo(p2.x, p2.y + y); + l.LineTo(p6.x, p6.y + y, col, LineStyle::Dotted_4); + l.MoveTo(p3.x + 1, p3.y + 1 + y); + l.LineTo(p7.x + 1, p7.y + 1 + y, col, LineStyle::Dotted_4); + l.MoveTo(p4.x, p4.y + y); + l.LineTo(p8.x, p8.y + y, col, LineStyle::Dotted_4); + } + } +} + +const int valadded = 10000; + + +void CIsoView::OnRButtonUp(UINT nFlags, CPoint point) +{ + if (rscroll) + { + if (b_IsLoading) return; + + ReleaseCapture(); + KillTimer(11); + ShowCursor(TRUE); + CMyViewFrame& dlg = *(CMyViewFrame*)owner; + dlg.m_minimap.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + } + + + if (nFlags == 0 && point.x == 0 && point.y == 0) + { + m_drag = FALSE; return; + } + + CIniFile& ini = Map->GetIniFile(); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + if (!rscroll) m_drag = FALSE; + + const auto projCoords = GetProjectedCoordinatesFromClientCoordinates(point); + const MapCoords mapCoords = GetMapCoordinatesFromClientCoordinates(point, (nFlags & MK_CONTROL) == MK_CONTROL); + + const int x = mapCoords.x; // compat + const int y = mapCoords.y; + + // context menu + if (AD.mode != 0 && !rscroll) + { + bool ignoreClick = false; + if (AD.mode == ACTIONMODE_MAPTOOL) + { + if (AD.tool) + ignoreClick = AD.tool->onRButtonUp(projCoords, mapCoords, MapToolMouseFlagsFromWin32(nFlags)); + } + + if (!ignoreClick) + { + AD.reset(); + + CMyViewFrame& frame = *((CMyViewFrame*)owner); + frame.m_objectview->GetTreeCtrl().Select(frame.m_objectview->GetTreeCtrl().GetRootItem(), TVGN_CARET); + } + return; + } + + rscroll = FALSE; + + return; + + + + + CView::OnRButtonUp(nFlags, point); +} + +// from old (popup menu) interface, taken over and used by OnLButtonDblClick +BOOL CIsoView::OnCommand(WPARAM wParam, LPARAM lParam) +{ + int wNotifyCode = HIWORD(wParam); // notification code + int wID = LOWORD(wParam); // item, control, or accelerator identifier + HWND hwndCtl = (HWND)lParam; // handle of control + + CIniFile& ini = Map->GetIniFile(); + + + if (wID < valadded) + { + // a standard menu, no popup! + + switch (wID) + { + case 4: + { + last_succeeded_operation = 54310; + //get the number + if (Map->GetAirAt(m_mapx + m_mapy * Map->GetIsoSize()) != -1) + { + HandleProperties(Map->GetAirAt(m_mapx + m_mapy * Map->GetIsoSize()), 2); + } + else if (Map->GetInfantryAt(m_mapx + m_mapy * Map->GetIsoSize()) != -1) + { + last_succeeded_operation = 54311; + int z; + for (z = 0;z < SUBPOS_COUNT;z++) + if (Map->GetInfantryAt(m_mapx + m_mapy * Map->GetIsoSize(), z) != -1) HandleProperties(Map->GetInfantryAt(m_mapx + m_mapy * Map->GetIsoSize(), z), 0); + } + else if (Map->GetUnitAt(m_mapx + m_mapy * Map->GetIsoSize()) != -1) + { + HandleProperties(Map->GetUnitAt(m_mapx + m_mapy * Map->GetIsoSize()), 3); + } + else if (Map->GetStructureAt(m_mapx + m_mapy * Map->GetIsoSize()) != -1) + { + HandleProperties(Map->GetStructureAt(m_mapx + m_mapy * Map->GetIsoSize()), 1); + } + + + break; + } + + } + + return 0; + } + + + + + + return CView::OnCommand(wParam, lParam); +} + +void CIsoView::HandleProperties(int n, int type) +{ + CIniFile& ini = Map->GetIniFile(); + + if (n < 0) return; + switch (type) + { + case 0: + { + last_succeeded_operation = 54312; + + // infantry + + INFANTRY data; + + Map->GetInfantryData(n, &data); + + last_succeeded_operation = 54313; + + + CInfantrie dlg(this); + char tmp[255]; + dlg.Init((LPCTSTR)data.house, (LPCTSTR)data.strength, (LPCTSTR)data.action, + (LPCTSTR)data.direction, (LPCTSTR)data.tag, (LPCTSTR)data.flag1, + (LPCTSTR)data.flag2, (LPCTSTR)data.flag3, (LPCTSTR)data.flag4, (LPCTSTR)data.flag5); + + int res = dlg.DoModal(); + if (res == IDCANCEL) return; + + data.action = dlg.m_action; + data.strength = dlg.m_strength; + data.tag = dlg.m_tag; + data.direction = dlg.m_direction; + data.house = dlg.m_house; + data.flag1 = dlg.m_flag1; + data.flag2 = dlg.m_flag2; + data.flag3 = dlg.m_flag3; + data.flag4 = dlg.m_flag4; + data.flag5 = dlg.m_flag5; + + + Map->DeleteInfantry(n); + Map->AddInfantry(&data); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + break; + } + case 1: + { + // building + + STRUCTURE data; + Map->GetStructureData(n, &data); + + + CBuilding dlg(this); + char tmp[255]; + dlg.Init((LPCTSTR)data.house, (LPCTSTR)data.strength, (LPCTSTR)data.direction, (LPCTSTR)data.tag, + (LPCTSTR)data.flag1, (LPCTSTR)data.flag2, (LPCTSTR)data.energy, + (LPCTSTR)data.upgradecount, (LPCTSTR)data.spotlight, (LPCTSTR)data.upgrade1, (LPCTSTR)data.upgrade2, + (LPCTSTR)data.upgrade3, (LPCTSTR)data.flag3, (LPCTSTR)data.flag4); + dlg.m_type = data.type; + + int res = dlg.DoModal(); + if (res == IDCANCEL) return; + + data.strength = dlg.m_strength; + data.tag = dlg.m_tag; + data.direction = dlg.m_direction; + data.house = dlg.m_house; + data.spotlight = dlg.m_spotlight; + data.flag1 = dlg.m_flag1; + data.flag2 = dlg.m_flag2; + data.flag3 = dlg.m_flag3; + data.flag4 = dlg.m_flag4; + data.energy = dlg.m_energy; + data.upgradecount = dlg.m_upgradecount; + data.upgrade1 = dlg.m_upgrade1; + data.upgrade2 = dlg.m_upgrade2; + data.upgrade3 = dlg.m_upgrade3; + + + + Map->DeleteStructure(n); + Map->AddStructure(&data); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + break; + + } + case 2: + { + // aircraft + + AIRCRAFT data; + Map->GetAircraftData(n, &data); + + + CAircraft dlg(this); + char tmp[255]; + dlg.Init(data.house, data.strength, data.direction, data.action, + data.tag, data.flag1, data.flag2, data.flag3, data.flag4); + + int res = dlg.DoModal(); + if (res == IDCANCEL) return; + + data.action = dlg.m_action; + data.strength = dlg.m_strength; + data.tag = dlg.m_tag; + data.direction = dlg.m_direction; + data.house = dlg.m_house; + data.flag1 = dlg.m_flag1; + data.flag2 = dlg.m_flag2; + data.flag3 = dlg.m_flag3; + data.flag4 = dlg.m_flag4; + + + Map->DeleteAircraft(n); + Map->AddAircraft(&data); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + break; + } + case 3: + { + // vehicle + + UNIT data; + Map->GetUnitData(n, &data); + + + CUnit dlg(this); + char tmp[255]; + dlg.Init(data.house, data.strength, data.direction, data.action, + data.tag, data.flag1, data.flag2, data.flag3, data.flag4, data.flag5, data.flag6); + + int res = dlg.DoModal(); + if (res == IDCANCEL) return; + + data.action = dlg.m_action; + data.strength = dlg.m_strength; + data.tag = dlg.m_tag; + data.direction = dlg.m_direction; + data.house = dlg.m_house; + data.flag1 = dlg.m_flag1; + data.flag2 = dlg.m_flag2; + data.flag3 = dlg.m_flag3; + data.flag4 = dlg.m_flag4; + data.flag5 = dlg.m_flag5; + data.flag6 = dlg.m_flag6; + + Map->DeleteUnit(n); + Map->AddUnit(&data); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + break; + + + } + } +} + +void CIsoView::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + + + if (b_IsLoading == TRUE) return; + + m_NoMove = TRUE; + m_drag = FALSE; + + const auto projCoords = GetProjectedCoordinatesFromClientCoordinates(point); + const MapCoords mapCoords = GetMapCoordinatesFromClientCoordinates(point, (nFlags & MK_CONTROL) == MK_CONTROL); + + if (AD.mode == ACTIONMODE_MAPTOOL) + { + if (AD.tool) + AD.tool->onLButtonDblClick(projCoords, mapCoords, MapToolMouseFlagsFromWin32(nFlags)); + } + else + { + if (!Map->isInside(mapCoords)) + return; + + m_mapx = mapCoords.x; + m_mapy = mapCoords.y; + + int pos = m_mapx + m_mapy * Map->GetIsoSize(); + if (Map->GetCelltagAt(pos) < 0) + { + OnCommand(4, 0); + } + else + OnCommand(9, 0); + } + + m_NoMove = FALSE; + + CView::OnLButtonDblClk(nFlags, point); +} + +void CIsoView::OnLButtonDown(UINT nFlags, CPoint point) +{ + if (Map->GetIsoSize() == 0) return; + if (b_IsLoading == TRUE) return; + + + CIniFile& ini = Map->GetIniFile(); + + const auto projCoords = GetProjectedCoordinatesFromClientCoordinates(point); + const MapCoords mapCoords = GetMapCoordinatesFromClientCoordinates(point, (nFlags & MK_CONTROL) == MK_CONTROL); + + + + const int x = mapCoords.x; // compat + const int y = mapCoords.y; + + + int mapwidth = Map->GetWidth(); + int mapheight = Map->GetHeight(); + //if(x>=Map->GetIsoSize() || y>=Map->GetIsoSize() || x<0 || y<0) return; + if (AD.mode != ACTIONMODE_COPY && AD.mode != ACTIONMODE_PASTE && AD.mode != ACTIONMODE_MAPTOOL) + { + if (!Map->isInside(mapCoords)) + return; + if (x < 1 || y < 1 || x + ymapwidth + mapheight * 2 || (y + 1 > mapwidth && x - 1 < y - mapwidth) || (x + 1 > mapwidth && y + mapwidth - 1 < x)) + return; + } + + int px = m_mapx; + int py = m_mapy; + + m_mapx = x; + m_mapy = y; + + CStatusBarCtrl& stat = ((CMyViewFrame*)owner)->m_statbar.GetStatusBarCtrl(); + + if (AD.mode == ACTIONMODE_CLIFFFRONT || AD.mode == ACTIONMODE_CLIFFBACK) + { + m_drag = TRUE; + } + else if (AD.mode == ACTIONMODE_PASTE) + { + Map->TakeSnapshot(); + Map->Paste(m_mapx, m_mapy, AD.z_data); + Map->TakeSnapshot(); + Map->Undo(); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (AD.mode == ACTIONMODE_COPY) + { + if (!m_drag) + { + m_drag = TRUE; + } + else // 2nd click + { + int x1, x2, y1, y2; + if (px < x) + { + x1 = px; + x2 = x; + } + else + { + x1 = x; + x2 = px; + } + if (py < y) + { + y1 = py; + y2 = y; + } + else + { + y1 = y; + y2 = py; + } + + + Map->Copy(x1, y1, x2 + 1, y2 + 1); + + m_drag = FALSE; + } + } + else if (Map->IsGroundObjectAt(m_mapx + m_mapy * Map->GetIsoSize()) && AD.mode == 0 && m_NoMove == FALSE) + { + m_drag = TRUE; + m_moved = FALSE; + m_id = Map->GetInfantryAt(m_mapx + m_mapy * Map->GetIsoSize()); + m_type = 0; + if (m_id < 0) + { + m_id = Map->GetUnitAt(m_mapx + m_mapy * Map->GetIsoSize()); + m_type = 3; + } + if (m_id < 0) + { + m_id = Map->GetAirAt(m_mapx + m_mapy * Map->GetIsoSize()); + m_type = 2; + } + if (m_id < 0) + { + m_id = Map->GetTerrainAt(m_mapx + m_mapy * Map->GetIsoSize()); + m_type = 4; + } + if (m_id < 0) + { + m_id = Map->GetStructureAt(m_mapx + m_mapy * Map->GetIsoSize()); + + STDOBJECTDATA sod; + Map->GetStdStructureData(m_id, &sod); + m_mapx = atoi(sod.x); + m_mapy = atoi(sod.y); + + m_type = 1; + } + + } + else if (AD.mode == ACTIONMODE_SETTILE) + { + + + if ((nFlags & MK_CONTROL) && !(nFlags & MK_SHIFT)) + { + // Fill the whole area + Sound(SOUND_LAYDOWNTILE); + + Map->TakeSnapshot(); + int i; + for (i = 0;i < Map->GetIsoSize() * Map->GetIsoSize();i++) + Map->SetReserved(i, 0); + + FillArea(x, y, AD.type, 0); + Map->TakeSnapshot(); + Map->Undo(); + } + else + { + // just place a single tile + + if (!(nFlags & MK_SHIFT)) + { + Sound(SOUND_LAYDOWNTILE); + } + + PlaceTile(x, y, nFlags); + } + + + + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (AD.mode == ACTIONMODE_HIDETILESET) + { + int ground = Map->GetFielddataAt(x + (y)*Map->GetIsoSize())->wGround; + if (ground == 0xFFFF) ground = 0; + + //if(ground!=0) + HideTileSet((*tiledata)[ground].wTileSet); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (AD.mode == ACTIONMODE_HIDEFIELD) + { + Map->HideField(x + y * Map->GetIsoSize(), TRUE); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (AD.mode == ACTIONMODE_HEIGHTEN) + { + Map->TakeSnapshot(); + + m_TileChangeCount = 0; + //if(x==m_mapx && y==m_mapy) + //try + { + int ground = Map->GetFielddataAt(x + (y)*Map->GetIsoSize())->wGround; + if (ground == 0xFFFF) ground = 0; + + if ((nFlags & MK_CONTROL) && !(*tiledata)[ground].bMorphable) + { + SetError("Applying non-morphable terrain height change, please wait..."); + stat.RedrawWindow(); + stat.UpdateWindow(); + } + + m_funcRect.left = x; + m_funcRect.top = y; + m_funcRect.bottom = y; + m_funcRect.right = x; + + if ((*tiledata)[ground].bMorphable) + { + int f, n; + int oheight = Map->GetHeightAt(x + y * Map->GetIsoSize()); + for (f = -m_BrushSize_x / 2;f < m_BrushSize_x / 2 + 1;f++) + { + for (n = -m_BrushSize_y / 2;n < m_BrushSize_y / 2 + 1;n++) + { + int pos = x + f + (y + n) * Map->GetIsoSize(); + int ground = Map->GetFielddataAt(pos)->wGround; + if (ground == 0xFFFF) ground = 0; + + if ((*tiledata)[ground].bMorphable && Map->GetHeightAt(pos) == oheight) + { + Map->SetHeightAt(pos, oheight + 1); + } + } + } + for (f = -m_BrushSize_x / 2;f < m_BrushSize_x / 2 + 1;f++) + { + for (n = -m_BrushSize_y / 2;n < m_BrushSize_y / 2 + 1;n++) + { + int pos = x + f + (y + n) * Map->GetIsoSize(); + int ground = Map->GetFielddataAt(pos)->wGround; + if (ground == 0xFFFF) ground = 0; + + if ((*tiledata)[ground].bMorphable && Map->GetHeightAt(x + f + (y + n) * Map->GetIsoSize()) == oheight + 1) + { + int i; + for (i = 0;i < Map->GetIsoSize() * Map->GetIsoSize();i++) + Map->SetReserved(i, 0); + + ChangeTileHeight(x + f + (y + n) * Map->GetIsoSize(), oheight + 1, FALSE, (nFlags & MK_CONTROL), TRUE); + } + } + } + } + else + { + int i; + for (i = 0;i < Map->GetIsoSize() * Map->GetIsoSize();i++) + Map->SetReserved(i, 0); + + // TODO: replace recursion, otherwise be aware of stack issues! + try + { + ChangeTileHeight(x + (y)*Map->GetIsoSize(), Map->GetHeightAt(x + y * Map->GetIsoSize()) + 1, FALSE, !(nFlags & MK_CONTROL)); + } + catch (...) + { + MessageBox("Stack is too small to complete operation!", "Error"); + } + } + + int f, n; + for (f = m_funcRect.left - 1;f <= m_funcRect.right + 1;f++) + { + for (n = m_funcRect.top - 1;n <= m_funcRect.bottom + 1;n++) + { + int pos = f + (n)*Map->GetIsoSize(); + Map->CreateSlopesAt(pos); + } + } + + + /*CHANGEHEIGHTDATA d; + d.pos=x+y*Map->GetIsoSize(); + d.bNonMorpheable=FALSE; + d.toHeight=Map->GetHeightAt(x+y*Map->GetIsoSize())+1; + DWORD id; + HANDLE hThread=CreateThread(NULL, 4000000, ChangeHeightThread, &d, NULL, &id); + SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL); + WaitForSingleObjectEx(hThread, INFINITE, FALSE);*/ + + + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + Map->TakeSnapshot(); + Map->Undo(); + } + //catch(...) + { + // MessageBox("Error occured","Error"); + } + } + else if (AD.mode == ACTIONMODE_LOWER) + { + Map->TakeSnapshot(); + + m_TileChangeCount = 0; + //if(x==m_mapx && y==m_mapy) + //try + { + int ground = Map->GetFielddataAt(x + (y)*Map->GetIsoSize())->wGround; + if (ground == 0xFFFF) ground = 0; + + if ((nFlags & MK_CONTROL) && !(*tiledata)[ground].bMorphable) + { + SetError("Applying non-morphable terrain height change, please wait..."); + stat.RedrawWindow(); + stat.UpdateWindow(); + } + + int i; + + m_funcRect.left = x; + m_funcRect.top = y; + m_funcRect.bottom = y; + m_funcRect.right = x; + + if ((*tiledata)[ground].bMorphable) + { + int f, n; + int oheight = Map->GetHeightAt(x + y * Map->GetIsoSize()); + for (f = -m_BrushSize_x / 2;f < m_BrushSize_x / 2 + 1;f++) + { + for (n = -m_BrushSize_y / 2;n < m_BrushSize_y / 2 + 1;n++) + { + int pos = x + f + (y + n) * Map->GetIsoSize(); + int ground = Map->GetFielddataAt(pos)->wGround; + if (ground == 0xFFFF) ground = 0; + + if ((*tiledata)[ground].bMorphable && Map->GetHeightAt(pos) == oheight) + { + Map->SetHeightAt(pos, oheight - 1); + } + } + } + for (f = -m_BrushSize_x / 2;f < m_BrushSize_x / 2 + 1;f++) + { + for (n = -m_BrushSize_y / 2;n < m_BrushSize_y / 2 + 1;n++) + { + int pos = x + f + (y + n) * Map->GetIsoSize(); + int ground = Map->GetFielddataAt(pos)->wGround; + if (ground == 0xFFFF) ground = 0; + + if ((*tiledata)[ground].bMorphable && Map->GetHeightAt(x + f + (y + n) * Map->GetIsoSize()) == oheight - 1) + { + for (i = 0;i < Map->GetIsoSize() * Map->GetIsoSize();i++) + Map->SetReserved(i, 0); + + ChangeTileHeight(x + f + (y + n) * Map->GetIsoSize(), oheight - 1, FALSE, (nFlags & MK_CONTROL), TRUE); + } + } + } + } + else + { + for (i = 0;i < Map->GetIsoSize() * Map->GetIsoSize();i++) + Map->SetReserved(i, 0); + + try + { + ChangeTileHeight(x + (y)*Map->GetIsoSize(), Map->GetHeightAt(x + y * Map->GetIsoSize()) - 1, FALSE, !(nFlags & MK_CONTROL)); + } + catch (...) + { + MessageBox("Stack is too small to complete operation!", "Error"); + } + } + + int f, n; + for (f = m_funcRect.left - 1;f <= m_funcRect.right + 1;f++) + { + for (n = m_funcRect.top - 1;n <= m_funcRect.bottom + 1;n++) + { + int pos = f + (n)*Map->GetIsoSize(); + Map->CreateSlopesAt(pos); + } + } + + /*CHANGEHEIGHTDATA d; + d.pos=x+y*Map->GetIsoSize(); + d.bNonMorpheable=FALSE; + d.toHeight=Map->GetHeightAt(x+y*Map->GetIsoSize())-1; + DWORD id; + HANDLE hThread=CreateThread(NULL, 4000000, ChangeHeightThread, &d, NULL, &id); + SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL); + WaitForSingleObjectEx(hThread, INFINITE, FALSE);*/ + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + //catch(...) + { + // MessageBox("Error occured","Error"); + } + + Map->TakeSnapshot(); + Map->Undo(); + } + else if (AD.mode == ACTIONMODE_HEIGHTENTILE) + { + Map->TakeSnapshot(); + + int n, m; + for (m = -m_BrushSize_x / 2;m < m_BrushSize_x / 2 + 1;m++) + { + for (n = -m_BrushSize_y / 2;n < m_BrushSize_y / 2 + 1;n++) + { + Map->SetHeightAt(x + m + (y + n) * Map->GetIsoSize(), Map->GetHeightAt(x + m + (y + n) * Map->GetIsoSize()) + 1); + } + } + + if (nFlags & MK_CONTROL) + for (m = -m_BrushSize_x / 2 - 1;m < m_BrushSize_x / 2 + 2;m++) + { + for (n = -m_BrushSize_y / 2 - 1;n < m_BrushSize_y / 2 + 2;n++) + { + Map->CreateSlopesAt(x + m + (y + n) * Map->GetIsoSize()); + } + } + + Map->TakeSnapshot(); + Map->Undo(); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (AD.mode == ACTIONMODE_LOWERTILE) + { + Map->TakeSnapshot(); + + int n, m; + for (m = -m_BrushSize_x / 2;m < m_BrushSize_x / 2 + 1;m++) + { + for (n = -m_BrushSize_y / 2;n < m_BrushSize_y / 2 + 1;n++) + { + Map->SetHeightAt(x + m + (y + n) * Map->GetIsoSize(), Map->GetHeightAt(x + m + (y + n) * Map->GetIsoSize()) - 1); + } + } + + if (nFlags & MK_CONTROL) + for (m = -m_BrushSize_x / 2 - 1;m < m_BrushSize_x / 2 + 2;m++) + { + for (n = -m_BrushSize_y / 2 - 1;n < m_BrushSize_y / 2 + 2;n++) + { + Map->CreateSlopesAt(x + m + (y + n) * Map->GetIsoSize()); + } + } + + Map->TakeSnapshot(); + Map->Undo(); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (AD.mode == ACTIONMODE_FLATTENGROUND) + { + Map->TakeSnapshot(); + + m_FlattenHeight = Map->GetHeightAt(x + y * Map->GetIsoSize()); + m_FlattenLastX = x; + m_FlattenLastY = y; + + Map->TakeSnapshot(); + Map->Undo(); + } + else if (Map->GetWaypointAt(m_mapx + m_mapy * Map->GetIsoSize()) >= 0 && AD.mode == 0) + { + m_drag = TRUE; + m_id = Map->GetWaypointAt(m_mapx + m_mapy * Map->GetIsoSize()); + m_type = 6; + } + else if (Map->GetCelltagAt(m_mapx + m_mapy * Map->GetIsoSize()) >= 0 && AD.mode == 0) + { + m_drag = TRUE; + m_id = Map->GetCelltagAt(m_mapx + m_mapy * Map->GetIsoSize()); + m_type = 5; + } + else if ((AD.mode < 3 || AD.mode>4) || (AD.mode == 3 && AD.type == 0) || (AD.mode >= 3 && AD.mode <= 4 && AD.type == 1)) + { + OnMouseMove(nFlags, point); + } + else if (AD.mode == 3) + { + if (AD.type == 2) + { + // create waypoint + CWaypointID w(this); + if (w.DoModal() != IDCANCEL) + { + int n = w.m_value; + + char id[50]; + itoa(n, id, 10); + Map->AddWaypoint(id, x + y * Map->GetIsoSize()); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + } + if (AD.type >= 3) OnMouseMove(nFlags, point); + + } + + else if (AD.mode == 4) + { + if (AD.type == 0) + { + // create celltag + CCellTag w(this); + if (w.DoModal() != IDCANCEL) + { + Map->AddCelltag(w.m_tag, x + y * Map->GetIsoSize()); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + } + if (AD.type == 2) + { + // change celltag properties + int n = Map->GetCelltagAt(x + y * Map->GetIsoSize()); + if (n < 0) return; + + DWORD dwPos; + CString tag; + + Map->GetCelltagData(n, &tag, &dwPos); + + + + CCellTag dlg(this); + + dlg.m_tag = tag; + dlg.m_tag += " ("; + dlg.m_tag += GetParam(Map->GetIniFile().sections["Tags"].values[(LPCTSTR)tag], 1); + dlg.m_tag += ")"; + + if (dlg.DoModal() == IDCANCEL) return; + + Map->DeleteCelltag(n); + + Map->AddCelltag(dlg.m_tag, dwPos); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + + } + + + + CView::OnLButtonDown(nFlags, point); +} + +void CIsoView::PlaceTile(const int x, const int y, const UINT nMouseFlags) +{ + Map->TakeSnapshot(TRUE, x - 6, y - 6, x + (*tiledata)[AD.type].cx * m_BrushSize_x + 7, y + (*tiledata)[AD.type].cy * m_BrushSize_y + 7); + int i, e, f, n; + int p = 0; + int width = (*tiledata)[AD.type].cx; + int height = (*tiledata)[AD.type].cy; + int pos = x - width + 1 + (y - height + 1) * Map->GetIsoSize(); + int startheight = Map->GetHeightAt(x + y * Map->GetIsoSize()) + AD.z_data; + int ground = Map->GetFielddataAt(x + y * Map->GetIsoSize())->wGround; + if (ground == 0xFFFF) ground = 0; + startheight -= (*tiledata)[ground].tiles[Map->GetFielddataAt(x + y * Map->GetIsoSize())->bSubTile].bZHeight; + for (f = 0;f < m_BrushSize_x;f++) + { + for (n = 0;n < m_BrushSize_y;n++) + { + int tile = AD.type; + if (AD.data == 1) + { + int n = rand() * 5 / RAND_MAX; + tile += n; + + } + p = 0; + for (i = 0;i < (*tiledata)[AD.type].cx;i++) + { + for (e = 0;e < (*tiledata)[AD.type].cy;e++) + { + + if (x - width + 1 + f * width + i >= Map->GetIsoSize() || + y - height + 1 + n * height + e >= Map->GetIsoSize()) + { + + } + else + if ((*tiledata)[AD.type].tiles[p].pic != NULL) + { + Map->SetHeightAt(pos + i + f * width + (e + n * height) * Map->GetIsoSize(), startheight + (*tiledata)[AD.type].tiles[p].bZHeight); + Map->SetTileAt(pos + i + f * width + (e + n * height) * Map->GetIsoSize(), tile, p); + + } + p++; + } + } + + } + } + + if (!((nMouseFlags & MK_CONTROL) && (nMouseFlags & MK_SHIFT))) + { + if (!theApp.m_Options.bDisableAutoShore) Map->CreateShore(x - 5, y - 5, x + (*tiledata)[AD.type].cx * m_BrushSize_x + 5, y + (*tiledata)[AD.type].cy * m_BrushSize_y + 5, FALSE); + //Map->CreateShore(0,0,Map->GetIsoSize(), Map->GetIsoSize()); + + for (f = 0;f < m_BrushSize_x;f++) + { + for (n = 0;n < m_BrushSize_y;n++) + { + p = 0; + for (i = -1;i < (*tiledata)[AD.type].cx + 1;i++) + { + for (e = -1;e < (*tiledata)[AD.type].cy + 1;e++) + { + + Map->SmoothAllAt(pos + i + f * width + (e + n * height) * Map->GetIsoSize()); + + p++; + } + } + + } + } + } + + // now make current tiles available for redo + Map->TakeSnapshot(TRUE, x - 6, y - 6, x + (*tiledata)[AD.type].cx * m_BrushSize_x + 6, y + (*tiledata)[AD.type].cy * m_BrushSize_y + 6); + Map->Undo(); +} + + + + + +void CIsoView::OnLButtonUp(UINT nFlags, CPoint point) +{ + if (b_IsLoading == TRUE) return; + + CIniFile& ini = Map->GetIniFile(); + + const auto projCoords = GetProjectedCoordinatesFromClientCoordinates(point); + const MapCoords mapCoords = GetMapCoordinatesFromClientCoordinates(point, (nFlags & MK_CONTROL) == MK_CONTROL); + + const int dx = mapCoords.x; // compat + const int dy = mapCoords.y; + + + //if(dx>=Map->GetIsoSize() || dy>=Map->GetIsoSize() || dx<0 || dy<0) return; + int mapwidth = Map->GetWidth(); + int mapheight = Map->GetHeight(); + if (AD.mode != ACTIONMODE_COPY && AD.mode != ACTIONMODE_PASTE && AD.mode != ACTIONMODE_MAPTOOL) + { + if (!Map->isInside(mapCoords)) + return; + if (dx < 1 || dy < 1 || dx + dymapwidth + mapheight * 2 || (dy + 1 > mapwidth && dx - 1 < dy - mapwidth) || (dx + 1 > mapwidth && dy + mapwidth - 1 < dx)) + return; + } + + + char fx[50], fy[50]; + itoa(dx, fx, 10); + itoa(dy, fy, 10); + + int x, y; + x = dx; + y = dy; + + // check if user did select something else than 0 in object browser + if (AD.mode != 0 && AD.mode != ACTIONMODE_COPY) + { + if (m_moved) + m_drag = FALSE; + m_moved = FALSE; + } + + if (AD.mode == ACTIONMODE_FLATTENGROUND) + { + Map->TakeSnapshot(); + Map->Undo(); + } + if (AD.mode == ACTIONMODE_CLIFFFRONT || AD.mode == ACTIONMODE_CLIFFBACK) + { + m_drag = FALSE; + Map->Redo(); + /*Map->TakeSnapshot(); + + if(AD.mode==ACTIONMODE_CLIFFFRONT) + { + CFrontCliffModifier f; + f.PlaceCliff(m_mapx, m_mapy, x, y); + } + else if(AD.mode==ACTIONMODE_CLIFFBACK) + { + CBackCliffModifier f; + f.PlaceCliff(m_mapx, m_mapy, x, y); + }*/ + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + + if (AD.mode == ACTIONMODE_COPY && m_drag) + { + /*m_drag=FALSE; + + int x1, x2, y1, y2; + if(m_mapxCopy(x1, y1, x2+1, y2+1);*/ + m_moved = FALSE; + } + + if (m_drag && m_moved) + { + m_moved = FALSE; + + // ok, drag the object at m_mapx/m_mapy to x/y + int x = dx, y = dy; + char strX[15], strY[15]; + itoa(x, strX, 10); + itoa(y, strY, 10); + switch (m_type) + { + case 0: // drag infantry + { + INFANTRY infantry; + Map->GetInfantryData(m_id, &infantry); + infantry.x = strX; + infantry.y = strY; + infantry.pos = "-1"; + + if ((nFlags != MK_SHIFT)) + { + Map->DeleteInfantry(m_id); + } + + Map->AddInfantry(&infantry); + + break; + } + case 1: // drag structure + { + STRUCTURE structure; + Map->GetStructureData(m_id, &structure); + structure.x = strX; + structure.y = strY; + + if ((nFlags != MK_SHIFT)) + { + Map->DeleteStructure(m_id); + } + + Map->AddStructure(&structure); + + break; + } + case 2: // drag aircraft + { + AIRCRAFT aircraft; + Map->GetAircraftData(m_id, &aircraft); + aircraft.x = strX; + aircraft.y = strY; + + + if ((nFlags != MK_SHIFT)) + { + Map->DeleteAircraft(m_id); + } + + Map->AddAircraft(&aircraft); + + break; + } + case 3: // drag vehicles + { + UNIT unit; + Map->GetUnitData(m_id, &unit); + unit.x = strX; + unit.y = strY; + + if (!(nFlags == MK_SHIFT)) + { + Map->DeleteUnit(m_id); + } + + Map->AddUnit(&unit); + + break; + } + case 4: // drag terrain + { + CString type; + + Map->GetTerrainData(m_id, &type); + + if ((nFlags != MK_SHIFT)) + { + Map->DeleteTerrain(m_id); + } + + Map->AddTerrain(type, x + y * Map->GetIsoSize()); + break; + } + + case 5: // drag celltag + { + CString tag; + DWORD dwPos; + Map->GetCelltagData(m_id, &tag, &dwPos); + + if ((nFlags != MK_SHIFT)) + { + Map->DeleteCelltag(m_id); + } + + Map->AddCelltag(tag, x + y * Map->GetIsoSize()); + break; + } + case 6: // drag waypoint + { + CString ID; + DWORD dwPos; + + Map->GetWaypointData(m_id, &ID, &dwPos); + + if (!(nFlags == MK_SHIFT)) + { + Map->DeleteWaypoint(m_id); + } + + Map->AddWaypoint(ID, x + y * Map->GetIsoSize()); + break; + } + + } + + + + m_drag = FALSE; + line.left = 0; + line.top = 0; + line.right = 0; + line.bottom = 0; + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (AD.mode == ACTIONMODE_MAPTOOL) + { + if (AD.tool) + AD.tool->onLButtonUp(projCoords, mapCoords, MapToolMouseFlagsFromWin32(nFlags)); + } + else if (AD.mode == ACTIONMODE_PLACE) // painting stuff + { + m_moved = FALSE; + if (AD.type == 6) // Overlay + { + if (AD.data == 5) // birdges + { + if (x == m_mapx && y == m_mapy) return; + + int ovrltype = 0x18; + if (abs(x - m_mapx) >= abs(y - m_mapy)) + { + // it´s from bottom left to top right + y = m_mapy; + ovrltype = 0x19; + } + else + { + // from bottom right to top left + x = m_mapx; + ovrltype = 0x18; + } + + int tmp; + + if (x < m_mapx) + { + tmp = m_mapx; + m_mapx = x; + x = tmp; + } + if (y < m_mapy) + { + tmp = m_mapy; + m_mapy = y; + y = tmp; + } + + // okay, now we can do it... + int i; + if (AD.data2 == 0) // big bridge + { + int startheight = Map->GetFielddataAt(m_mapx + m_mapy * Map->GetIsoSize())->bHeight; + + if (y == m_mapy) + { + for (i = m_mapx;i <= x;i++) + { + if (Map->GetFielddataAt(i + m_mapy * Map->GetIsoSize())->bHeight == startheight - 4) + { + startheight = Map->GetFielddataAt(i + m_mapy * Map->GetIsoSize())->bHeight; + break; + } + } + } + else + { + for (i = m_mapy;i <= y;i++) + { + if (Map->GetFielddataAt(m_mapx + i * Map->GetIsoSize())->bHeight == startheight - 4) + { + startheight = Map->GetFielddataAt(m_mapx + i * Map->GetIsoSize())->bHeight; + break; + } + } + } + + if (y == m_mapy) + { + for (i = m_mapx;i <= x;i++) + { + if (Map->GetFielddataAt(i + m_mapy * Map->GetIsoSize())->bHeight == startheight) + { + Map->SetOverlayAt(i + m_mapy * Map->GetIsoSize(), ovrltype); + Map->SetOverlayDataAt(i + m_mapy * Map->GetIsoSize(), 0x9); + } + } + } + else + { + for (i = m_mapy;i <= y;i++) + { + if (Map->GetFielddataAt(m_mapx + i * Map->GetIsoSize())->bHeight == startheight) + { + Map->SetOverlayAt(m_mapx + i * Map->GetIsoSize(), ovrltype); + Map->SetOverlayDataAt(m_mapx + i * Map->GetIsoSize(), 0x0); + } + } + } + } + if (AD.data2 == 2) // big track bridge + { + int startheight = Map->GetFielddataAt(m_mapx + m_mapy * Map->GetIsoSize())->bHeight; + + if (y == m_mapy) + { + for (i = m_mapx;i <= x;i++) + { + if (Map->GetFielddataAt(i + m_mapy * Map->GetIsoSize())->bHeight == startheight - 4) + { + startheight = Map->GetFielddataAt(i + m_mapy * Map->GetIsoSize())->bHeight; + break; + } + } + } + else + { + for (i = m_mapy;i <= y;i++) + { + if (Map->GetFielddataAt(m_mapx + i * Map->GetIsoSize())->bHeight == startheight - 4) + { + startheight = Map->GetFielddataAt(m_mapx + i * Map->GetIsoSize())->bHeight; + break; + } + } + } + + if (y == m_mapy) + { + for (i = m_mapx;i <= x;i++) + { + if (Map->GetFielddataAt(i + m_mapy * Map->GetIsoSize())->bHeight == startheight) + { + + Map->SetOverlayAt(i + m_mapy * Map->GetIsoSize(), 0x3c); +#ifdef RA2_MODE + Map->SetOverlayAt(i + m_mapy * Map->GetIsoSize(), 0xee); +#endif + Map->SetOverlayDataAt(i + m_mapy * Map->GetIsoSize(), 0x9); + } + } + } + else + { + for (i = m_mapy;i <= y;i++) + { + if (Map->GetFielddataAt(m_mapx + i * Map->GetIsoSize())->bHeight == startheight) + { + Map->SetOverlayAt(m_mapx + i * Map->GetIsoSize(), 0x3b); +#ifdef RA2_MODE + Map->SetOverlayAt(m_mapx + i * Map->GetIsoSize(), 0xed); +#endif + Map->SetOverlayDataAt(m_mapx + i * Map->GetIsoSize(), 0x0); + } + } + } + + /*if(y==m_mapy) + { + for(i=m_mapx;i<=x;i++) + { + Map->SetOverlayAt(i+m_mapy*Map->GetIsoSize(), 0x3b); + Map->SetOverlayDataAt(i+m_mapy*Map->GetIsoSize(), 0x9); + } + } + else + { + for(i=m_mapy;i<=y;i++) + { + Map->SetOverlayAt(m_mapx+i*Map->GetIsoSize(), 0x3b); + Map->SetOverlayDataAt(m_mapx+i*Map->GetIsoSize(), 0x0); + } + }*/ + } + else if (AD.data2 == 1 || AD.data2 == 3) // small bridge + { + int start = 0x4a; + if (AD.data2 == 3) start = 0xcd; + + if (y == m_mapy) + { + srand((unsigned)time(NULL)); + for (i = m_mapx + 1;i <= x - 1;i++) + { + + int v2 = ((float)rand() / (float)RAND_MAX) * 4; + + Map->SetOverlayAt(i + (m_mapy - 1) * Map->GetIsoSize(), start + 9 + v2); + Map->SetOverlayDataAt(i + (m_mapy - 1) * Map->GetIsoSize(), 0x0); + Map->SetOverlayAt(i + (m_mapy + 0) * Map->GetIsoSize(), start + 9 + v2); + Map->SetOverlayDataAt(i + (m_mapy + 0) * Map->GetIsoSize(), 0x1); + Map->SetOverlayAt(i + (m_mapy + 1) * Map->GetIsoSize(), start + 9 + v2); + Map->SetOverlayDataAt(i + (m_mapy + 1) * Map->GetIsoSize(), 0x2); + } + Map->SetOverlayAt(m_mapx + (m_mapy - 1) * Map->GetIsoSize(), start + 22); + Map->SetOverlayAt(m_mapx + (m_mapy - 0) * Map->GetIsoSize(), start + 22); + Map->SetOverlayAt(m_mapx + (m_mapy + 1) * Map->GetIsoSize(), start + 22); + Map->SetOverlayDataAt(m_mapx + (m_mapy - 1) * Map->GetIsoSize(), 0x0); + Map->SetOverlayDataAt(m_mapx + (m_mapy - 0) * Map->GetIsoSize(), 0x1); + Map->SetOverlayDataAt(m_mapx + (m_mapy + 1) * Map->GetIsoSize(), 0x2); + + Map->SetOverlayAt(x + (m_mapy - 1) * Map->GetIsoSize(), start + 24); + Map->SetOverlayAt(x + (m_mapy - 0) * Map->GetIsoSize(), start + 24); + Map->SetOverlayAt(x + (m_mapy + 1) * Map->GetIsoSize(), start + 24); + Map->SetOverlayDataAt(x + (m_mapy - 1) * Map->GetIsoSize(), 0x0); + Map->SetOverlayDataAt(x + (m_mapy - 0) * Map->GetIsoSize(), 0x1); + Map->SetOverlayDataAt(x + (m_mapy + 1) * Map->GetIsoSize(), 0x2); + + + } + else + { + srand((unsigned)time(NULL)); + + for (i = m_mapy + 1;i <= y - 1;i++) + { + + int v2 = ((float)rand() / (float)RAND_MAX) * 4; + + Map->SetOverlayAt((m_mapx - 1) + i * Map->GetIsoSize(), start + v2); + Map->SetOverlayDataAt((m_mapx - 1) + i * Map->GetIsoSize(), 0x0); + Map->SetOverlayAt((m_mapx - 0) + i * Map->GetIsoSize(), start + v2); + Map->SetOverlayDataAt((m_mapx - 0) + i * Map->GetIsoSize(), 0x1); + Map->SetOverlayAt((m_mapx + 1) + i * Map->GetIsoSize(), start + v2); + Map->SetOverlayDataAt((m_mapx + 1) + i * Map->GetIsoSize(), 0x2); + } + Map->SetOverlayAt((m_mapx - 1) + m_mapy * Map->GetIsoSize(), start + 20); + Map->SetOverlayAt((m_mapx - 0) + m_mapy * Map->GetIsoSize(), start + 20); + Map->SetOverlayAt((m_mapx + 1) + m_mapy * Map->GetIsoSize(), start + 20); + Map->SetOverlayDataAt((m_mapx - 1) + m_mapy * Map->GetIsoSize(), 0x0); + Map->SetOverlayDataAt((m_mapx - 0) + m_mapy * Map->GetIsoSize(), 0x1); + Map->SetOverlayDataAt((m_mapx + 1) + m_mapy * Map->GetIsoSize(), 0x2); + + Map->SetOverlayAt((m_mapx - 1) + y * Map->GetIsoSize(), start + 18); + Map->SetOverlayAt((m_mapx - 0) + y * Map->GetIsoSize(), start + 18); + Map->SetOverlayAt((m_mapx + 1) + y * Map->GetIsoSize(), start + 18); + Map->SetOverlayDataAt((m_mapx - 1) + y * Map->GetIsoSize(), 0x0); + Map->SetOverlayDataAt((m_mapx + 0) + y * Map->GetIsoSize(), 0x1); + Map->SetOverlayDataAt((m_mapx + 1) + y * Map->GetIsoSize(), 0x2); + + + } + } + + + + + //UpdateMap(); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + } + } + + CFinalSunDlg& dlg = *(CFinalSunDlg*)theApp.m_pMainWnd; + dlg.m_view.m_minimap.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + m_moved = FALSE; + + CView::OnLButtonUp(nFlags, point); +} + + + + +void CIsoView::TextOut(int x, int y, const char* text, COLORREF col) +{ + HDC hdc; + lpdsBack->GetDC(&hdc); + + SetTextColor(hdc, col); + SetBkMode(hdc, TRANSPARENT); + ::TextOut(hdc, x, y, text, strlen(text)); + + + lpdsBack->ReleaseDC(hdc); +} + +void CIsoView::TextOut(HDC hDC, int x, int y, const char* text, COLORREF col) +{ + SetTextColor(hDC, col); + SetBkMode(hDC, TRANSPARENT); + ::TextOut(hDC, x, y, text, strlen(text)); +} + + + +void CIsoView::OnMove(int x, int y) +{ + CView::OnMove(x, y); + + if (lpds == NULL) return; + LPDIRECTDRAWCLIPPER ddc; + + lpds->GetClipper(&ddc); + ddc->SetHWnd(0, m_hWnd); + updateFontScaled(); + + RedrawWindow(); +} + +void CIsoView::OnSize(UINT nType, int cx, int cy) +{ + // CView::OnSize(nType, cx, cy); + if (lpds == NULL) return; + + LPDIRECTDRAWCLIPPER ddc; + + lpds->GetClipper(&ddc); + ddc->SetHWnd(0, m_hWnd); + updateFontScaled(); + + CMyViewFrame& dlg = *(CMyViewFrame*)owner; + dlg.m_minimap.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + UpdateScrollRanges(); + + GetWindowRect(&m_myRect); +} + +COLORREF CIsoView::GetColor(const char* house, const char* vcolor) +{ + + COLORREF neutral = RGB(120, 120, 120); + COLORREF GDI = RGB(170, 170, 0); + COLORREF Nod = RGB(255, 0, 0); + COLORREF other = RGB(255, 255, 0); + + CString color; + CIniFile& ini = Map->GetIniFile(); + if (house && strlen(house)) + { + if (ini.sections.find(house) != ini.sections.end()) + { + color = ini.sections[house].values["Color"]; + } + else + color = rules.sections[house].values["Color"]; + } + + if (vcolor) + color = vcolor; + + if (color) + { + CString colorValues; + if (ini.sections.contains("Colors")) + { + colorValues = ini.sections["Colors"].GetValueByName(color); + } + if (colorValues.IsEmpty() && rules.sections.contains("Colors")) + { + colorValues = rules.sections["Colors"].GetValueByName(color); + } + auto colorArray = SplitParams(colorValues); + if (colorArray.size() == 3) + { + unsigned char hsv[3] = { static_cast(std::atoi(colorArray[0])), static_cast(std::atoi(colorArray[1])), static_cast(std::atoi(colorArray[2])) }; + unsigned char rgb[3]; + HSVToRGB(hsv, rgb); + return RGB(rgb[0], rgb[1], rgb[2]); + } + } + +#ifndef RA2_MODE + if (strstr(house, houses[0].name) != NULL) + { + return GDI; + } + else if (strstr(house, houses[1].name) != NULL) + { + return Nod; + } + else if (strstr(house, houses[2].name) != NULL) + { + return neutral; + } + else + { + if (isIncluded(color, "darkred") != NULL) + { + return Nod; + } + if (isIncluded(color, "grey") != NULL) + { + return RGB(120, 120, 120); + } + if (isIncluded(color, "gold") != NULL) + { + return GDI; + } + + + return other; + } +#else + if (isIncluded(color, "darkred") != NULL) + { + return RGB(130, 20, 20); + } + if (isIncluded(color, "grey") != NULL) + { + return RGB(120, 120, 120); + } + if (isIncluded(color, "red") != NULL) + { + return RGB(240, 20, 20); + } + if (isIncluded(color, "lightgold") != NULL) + { + return RGB(220, 220, 150); + } + if (isIncluded(color, "yellow") != NULL) + { + return RGB(240, 240, 0); + } + if (isIncluded(color, "gold") != NULL) + { + return RGB(230, 200, 0); + } + if (isIncluded(color, "darkgreen") != NULL) + { + return RGB(50, 160, 70); + } + if (isIncluded(color, "neongreen") != NULL) + { + return RGB(10, 255, 10); + } + if (isIncluded(color, "green") != NULL) + { + return RGB(50, 200, 70); + } + if (isIncluded(color, "darkblue") != NULL) + { + return RGB(30, 30, 150); + } + if (isIncluded(color, "lightblue") != NULL) + { + return RGB(100, 100, 200); + } + if (isIncluded(color, "neonblue") != NULL) + { + return RGB(35, 205, 255); + } + + { + return other; + } + +#endif + + +} + + + + +/* +GetOverlayPic(BYTE ovrl, BYTE ovrldata); + +Returns the picture that should be used to draw the overlay tile. +First checks if a explicite bitmap exists for this tile, if not +checks if it can be displayed by a standard bitmap. +For bridges, it also needs the overlaydata. +*/ +inline PICDATA* GetOverlayPic(BYTE ovrl, BYTE ovrldata) +{ + + char c[50]; + char d[50]; + itoa(ovrl, c, 10); + itoa(ovrldata, d, 10); + + CString fname = (CString)"OVRL" + c + "_" + d; + + // MessageBox(0,fname,"",0); + + if (pics.find(fname) != pics.end()) return &pics[fname]; + + //errstream << "pic " << (LPCSTR)fname << " not found" << endl; + + + return NULL; +} + + + + +void CIsoView::OnDraw(CDC* pDC) +{ + DrawMap(); +} + + +void CIsoView::ReInitializeDDraw() +{ + b_IsLoading = TRUE; + ReleaseCapture(); + KillTimer(11); + // rscroll=FALSE; + + + +#ifdef NOSURFACES + while ((GetDeviceCaps(::GetDC(::GetDesktopWindow()), BITSPIXEL) <= 8)) + { + if (MessageBox("You currently only have 8 bit color mode enabled. FinalAlert 2 does not work in 8 bit color mode. Please change the color mode and then click on OK. Click Cancel to quit (and save the map as backup.map).", "Error", MB_OKCANCEL) == IDCANCEL) + { + ((CFinalSunDlg*)theApp.m_pMainWnd)->SaveMap((u8AppDataPath + "\\backup.map").c_str()); + PostQuitMessage(0); + return; + } + } +#endif + + + CDynamicGraphDlg dlg; + + dlg.ShowWindow(SW_SHOW); + dlg.UpdateWindow(); + + dd->RestoreAllSurfaces(); + + updateFontScaled(); + + + missingimages.clear(); + + theApp.m_loading->FreeAll(); + theApp.m_loading->InitDirectDraw(); + theApp.m_loading->InitPics(); + theApp.m_loading->InitTMPs(&dlg.m_Progress); + + memset(ovrlpics, 0, max_ovrl_img * 0xFF * sizeof(LPDIRECTDRAWSURFACE4)); + //UpdateOverlayPictures(-1); + //Map->UpdateIniFile(MAPDATA_UPDATE_FROM_INI); + Map->UpdateBuildingInfo(); + Map->UpdateTreeInfo(); +#ifdef SMUDGE_SUPP + Map->UpdateSmudgeInfo(); +#endif + + + + b_IsLoading = FALSE; + + //Sleep(2500); + + + + dlg.DestroyWindow(); + + + + + + RedrawWindow(); + + + + /* + + CString CommandLine; + + if(res==IDYES) + { + CFileDialog dlg(FALSE, ".mpr", "noname.mpr", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "TS maps|*.mpr;*.map|TS multi maps|*.mpr|TS single maps|*.map|"); + do + { + + + char cuPath[MAX_PATH]; + + GetCurrentDirectory(MAX_PATH, cuPath); + dlg.m_ofn.lpstrInitialDir=cuPath; + + if(theApp.m_Options.TSExe.GetLength()) dlg.m_ofn.lpstrInitialDir=(char*)(LPCTSTR)theApp.m_Options.TSExe; + + }while(dlg.DoModal()==IDCANCEL) ; + + CommandLine=dlg.GetPathName(); + + ((CFinalSunDlg*)theApp.m_pMainWnd)->SaveMap(dlg.GetPathName()); + } + + if(res==IDNO || res==IDYES) + { + PROCESS_INFORMATION pi; + STARTUPINFO si; + memset(&si, 0, sizeof(STARTUPINFO)); + si.cb=sizeof(STARTUPINFO); + + char myExe[MAX_PATH]; + GetModuleFileName(NULL, myExe, MAX_PATH); + + BOOL success=CreateProcess(myExe, + (LPTSTR)(LPCTSTR)CommandLine, + NULL, + NULL, + FALSE, + NORMAL_PRIORITY_CLASS, + NULL, + AppPath, + &si, + &pi); + } + + theApp.m_pMainWnd->DestroyWindow();*/ + + + + + + /*CLoading load; + load.InitDirectDraw(); + load.InitMixFiles(); + load.InitPics(); + + + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + b_IsLoading=FALSE;*/ + + +} + +void CIsoView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + + + CView::OnChar(nChar, nRepCnt, nFlags); +} + +void CIsoView::OnDeadChar(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + + CView::OnDeadChar(nChar, nRepCnt, nFlags); +} + +void CIsoView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + int nPos; + + + + if (nChar == 68) // D key + { + theApp.m_Options.bFlat = !theApp.m_Options.bFlat; + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + if (nChar == 65) + m_bAltCliff = !m_bAltCliff; + + CView::OnKeyDown(nChar, nRepCnt, nFlags); +} + +void CIsoView::SetError(const char* text) +{ + CMyViewFrame& v = *((CMyViewFrame*)owner); + v.m_statbar.GetStatusBarCtrl().SetText(text, 0, 0); +} + + + + +int CIsoView::GetOverlayDirection(int x, int y) +{ + DWORD dwIsoSize = Map->GetIsoSize(); + int p = -1; + int type = Map->GetOverlayAt(x + y * dwIsoSize); + + BOOL isTrail = FALSE; + int i; + for (i = 0;i < overlay_count;i++) + if (overlay_number[i] == type) + if (overlay_trail[i]) isTrail = TRUE; + + if (isTrack(type)) // handling a train track + { + + + if (isTrack(Map->GetOverlayAt((x - 1) + (y - 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 1) + (y + 1) * dwIsoSize))) + return 0; + if (isTrack(Map->GetOverlayAt((x + 1) + (y - 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x - 1) + (y + 1) * dwIsoSize))) + return 1; + if (isTrack(Map->GetOverlayAt((x - 1) + (y - 0) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 1) + (y + 0) * dwIsoSize))) + return 2; + if (isTrack(Map->GetOverlayAt((x - 0) + (y - 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 0) + (y + 1) * dwIsoSize))) + return 3; + if (isTrack(Map->GetOverlayAt((x - 1) + (y - 0) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 1) + (y + 1) * dwIsoSize))) + return 4; + if (isTrack(Map->GetOverlayAt((x - 0) + (y - 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 1) + (y + 1) * dwIsoSize))) + return 5; + if (isTrack(Map->GetOverlayAt((x - 1) + (y - 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x - 0) + (y + 1) * dwIsoSize))) + return 6; + if (isTrack(Map->GetOverlayAt((x - 1) + (y - 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 1) + (y + 0) * dwIsoSize))) + return 7; + if (isTrack(Map->GetOverlayAt((x - 1) + (y - 0) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 1) + (y - 1) * dwIsoSize))) + return 8; + if (isTrack(Map->GetOverlayAt((x + 0) + (y + 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 1) + (y - 1) * dwIsoSize))) + return 9; + if (isTrack(Map->GetOverlayAt((x - 0) + (y - 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x - 1) + (y + 1) * dwIsoSize))) + return 10; + if (isTrack(Map->GetOverlayAt((x - 1) + (y + 1) * dwIsoSize)) && isTrack(Map->GetOverlayAt((x + 1) + (y + 0) * dwIsoSize))) + return 11; + if (isTrack(Map->GetOverlayAt((x - 1) + (y - 1) * dwIsoSize))) + return 0; + if (isTrack(Map->GetOverlayAt((x - 1) + (y + 1) * dwIsoSize))) + return 1; + if (isTrack(Map->GetOverlayAt((x - 1) + (y - 0) * dwIsoSize))) + return 2; + if (isTrack(Map->GetOverlayAt((x - 0) + (y - 1) * dwIsoSize))) + return 3; + if (isTrack(Map->GetOverlayAt((x + 1) + (y + 1) * dwIsoSize))) + return 0; + if (isTrack(Map->GetOverlayAt((x + 1) + (y - 1) * dwIsoSize))) + return 1; + if (isTrack(Map->GetOverlayAt((x + 1) + (y + 0) * dwIsoSize))) + return 2; + if (isTrack(Map->GetOverlayAt((x + 0) + (y + 1) * dwIsoSize))) + return 3; + + return 0; + } + else if (isTrail) // handling something like a sandbag + { + p = 0; + if (Map->GetOverlayAt(x - 1 + (y - 0) * dwIsoSize) == type) p |= 0x1; + if (Map->GetOverlayAt(x + (y + 1) * dwIsoSize) == type) p |= 0x2; + if (Map->GetOverlayAt(x + 1 + (y + 0) * dwIsoSize) == type) p |= 0x4; + if (Map->GetOverlayAt(x + (y - 1) * dwIsoSize) == type) p |= 0x8; + } + + return p; + +} + +void CIsoView::HandleTrail(int x, int y) +{ + int i, e; + int type = Map->GetOverlayAt(x + y * Map->GetIsoSize()); + + if (isTrack(type)) // is a track (overlay must be changed) + { + + for (i = x - 2;i <= x + 2;i++) + { + for (e = y - 1;e <= y + 1;e++) + { + if (isTrack(Map->GetOverlayAt(i + e * Map->GetIsoSize()))) + Map->SetOverlayAt(i + e * Map->GetIsoSize(), 0x27 + GetOverlayDirection(i, e)); + } + } + } + else // something like a sandbag (overlaydata must be changed) + { + + for (i = x - 2;i <= x + 2;i++) + { + for (e = y - 1;e <= y + 1;e++) + { + if (Map->GetOverlayAt(i + e * Map->GetIsoSize()) == type) + { + int dir = GetOverlayDirection(i, e); + if (dir >= 0) Map->SetOverlayDataAt(i + e * Map->GetIsoSize(), dir); + } + } + } + } + +} + + +/* +DrawCell(int x, int y, int w, int h, COLORREF col) + +Draws a frame around one or more cells. +w is the width, h is the height (in cells). +x and y are pixel coordinates. +col specifies the color. +*/ +void CIsoView::DrawCell(int x, int y, int w, int h, COLORREF col, BOOL dotted, HDC hDC_) +{ + + + // correct the y value: + //y -= f_y; + + POINT p1, p2, p3, p4; + p1.x = x + f_x / 2; + p1.y = y; + p2.x = x + w * f_x / 2 + f_x / 2; + p2.y = y + w * f_y / 2; + p3.x = x + w * f_x / 2 - h * f_x / 2 + f_x / 2 - 1; + p3.y = y + h * f_y / 2 + w * f_y / 2 - 1; + p4.x = x - h * f_x / 2 + f_x / 2 - 1; + p4.y = y + h * f_y / 2 - 1; + + HDC hDC = hDC_; + if (!hDC) + while (lpdsBack->GetDC(&hDC) == DDERR_WASSTILLDRAWING); + + HPEN p; + int width = 1; +#ifdef RA2_MODE + width = 2; +#endif + if (!dotted) p = CreatePen(PS_SOLID, width, col); + else p = CreatePen(PS_DOT, 0, col); + + SelectObject(hDC, p); + + if (dotted) + { + SetBkMode(hDC, TRANSPARENT); + MoveToEx(hDC, p1.x, p1.y - 1, NULL); + LineTo(hDC, p2.x + 1, p2.y); + LineTo(hDC, p3.x, p3.y + 1); + LineTo(hDC, p4.x - 1, p4.y); + LineTo(hDC, p1.x, p1.y - 1); + } + + if (!dotted) + { + MoveToEx(hDC, p1.x, p1.y, NULL); + LineTo(hDC, p2.x, p2.y); + LineTo(hDC, p3.x, p3.y); + LineTo(hDC, p4.x, p4.y); + LineTo(hDC, p1.x, p1.y); + } + + + + + + if (!hDC_) + lpdsBack->ReleaseDC(hDC); + + DeleteObject(p); +} + +void CIsoView::DrawCell(void* dest, int dest_width, int dest_height, int dest_pitch, int drawx, int drawy, int w, int h, int col, bool dotted, bool touchNeighbours, int colNeighbour) const +{ + if (colNeighbour == CLR_INVALID) + colNeighbour = col; + + // correct the y value: + //y -= f_y; + + POINT p1, p2, p3, p4; + p1.x = drawx + f_x / 2; + p1.y = drawy; + p2.x = drawx + w * f_x / 2 + f_x / 2; + p2.y = drawy + w * f_y / 2; + p3.x = drawx + w * f_x / 2 - h * f_x / 2 + f_x / 2; + p3.y = drawy + h * f_y / 2 + w * f_y / 2; + p4.x = drawx - h * f_x / 2 + f_x / 2; + p4.y = drawy + h * f_y / 2; + + LineDrawer drawer(dest, bpp, dest_width, dest_height, dest_pitch); + + const LineStyle style = dotted ? LineStyle::Dotted_4 : LineStyle::Standard; + + for (int x = 0; x < 1; ++x) // you could use this loop for more thickness + { + for (int y = 0; y < 1; ++y) + { + // inside the MM tile + drawer.MoveTo(p1.x + x + 1, p1.y + y + 1); + drawer.LineTo(p2.x + x - 2, p2.y + y - 1, col, style); + drawer.LineTo(p3.x + x + 1, p3.y + y - 3, col, style); + drawer.LineTo(p3.x + x, p3.y + y - 3, col, style); + drawer.LineTo(p4.x + x + 3, p4.y + y - 1, col, style); + drawer.LineTo(p4.x + x + 2, p4.y + y - 1, col, style); + drawer.MoveTo(p4.x + x + 3, p4.y + y - 1); + drawer.LineTo(p1.x + x, p1.y + y + 1, col, style); + drawer.LineTo(p1.x + x + 1, p1.y + y + 1, col, style); + + // on inner pixels of MM tile boundary + drawer.MoveTo(p1.x + x + 1, p1.y + y); + drawer.LineTo(p2.x + x, p2.y + y - 1, col, style); + drawer.LineTo(p3.x + x + 1, p3.y + y - 2, col, style); + drawer.LineTo(p3.x + x, p3.y + y - 2, col, style); + drawer.LineTo(p4.x + x + 1, p4.y + y - 1, col, style); + drawer.LineTo(p1.x + x, p1.y + y, col, style); + drawer.LineTo(p1.x + x + 1, p1.y + y, col, style); + } + } + + // pixels of neighboured MM tiles boundary + if (touchNeighbours) + { + for (int x = 0; x < 1; ++x) // you could use this loop for more thickness + { + for (int y = 0; y < 1; ++y) + { + drawer.MoveTo(p1.x + x + 1, p1.y + y - 1); + drawer.LineTo(p2.x + x - 2, p2.y + y - 3, colNeighbour, style); + drawer.MoveTo(p2.x + x - 2, p2.y + y - 2); + drawer.LineTo(p2.x + x - 1, p2.y + y, colNeighbour, style); + drawer.LineTo(p2.x + x, p2.y + y, colNeighbour, style); + drawer.LineTo(p3.x + x + 1, p3.y + y - 1, colNeighbour, style); + drawer.LineTo(p3.x + x, p3.y + y - 1, colNeighbour, style); + drawer.LineTo(p4.x + x + 1, p4.y + y, colNeighbour, style); + drawer.LineTo(p4.x + x, p4.y + y - 1, colNeighbour, style); + drawer.LineTo(p1.x + x, p1.y + y - 1, colNeighbour, style); + drawer.LineTo(p1.x + x + 1, p1.y + y - 1, colNeighbour, style); + } + } + } +} + +void CIsoView::DrawTube(const CTube& tube, const DDSURFACEDESC2* lockedDDSD, const COLORREF* color) const +{ + SurfaceLocker locker(lpdsBack); + + if (!lockedDDSD || !lockedDDSD->lpSurface) + { + lockedDDSD = locker.ensure_locked(); + } + if (!lockedDDSD) + return; + + // TODO: culling if required + + // find out if we are tube #1 or #2 for bidirectional tubes + bool type0 = tube.getStartX() == tube.getEndX() ? (tube.getStartY() < tube.getEndY()) : (tube.getStartX() < tube.getEndX()); + const auto col = color ? m_color_converter->GetColor(*color) : (type0 ? m_color_converter->GetColor(255, 0, 0) : m_color_converter->GetColor(0, 0, 255)); + ProjectedVec lineOffset = type0 ? ProjectedVec() : ProjectedVec(1, 1); + + int lowestHeight = min(Map->GetHeightAt(tube.getStartCoords()), Map->GetHeightAt(tube.getEndCoords())); + LineDrawer ld(lockedDDSD->lpSurface, bpp, lockedDDSD->dwWidth, lockedDDSD->dwHeight, lockedDDSD->lPitch); + auto startDraw = GetRenderTargetCoordinates(tube.getStartCoords(), lowestHeight); + ld.MoveTo(startDraw.x + f_x / 2 + lineOffset.x, startDraw.y + f_y / 2 + lineOffset.y); + + + tube.walk([this, &tube, lockedDDSD, &ld, lowestHeight, col, lineOffset](const auto& wi) { + auto draw = GetRenderTargetCoordinates(wi.pos, lowestHeight); + if (wi.pos == tube.getEndCoords()) + { + // end coordinates are drawn as cross + LineDrawer startLD(lockedDDSD->lpSurface, bpp, lockedDDSD->dwWidth, lockedDDSD->dwHeight, lockedDDSD->lPitch); + ProjectedVec off(7, 4); + startLD.DrawLine(draw.x + off.x, draw.y + f_y / 2, draw.x + f_x - off.x, draw.y + f_y / 2, col); + startLD.DrawLine(draw.x + f_x / 2 - 1, draw.y + off.y, draw.x + f_x / 2 - 1, draw.y + f_y - off.y, col); + } + if (wi.pos == tube.getStartCoords()) + { + // Start coordinates are drawn as cell + DrawCell(lockedDDSD->lpSurface, lockedDDSD->dwWidth, lockedDDSD->dwHeight, lockedDDSD->lPitch, draw.x, draw.y, 1, 1, col, true); + } + ld.LineTo(draw.x + f_x / 2 + lineOffset.x, draw.y + f_y / 2 + lineOffset.y, col); + return true; + }); +} + +MapCoords CIsoView::GetMapCoordinates(const ProjectedCoords& projCoords, bool bAllowAccessBehindCliffs, bool ignoreHideFlagsAndOutside) const +{ + return theApp.m_Options.bFlat ? Map->ToMapCoords(projCoords) : Map->ToMapCoords3d(projCoords, bAllowAccessBehindCliffs, ignoreHideFlagsAndOutside); +} + +MapCoords CIsoView::GetMapCoordinatesFromRenderTargetCoordinates(const ProjectedCoords& projCoords, bool bAllowAccessBehindCliffs, bool ignoreHideFlagsAndOutside) const +{ + return GetMapCoordinates(projCoords + m_viewOffset, bAllowAccessBehindCliffs, ignoreHideFlagsAndOutside); +} + +MapCoords CIsoView::GetMapCoordinatesFromClientCoordinates(const CPoint& clientPt, bool bAllowAccessBehindCliffs, bool ignoreHideFlagsAndOutside) const +{ + return GetMapCoordinates(GetProjectedCoordinatesFromClientCoordinates(clientPt), bAllowAccessBehindCliffs, ignoreHideFlagsAndOutside); +} + +ProjectedCoords CIsoView::GetProjectedCoordinatesFromClientCoordinates(const CPoint& clientPt) const +{ + RECT r; + GetWindowRect(&r); + const auto viewOffsetWR = m_viewOffset + ProjectedVec(r.left, r.top); + const auto projCoords = ProjectedCoords(clientPt.x * m_viewScale.x, clientPt.y * m_viewScale.y) + viewOffsetWR; + return projCoords; +} + +ProjectedCoords CIsoView::GetProjectedCoordinates(const MapCoords& mapCoords) const +{ + return theApp.m_Options.bFlat ? Map->ProjectCoords(mapCoords) : Map->ProjectCoords3d(mapCoords); +} + +ProjectedCoords CIsoView::GetProjectedCoordinates(const MapCoords& mapCoords, int mapZ) const +{ + return Map->ProjectCoords3d(mapCoords, mapZ); +} + +ProjectedCoords CIsoView::GetRenderTargetCoordinates(const MapCoords& mapCoords) const +{ + // Draw coordinates are display coordinates + return GetProjectedCoordinates(mapCoords) - m_viewOffset; +} + +ProjectedCoords CIsoView::GetRenderTargetCoordinates(const MapCoords& mapCoords, int mapZ) const +{ + return GetProjectedCoordinates(mapCoords, mapZ) - m_viewOffset; +} + +CPoint CIsoView::GetClientCoordinates(const MapCoords& mapCoords) const +{ + RECT r; + GetWindowRect(&r); + const auto windowPos = ProjectedVec(r.left, r.top); + //const auto p = ScaleBackToFrontBuffer(GetRenderTargetCoordinates(mapCoords)) - windowPos; + const auto rtc = GetRenderTargetCoordinates(mapCoords); + const auto p = ((ProjectedCoords(rtc.x, rtc.y) - windowPos) / m_viewScale).convertT(); + return CPoint(p.x, p.y); +} + +CPoint CIsoView::GetClientCoordinatesFromWorld(const ProjectedCoords& projectedCoords) const +{ + RECT r; + GetWindowRect(&r); + const auto windowPos = ProjectedVec(r.left, r.top); + //const auto p = ScaleBackToFrontBuffer(GetRenderTargetCoordinates(mapCoords)) - windowPos; + const auto rtc = projectedCoords - m_viewOffset; + const auto p = ((ProjectedCoords(rtc.x, rtc.y)) / m_viewScale).convertT(); + return CPoint(p.x, p.y); +} + +ProjectedCoords CIsoView::ScaleBackToFrontBuffer(const ProjectedCoords& backBufferCoords) const +{ + RECT r; + GetWindowRect(&r); + const auto windowPos = ProjectedVec(r.left, r.top); + return ((ProjectedCoords(backBufferCoords.x, backBufferCoords.y) - windowPos) / m_viewScale).convertT() + windowPos; +} + + +void CIsoView::UpdateStatusBar(int x, int y) +{ + CString statusbar;//=TranslateStringACP("Ready"); + + FIELDDATA m = *Map->GetFielddataAt(x + y * Map->GetIsoSize()); + if (m.wGround == 0xFFFF) m.wGround = 0; + + if (m.wGround < (*tiledata_count) && m.bSubTile < (*tiledata)[m.wGround].wTileCount) + { + statusbar = "Terrain type: 0x"; + char c[50]; + itoa((*tiledata)[m.wGround].tiles[m.bSubTile].bTerrainType, c, 16); + statusbar += c; + statusbar += ", height: "; + itoa(m.bHeight, c, 10); + statusbar += c; + statusbar += " / "; + } + + + if (Map->GetOverlayAt(x + y * Map->GetIsoSize()) != 0xFF) + { + char ov[50]; + itoa(Map->GetOverlayAt(x + y * Map->GetIsoSize()), ov, 16); + + int i; + CString name; + name = "0x"; + name += ov; + for (i = 0;i < overlay_count;i++) + { + if (overlay_number[i] == Map->GetOverlayAt(x + y * Map->GetIsoSize())) + name = overlay_name[i]; + } + + + itoa(Map->GetOverlayDataAt(x + y * Map->GetIsoSize()), ov, 16); + + statusbar += GetLanguageStringACP("OvrlStatus"); + statusbar += TranslateStringACP(name); + statusbar += ", OverlayData: 0x"; + statusbar += ov; + } + + STDOBJECTDATA sod; + sod.type = ""; + + int n = Map->GetStructureAt(x + y * Map->GetIsoSize()); + int on = -1; + if (n >= 0) + { + + Map->GetStdStructureData(n, &sod); + statusbar = GetLanguageStringACP("StructStatus"); + on = n; + } + + n = Map->GetUnitAt(x + y * Map->GetIsoSize()); + if (n >= 0) + { + + Map->GetStdUnitData(n, &sod); + statusbar = GetLanguageStringACP("UnitStatus"); + on = n; + + } + + n = Map->GetAirAt(x + y * Map->GetIsoSize()); + if (n >= 0) + { + + Map->GetStdAircraftData(n, &sod); + statusbar = GetLanguageStringACP("AirStatus"); + on = n; + } + + n = Map->GetInfantryAt(x + y * Map->GetIsoSize()); + if (n >= 0) + { + Map->GetStdInfantryData(n, &sod); + statusbar = GetLanguageStringACP("InfStatus"); + on = n; + } + + if (sod.type.GetLength() > 0) + { + char c[50]; + itoa(on, c, 10); + statusbar += "ID "; + statusbar += c; + statusbar += ", "; + + statusbar += TranslateStringACP(Map->GetUnitName(sod.type)); + statusbar += " ("; + + statusbar += TranslateHouse(sod.house, TRUE); + statusbar += ", "; + statusbar += sod.type; + statusbar += ")"; + } + + /* + // activate this code to display information about the mappack! + + statusbar="MAPPACK: "; + int i; + FIELDDATA td=Map->GetFielddataAt(x+y*Map->GetIsoSize()); + char c[50]; + itoa(td.wGround, c, 10); + statusbar+="tile: "; + statusbar+=c; + statusbar+=" "; + for(i=0;i<3;i++) + { + itoa(td.bMapData[i], c, 10); + statusbar+=c; + statusbar+=" "; + } + + statusbar+=" height: "; + itoa(td.bHeight, c, 10); + statusbar+=c; + statusbar+=" "; + itoa(td.bMapData2[0],c,10); + statusbar+=c;*/ + + + n = Map->GetCelltagAt(x + y * Map->GetIsoSize()); + if (n >= 0) + { + CString type; + CString name; + DWORD pos; + Map->GetCelltagData(n, &type, &pos); + CIniFile& ini = Map->GetIniFile(); + if (ini.sections["Tags"].values.find(type) != ini.sections["Tags"].values.end()) + name = GetParam(ini.sections["Tags"].values[type], 1); + + statusbar += GetLanguageStringACP("CellTagStatus"); + statusbar += name; + statusbar += " ("; + statusbar += type; + statusbar += ")"; + } + + if (AD.mode == ACTIONMODE_SETTILE) + { + statusbar = GetLanguageStringACP("TilePlaceStatus"); + } + + if (AD.mode == ACTIONMODE_COPY) + statusbar = GetLanguageStringACP("CopyHelp"); + + if (statusbar.GetLength() > 0) + SetError(statusbar); + +} + +void CIsoView::UpdateOverlayPictures(int id) +{ + if (id < 0) + { + memset(ovrlpics, 0, max_ovrl_img * 0xFF * sizeof(LPDIRECTDRAWSURFACE4)); + + int i, e; + for (i = 0;i < 0xFF;i++) + { + for (e = 0;e < max_ovrl_img;e++) + { + /*PICDATA& p=GetOverlayPic(i, e); + if(p.pic!=NULL) ovrlpics[i][e]=&p; + else + ovrlpics[i][e]=NULL;*/ + ovrlpics[i][e] = GetOverlayPic(i, e); + } + } + } + else + { + int e; + for (e = 0;e < max_ovrl_img;e++) + { + ovrlpics[id][e] = GetOverlayPic(id, e); + } + } +} + + +__forceinline void FixTileHeight(DWORD dwPos, int x, int y) +{ + return; // we use CMapData::CreateSlopes() to fix slopes now + + int oheight = Map->GetHeightAt(dwPos); + int isosize = Map->GetIsoSize(); + + char bHeightDiff[9]; + + int i, e; + for (i = -1;i < 2;i++) + { + for (e = -1;e < 2;e++) + { + if (x + i < 0 || y + e < 0 || x + i >= isosize || y + e >= isosize) bHeightDiff[i + 1 + (e + 1) * 3] = 0; + else + bHeightDiff[i + 1 + (e + 1) * 3] = oheight - Map->GetHeightAt(dwPos + i + e * isosize); + } + } + + if (bHeightDiff[1] < 0 && bHeightDiff[7] < 0) + { + Map->SetHeightAt(dwPos, oheight + 1); + return; + } + if (bHeightDiff[3] < 0 && bHeightDiff[5] < 0) + { + Map->SetHeightAt(dwPos, oheight + 1); + return; + } + + if ( + (bHeightDiff[1] < 0 && bHeightDiff[6] < 0) || + (bHeightDiff[1] < 0 && bHeightDiff[8] < 0) /*|| + (bHeightDiff[3]<0 && bHeightDiff[2]<0) || + (bHeightDiff[3]<0 && bHeightDiff[8]<0) || + (bHeightDiff[5]<0 && bHeightDiff[0]<0) || + (bHeightDiff[5]<0 && bHeightDiff[6]<0) || + (bHeightDiff[7]<0 && bHeightDiff[0]<0) || + (bHeightDiff[7]<0 && bHeightDiff[2]<0) */ + ) + { + Map->SetHeightAt(dwPos, oheight + 1); + return; + } +} + + +/* +ChangeTileHeight(); + +General routine for changing the height of a tile. +Warning: This routine calls itself if necessary, and therefore may be quite performance hungry! +*/ +void __fastcall CIsoView::ChangeTileHeight(DWORD dwPos, DWORD dwNewHeight, BOOL bNonMorpheableMove, BOOL bOnlyThisTile, BOOL bNoSlopes) +{ + int isosize = Map->GetIsoSize(); + int mapsize = isosize * isosize; + int mapwidth = Map->GetWidth(); + int mapheight = Map->GetHeight(); + + int dwX = dwPos % isosize; + int dwY = dwPos / isosize; + + //if(dwX==0 || dwY==0 || dwX+dwYmapwidth+mapheight*2 || (dwY>mapwidth && dwXmapwidth && dwY+mapwidthmapwidth+mapheight*2 || (dwY+2>mapwidth && dwX-2mapwidth && dwY+mapwidth-2mapwidth + mapheight * 2 || (dwY + 1 > mapwidth && dwX - 1 < dwY - mapwidth) || (dwX + 1 > mapwidth && dwY + mapwidth - 1 < dwX)) return; + + + + FIELDDATA orig_fd = *Map->GetFielddataAt(dwPos); + + //if(bOnlyHeighten && dwNewHeight m_funcRect.right) m_funcRect.right = dwX; + if (dwY > m_funcRect.bottom) m_funcRect.bottom = dwY; + + BOOL bCliffNext = FALSE; + /*if(bOnlyHeighten) + { + bCliffNext=FALSE; + /*int i; + int e; + for(i=-1;i<2;i++) + { + for(e=-1;e<2;e++) + { + int pos=dwPos+i+(e)*isosize; + + FIELDDATA fd=*Map->GetFielddataAt(pos); + if(fd.wGround==0xFFFF) fd.wGround=0; + + if((*tiledata)[fd.wGround].wTileSet==cliffset || fd.bCliffHack) + { + bCliffNext=TRUE; + break; + } + } + if(bCliffNext) break; + }*//* + + }*/ + + Map->SetReserved(dwPos, 1); + + + if (!(*tiledata)[orig_ground].bMorphable) bNonMorpheableMove = TRUE; + + Map->SetHeightAt(dwPos, dwNewHeight); + + + int i, e; + for (i = -1;i < 2;i++) + { + for (e = -1;e < 2;e++) + { + + int pos = dwPos + i + (e)*isosize; + + FIELDDATA fd = *Map->GetFielddataAt(pos); + if (fd.wGround == 0xFFFF) fd.wGround = 0; + + BOOL bAllowed = TRUE; + + if (dwX == 0 && i == -1) bAllowed = FALSE; + else if (dwY == 0 && e == -1) bAllowed = FALSE; + else if (dwX == isosize - 1 && i == 1) bAllowed = FALSE; + else if (dwY == isosize - 1 && e == 1) bAllowed = FALSE; + + + if (bOnlyThisTile) + { + if (fd.wGround != orig_fd.wGround) bAllowed = FALSE; // was another tile + + else + { + // we now need to check if it is really the same tile or just the same tile type (!) + int of = orig_fd.bSubTile; + int f = fd.bSubTile; + int width = (*tiledata)[orig_ground].cy; + int height = (*tiledata)[orig_ground].cx; + int ox = of / width; + int oy = of % width; + int x = f / width; + int y = f % width; + + if (x - ox != i || y - oy != e) bAllowed = FALSE; + } + } + + + int ground = fd.wGround; + + + if (bAllowed && !fd.bReserved && pos > 0 && pos < mapsize) + { + + + + + BOOL bDestMorphable = (*tiledata)[fd.wGround].bMorphable; + TILEDATA destTile = (*tiledata)[fd.wGround]; + TILEDATA sourceTile = (*tiledata)[orig_fd.wGround]; + + if (bAllowed && (!bNonMorpheableMove || bDestMorphable)) + { + if (e == 1 && i == 1) + { + int leftGround = Map->GetFielddataAt(dwPos + 1)->wGround; + int rightGround = Map->GetFielddataAt(dwPos + isosize)->wGround; + if (leftGround == 0xFFFF) leftGround = 0; + if (rightGround == 0xFFFF) rightGround = 0; + if (!(*tiledata)[leftGround].bMorphable && !(*tiledata)[rightGround].bMorphable) + bAllowed = FALSE; + } + if (e == -1 && i == -1) + { + int leftGround = Map->GetFielddataAt(dwPos - 1)->wGround; + int rightGround = Map->GetFielddataAt(dwPos - isosize)->wGround; + if (leftGround == 0xFFFF) leftGround = 0; + if (rightGround == 0xFFFF) rightGround = 0; + if (!(*tiledata)[leftGround].bMorphable && !(*tiledata)[rightGround].bMorphable) + bAllowed = FALSE; + } + if (e == -1 && i == 1) + { + int leftGround = Map->GetFielddataAt(dwPos - 1)->wGround; + int rightGround = Map->GetFielddataAt(dwPos + isosize)->wGround; + if (leftGround == 0xFFFF) leftGround = 0; + if (rightGround == 0xFFFF) rightGround = 0; + if (!(*tiledata)[leftGround].bMorphable && !(*tiledata)[rightGround].bMorphable) + bAllowed = FALSE; + } + if (e == 1 && i == -1) + { + int leftGround = Map->GetFielddataAt(dwPos + 1)->wGround; + int rightGround = Map->GetFielddataAt(dwPos - isosize)->wGround; + if (leftGround == 0xFFFF) leftGround = 0; + if (rightGround == 0xFFFF) rightGround = 0; + if (!(*tiledata)[leftGround].bMorphable && !(*tiledata)[rightGround].bMorphable) + bAllowed = FALSE; + } + } + + + + + + + if (/*(*tiledata)[ground].bMorphable &&*/ bAllowed) + { + int need_diff = (*tiledata)[ground].tiles[fd.bSubTile].bZHeight - (*tiledata)[orig_ground].tiles[orig_fd.bSubTile].bZHeight; + + + //if(Map->GetHeightAt(pos)-dwNewHeight!=need_diff || !bNonMorpheableMove) + { + int diff = fd.bHeight - dwNewHeight; + + /* + Activate this code to use the huge slopes + Removed because it did look worse than the normal slopes + */ + /* + if(i && abs(i)==abs(e)) + { + if(diff<-1) diff++; + if(diff>1) diff--; + }*/ + + + if (!bNonMorpheableMove && bDestMorphable) + { + //if(!bOnlyHeighten)//!bCliffNext) + { + if (diff < -1) + ChangeTileHeight(pos, dwNewHeight - 1, bNonMorpheableMove, bOnlyThisTile, bNoSlopes); + if (diff > 1) + ChangeTileHeight(pos, dwNewHeight + 1, bNonMorpheableMove, bOnlyThisTile, bNoSlopes); + } + /*else + { + ChangeTileHeight(pos, dwNewHeight, bNonMorpheableMove, bOnlyThisTile, bOnlyHeighten); + }*/ + } + else if (bNonMorpheableMove) + { + if (!bDestMorphable /*&& (*tiledata)[fd.wGround].wTileSet==(*tiledata)[orig_fd.wGround].wTileSet*/ /*&& need_diff!=fd.bHeight-orig_fd.bHeight*/) + { + if (destTile.tiles[fd.bSubTile].bTerrainType == sourceTile.tiles[orig_fd.bSubTile].bTerrainType || destTile.wTileSet == sourceTile.wTileSet) + { + ChangeTileHeight(pos, dwNewHeight + need_diff, TRUE, bOnlyThisTile, bNoSlopes); + } + } + else if (bDestMorphable /*&& need_diff!=fd.bHeight-orig_fd.bHeight*/) + { + //diff-=need_diff; + + if ((sourceTile.cx > 1 && sourceTile.cy > 1 && (e < 0 && i < 0)) || ((sourceTile.cx < 2 || sourceTile.cy < 2) && (e > 0 && i > 0))) + { + ChangeTileHeight(pos, dwNewHeight, FALSE, bOnlyThisTile, bNoSlopes); + } + else + { + if (diff - need_diff > 0) + ChangeTileHeight(pos, dwNewHeight + need_diff, FALSE, bOnlyThisTile, bNoSlopes); + else if (diff - need_diff < 0) + ChangeTileHeight(pos, dwNewHeight + need_diff, FALSE, bOnlyThisTile, bNoSlopes); + } + + } + } + + } + } + } + } + } + + /*for(i=-1;i<2;i++) + { + for(e=-1;e<2;e++) + { + FixTileHeight(dwPos+i+e*isosize, dwX+i, dwY+e); + } + }*/ + + if (!bNoSlopes) + { + for (i = -1;i < 2;i++) + { + for (e = -1;e < 2;e++) + { + int pos = dwPos + i + (e)*isosize; + if (pos > 0 && pos < mapsize) + Map->CreateSlopesAt(pos); + } + } + } + +} + +BOOL CIsoView::ReachableFrom(DWORD dwStart, DWORD dwEnd) +{ + FIELDDATA orig_fd = *Map->GetFielddataAt(dwStart); + if (orig_fd.wGround == 0xFF) orig_fd.wGround = 0; + int orig_ground = orig_fd.wGround; + + if (orig_fd.bReserved) return FALSE; + orig_fd.bReserved = 1; + + if (dwStart == dwEnd) return TRUE; + + + int i, e; + for (i = -1;i < 2;i++) + { + for (e = -1;e < 2;e++) + { + int new_ground = orig_fd.wGround; + if (new_ground == 0xFFFF) new_ground = 0; + + if (!(*tiledata)[new_ground].bMorphable && ReachableFrom(dwStart + i + e * Map->GetIsoSize(), dwEnd)) + return TRUE; + } + } + + return FALSE; +} + +void CIsoView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + CView::OnKeyUp(nChar, nRepCnt, nFlags); +} + +void CIsoView::HideTileSet(DWORD dwTileSet) +{ + int i; + for (i = 0;i < *tiledata_count;i++) + { + if ((*tiledata)[i].wTileSet == dwTileSet) (*tiledata)[i].bHide = TRUE; + } +} + +void CIsoView::BlitBackbufferToHighRes() +{ + // MW: + // the primary buffer and the (optional) high-res buffer cover the whole screen (Windows automatic high DPI scaling does not change this) + // the backbuffer also has the size of the whole screen, however we don't render to the whole screen + // we only render to the visible window rectangle (which IS affected by Windows' automatic DPI scaling features) + // Additionally, we have a user-controlled scale factor. + // If the user zooms in, we only render to a smaller part of the backbuffer and stretch it to the window rectangle (which may then again be stretched by Windows DPI if enabled in the Windows settings). + // the rectangle we render to has the same left/top border but a lower value for right/bottom. + // + // This is a simple scaling and also scales any text that has already been rendered to the backbuffer (which is why we're usually rendering text afterwards to the HighRes backbuffer). + // Altogether it'd probably be best to move from DirectDraw to Direct3D, support high DPI awareness and do the scaling right when initially drawing the map. + + + if (m_viewScale != Vec2(1.0f, 1.0f) && lpdsBackHighRes) + { + // copy scene backbuffer to the high-res buffer that will receive text rendering + RECT dr; + GetWindowRect(&dr); + auto cr = GetScaledDisplayRect(); + lpdsBackHighRes->Blt(&dr, lpdsBack, &cr, DDBLT_WAIT, 0); + } + else + { + // do nothing, backbuffer will receive additional text rendering as text doesn't have to be scaled + } +} + +void CIsoView::FlipHighResBuffer() +{ + if (m_viewScale != Vec2(1.0f, 1.0f) && lpdsBackHighRes) + { + // This flip copies the high-res backbuffer to the front buffer + RECT dr; + GetWindowRect(&dr); + lpds->Blt(&dr, lpdsBackHighRes, &dr, DDBLT_WAIT, 0); + } + else + { + // copy scene backbuffer to the front buffer that will receive text/gdi rendering + RECT dr; + GetWindowRect(&dr); + auto cr = GetScaledDisplayRect(); + lpds->Blt(&dr, lpdsBack, &cr, DDBLT_WAIT, 0); + } +} + +void CIsoView::ShowAllTileSets() +{ + int i; + for (i = 0;i < *tiledata_count;i++) + { + (*tiledata)[i].bHide = FALSE; + } +} + + + +void CIsoView::PlaceCurrentObjectAt(int x, int y) +{ + if (AD.mode == ACTIONMODE_RANDOMTERRAIN) + { + if (Map->GetTerrainAt(x + y * Map->GetIsoSize()) >= 0) + { + return; + } + + CString s; + + int n = rand() * rndterrainsrc.size() / RAND_MAX; + + // safety checks... + if (n >= rndterrainsrc.size()) n = rndterrainsrc.size() - 1; + if (n < 0) n = 0; + + s = rndterrainsrc[n]; + + Map->AddTerrain(s, x + y * Map->GetIsoSize()); + + return; + } + + if (AD.type == 1) // ADD INFANTRY + { + if (Map->GetInfantryCountAt(x + y * Map->GetIsoSize()) >= SUBPOS_COUNT) + { + return; + } + + Map->AddInfantry(NULL, AD.data_s, currentOwner, x + y * Map->GetIsoSize()); + //RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (AD.type == 2) // add structure + { + int n = Map->GetStructureAt(x + y * Map->GetIsoSize()); + if (n >= 0) + { + STDOBJECTDATA sod; + Map->GetStdStructureData(n, &sod); + if (strcmp(sod.type, "GAPAVE") != NULL) + { + //isMoving=FALSE; + return; + } + } + + + Map->AddStructure(NULL, AD.data_s, currentOwner, x + y * Map->GetIsoSize()); + //RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (AD.type == 3) // add aircraft + { + + if (Map->GetAirAt(x + y * Map->GetIsoSize()) >= 0) + { + return; + } + + Map->AddAircraft(NULL, AD.data_s, currentOwner, x + y * Map->GetIsoSize()); + + //RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (AD.type == 4) // add vehicle + { + if (Map->GetUnitAt(x + y * Map->GetIsoSize()) >= 0) + { + return; + } + + Map->AddUnit(NULL, AD.data_s, currentOwner, x + y * Map->GetIsoSize()); + + //RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (AD.type == 5) // add terrain + { + if (Map->GetTerrainAt(x + y * Map->GetIsoSize()) >= 0) + { + return; + } + + Map->AddTerrain(AD.data_s, x + y * Map->GetIsoSize()); + + //RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (AD.type == 6) + { + // Overlay + + + + DWORD dwPos = x + y * Map->GetIsoSize(); + + FIELDDATA m = *Map->GetFielddataAt(dwPos); + if (m.wGround == 0xFFFF) m.wGround = 0; + + BYTE oldOverlay = Map->GetOverlayAt(dwPos); + BYTE oldOverlayData = Map->GetOverlayDataAt(dwPos); + + if (AD.data == 1) // delete overlay + { + int gx, gy; + for (gx = x - AD.data2;gx <= x + AD.data2;gx++) + { + for (gy = y - AD.data2;gy <= y + AD.data2;gy++) + { + Map->SetOverlayDataAt(gx + gy * Map->GetIsoSize(), 0xFF); + Map->SetOverlayAt(gx + gy * Map->GetIsoSize(), 0xFF); + + + HandleTrail(gx - 1, gy - 1); + HandleTrail(gx + 1, gy - 1); + HandleTrail(gx - 1, gy + 1); + HandleTrail(gx + 1, gy + 1); + HandleTrail(gx - 0, gy - 1); + HandleTrail(gx + 0, gy + 1); + HandleTrail(gx - 1, gy + 0); + HandleTrail(gx + 1, gy + 0); + } + } + + + } + else if (AD.data == 2) // green tiberium mode + { + + { + if (AD.data2 == 0) + { + int i, e; + for (i = 0;i < m_BrushSize_x;i++) + { + for (e = 0;e < m_BrushSize_y;e++) + { + int curground = Map->GetFielddataAt(dwPos + i + e * Map->GetIsoSize())->wGround; + if (curground == 0xFFFF) curground = 0; + + if ((*tiledata)[curground].bAllowTiberium) + { + //srand( GetTickCount()+i+e*5 ); + int v1 = ((float)rand() / (float)RAND_MAX) * 8.0f + 0x68; + int v2 = ((float)rand() / (float)RAND_MAX) * 8.0f + 1; + Map->SetOverlayAt(dwPos + i + e * Map->GetIsoSize(), v1); + Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), v2); + } + } + } + } + else if (AD.data2 == 10) + { + int i, e; + for (i = 0;i < m_BrushSize_x;i++) + { + for (e = 0;e < m_BrushSize_y;e++) + { + int curground = Map->GetFielddataAt(dwPos + i + e * Map->GetIsoSize())->wGround; + if (curground == 0xFFFF) curground = 0; + + if ((*tiledata)[curground].bAllowTiberium) + { + Map->SetOverlayAt(dwPos + i + e * Map->GetIsoSize(), 0x70); + Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), 0x5); + } + } + } + } + else if (AD.data2 == 20) + { + int i, e; + for (i = 0;i < m_BrushSize_x;i++) + { + for (e = 0;e < m_BrushSize_y;e++) + { + int ovrl = Map->GetOverlayAt(dwPos + i + e * Map->GetIsoSize()); + if (ovrl > 0x65 && ovrl < 0x72) + { + if (Map->GetOverlayDataAt(i + e * Map->GetIsoSize() + dwPos) < 9) Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), Map->GetOverlayDataAt(dwPos + i + e * Map->GetIsoSize()) + 1); + } + } + } + } + else if (AD.data2 == 21) + { + + int i, e; + for (i = 0;i < m_BrushSize_x;i++) + { + for (e = 0;e < m_BrushSize_y;e++) + { + int ovrl = Map->GetOverlayAt(dwPos + i + e * Map->GetIsoSize()); + if (ovrl > 0x65 && ovrl < 0x72) + { + if (Map->GetOverlayDataAt(dwPos + i + e * Map->GetIsoSize()) > 0) Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), Map->GetOverlayDataAt(dwPos + i + e * Map->GetIsoSize()) - 1); + } + } + } + } + } + + } + else if (AD.data == 3) // blue tiberium mode + { + int o = 0x7f; +#ifdef RA2_MODE + o = 0x1e; +#endif + //if((*tiledata)[m.wGround].bAllowTiberium) + { + if (AD.data2 == 0) + { + + int i, e; + for (i = 0;i < m_BrushSize_x;i++) + { + for (e = 0;e < m_BrushSize_y;e++) + { + int curground = Map->GetFielddataAt(dwPos + i + e * Map->GetIsoSize())->wGround; + if (curground == 0xFFFF) curground = 0; + + if ((*tiledata)[curground].bAllowTiberium) + { + + int v2 = ((float)rand() / (float)RAND_MAX) * 8 + 1; + Map->SetOverlayAt(dwPos + i + e * Map->GetIsoSize(), o); + Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), v2); + } + } + } + + } + else if (AD.data2 == 10) + { + int i, e; + for (i = 0;i < m_BrushSize_x;i++) + { + for (e = 0;e < m_BrushSize_y;e++) + { + int curground = Map->GetFielddataAt(dwPos + i + e * Map->GetIsoSize())->wGround; + if (curground == 0xFFFF) curground = 0; + + if ((*tiledata)[curground].bAllowTiberium) + { + Map->SetOverlayAt(dwPos + i + e * Map->GetIsoSize(), o); + Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), 0x5); + } + } + } + } + else if (AD.data2 == 20) + { + int i, e; + for (i = 0;i < m_BrushSize_x;i++) + { + for (e = 0;e < m_BrushSize_y;e++) + { + int ovrl = Map->GetOverlayAt(dwPos + i + e * Map->GetIsoSize()); + if (ovrl == o) + { + if (Map->GetOverlayDataAt(dwPos + i + e * Map->GetIsoSize()) < 9) Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), Map->GetOverlayDataAt(dwPos + i + e * Map->GetIsoSize()) + 1); + } + } + } + } + else if (AD.data2 == 21) + { + int i, e; + for (i = 0;i < m_BrushSize_x;i++) + { + for (e = 0;e < m_BrushSize_y;e++) + { + int ovrl = Map->GetOverlayAt(dwPos + i + e * Map->GetIsoSize()); + if (ovrl == o) + { + if (Map->GetOverlayDataAt(dwPos + i + e * Map->GetIsoSize()) > 0) Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), Map->GetOverlayDataAt(dwPos + i + e * Map->GetIsoSize()) - 1); + } + } + } + } + } + + } + else if (AD.data == 4) // veinhole stuff mode + { + if (AD.data2 == 0) // Set veinhole! + { + int gx, gy; + for (gx = x - 1;gx <= x + 1;gx++) + { + for (gy = y - 1;gy <= y + 1;gy++) + { + Map->SetOverlayAt(gx + gy * Map->GetIsoSize(), OVRL_VEINHOLEBORDER); + Map->SetOverlayDataAt(gx + gy * Map->GetIsoSize(), 0x0); + } + } + Map->SetOverlayAt(dwPos, OVRL_VEINHOLE); + Map->SetOverlayDataAt(dwPos, 0x0); + Map->SetHeightAt(dwPos, Map->GetHeightAt(dwPos) - 1); + } + else if (AD.data2 == 1) // set veins + { + Map->SetOverlayAt(dwPos, OVRL_VEINS); + Map->SetOverlayDataAt(dwPos, 0x30); + } + + } + else if (AD.data == 30) // any overlay + { + Map->SetOverlayAt(dwPos, AD.data2); + Map->SetOverlayDataAt(dwPos, 0); + int i; + for (i = 0;i < overlay_count;i++) + { + if (overlay_number[i] == AD.data2) + { + if (overlay_trail[i]) + { + // handle trail stuff! + HandleTrail(x, y); + } + } + } + } + else if (AD.data == 33) + { + int i, e; + for (i = 0;i < m_BrushSize_x;i++) + { + for (e = 0;e < m_BrushSize_y;e++) + { + Map->SetOverlayAt(dwPos + i + e * Map->GetIsoSize(), AD.data2); + Map->SetOverlayDataAt(dwPos + i + e * Map->GetIsoSize(), AD.data3); + } + } + } + + else if (AD.data == 31) + { + Map->SetOverlayAt(dwPos, AD.data2); + } + else if (AD.data == 32) + { + Map->SetOverlayDataAt(dwPos, AD.data2); + } + + // RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (AD.type == 7) + { + // set owner! + BOOL bchanged = FALSE; + + int t = Map->GetStructureAt(x + y * Map->GetIsoSize()); + if (t >= 0) + { + STRUCTURE structure; + Map->GetStructureData(t, &structure); + Map->DeleteStructure(t); + structure.house = AD.data_s; + Map->AddStructure(&structure); + bchanged = TRUE; + } + t = Map->GetUnitAt(x + y * Map->GetIsoSize()); + if (t >= 0) + { + UNIT unit; + Map->GetUnitData(t, &unit); + Map->DeleteUnit(t); + unit.house = AD.data_s; + Map->AddUnit(&unit); + bchanged = TRUE; + } + t = Map->GetAirAt(x + y * Map->GetIsoSize()); + if (t >= 0) + { + AIRCRAFT aircraft; + Map->GetAircraftData(t, &aircraft); + Map->DeleteAircraft(t); + aircraft.house = AD.data_s; + Map->AddAircraft(&aircraft); + bchanged = TRUE; + } + int z; + for (z = 0;z < SUBPOS_COUNT;z++) + { + t = Map->GetInfantryAt(x + y * Map->GetIsoSize(), z); + if (t >= 0) + { + INFANTRY infantry; + Map->GetInfantryData(t, &infantry); + Map->DeleteInfantry(t); + infantry.house = AD.data_s; + Map->AddInfantry(&infantry); + bchanged = TRUE; + } + } + + if (bchanged) + { + //RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW); + } + + + } +#ifdef SMUDGE_SUPP + else if (AD.type == 8) // add smudge + { + + if (Map->GetFielddataAt(x + y * Map->GetIsoSize())->smudge >= 0) + { + return; + } + + SMUDGE s; + s.type = AD.data_s; + s.x = x; + s.y = y; + s.deleted = 0; + Map->AddSmudge(&s); + + //RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } +#endif + +} + +void CIsoView::OnTimer(UINT nIDEvent) +{ + // theApp.m_loading->FreeAll(); + // theApp.m_loading->InitPics(); + + last_succeeded_operation = 1000000; + + + if (nIDEvent == 11) + { + // BUGSEARCH + //if(b_IsLoading) return; + // + m_viewOffset += ProjectedVec((cur_x_mouse - rclick_x) / 2, (cur_y_mouse - rclick_y) / 2); + + SetScroll(m_viewOffset.x, m_viewOffset.y); + + InvalidateRect(NULL, FALSE); + } + else + { + errstream << "Timer calls InitTMPs()" << endl; + errstream.flush(); + + theApp.m_loading->InitTMPs(); + + CView::OnTimer(nIDEvent); + + KillTimer(nIDEvent); + + b_IsLoading = FALSE; + RedrawWindow(); + } +} + +void CIsoView::FillArea(DWORD dwX, DWORD dwY, DWORD dwID, BYTE bSubTile) +{ + if ((*tiledata)[dwID].cx != 1 || (*tiledata)[dwID].cy != 1) + { + MessageBox("You can only use 1x1 tiles to fill areas."); + return; + } + + FIELDDATA* f = Map->GetFielddataAt(dwX + dwY * Map->GetIsoSize()); + f->bReserved = TRUE; + + int mapwidth, mapheight; + mapwidth = Map->GetWidth(); + mapheight = Map->GetHeight(); + + int i, e; + for (i = -1;i < 2;i++) + { + for (e = -1;e < 2;e++) + { + if (abs(i) == abs(e)) continue; + int cur_x, cur_y; + cur_x = dwX + i; + cur_y = dwY + e; + if (cur_x < 1 || cur_y < 1 || cur_x + cur_ymapwidth + mapheight * 2 || (cur_y + 1 > mapwidth && cur_x - 1 < cur_y - mapwidth) || (cur_x + 1 > mapwidth && cur_y + mapwidth - 1 < cur_x)) continue; + + FIELDDATA* f2 = Map->GetFielddataAt(cur_x + cur_y * Map->GetIsoSize()); + + if (f2->bReserved) continue; + + + + if (f2->wGround != dwID && f2->wGround == f->wGround && f2->bSubTile == f->bSubTile) + { + FillArea(cur_x, cur_y, dwID, bSubTile); + } + + } + } + f->wGround = dwID; + f->bSubTile = bSubTile; +} + +void CIsoView::AutoLevel() +{ + Map->TakeSnapshot(); + + + + int mapsize = Map->GetIsoSize() * Map->GetIsoSize(); + int mapedge = Map->GetIsoSize(); + + if (mapsize == 0) return; + + BOOL* bChanged; + bChanged = new(BOOL[mapsize]); + memset(bChanged, 0, mapsize); + + int iCliffStart = -1; //, iSlopeSetStart = -1; + + int i; + + for (i = 0;i < *tiledata_count;i++) + { + if ((*tiledata)[i].wTileSet == cliffset) + { + iCliffStart = i; + break; + + } + } + + if (iCliffStart < 0) + return; + + /*for (i = 0;i<*tiledata_count;i++) + { + if((*tiledata)[i].wTileSet==slopesetpiecesset) + { + iSlopeSetStart=i; + break; + } + }*/ + + /*int count=atoi(g_data.sections["SlopeSetPiecesDirections"].values["Count"]); + BYTE* bXLeftSearch=new(BYTE[count]); + BYTE* bXRightSearch=new(BYTE[count]); + BYTE* bYTopSearch=new(BYTE[count]); + BYTE* bYBottomSearch=new(BYTE[count]); + + for(i=0;iGetFielddataAt(i); + int o_ground = f1->wGround; + if (o_ground == 0xFFFF) o_ground = 0; + int o_width = (*tiledata)[o_ground].cx; + int o_height = (*tiledata)[o_ground].cy; + + int ox, oy; + ox = i % mapedge; + oy = i / mapedge; + + + int x, y; + for (x = -1;x < 2;x++) + { + for (y = -1;y < 2;y++) + { + if (x == -1 && y == -1) continue; + if (x == 1 && y == 1) continue; + if (x == 1 && y == -1) continue; + if (x == -1 && y == 1) continue; + + int count = 0; + int p, k; + int heights[32][32]; + memset(heights, 0, 32 * 32 * sizeof(int)); + + for (p = 0;p < o_width;p++) + { + for (k = 0;k < o_height;k++) + { + count++; + heights[p][k] = (*tiledata)[o_ground].tiles[p + k * o_width].bZHeight; + } + } + + + + if (o_ground < 8 + iCliffStart || o_ground>13 + iCliffStart) + { + if (count < 4 || count>4) + { + if (x < 0 || y < 0) continue; + } + + + + + if (heights[0][0] && !heights[1][1]) + { + if (heights[1][0] && heights[0][1]) + { + + if (x < 0 || y < 0) continue; + + } + } + + if (heights[0][0] && heights[1][1]) + { + if (x < 0 || y>0) continue; + } + + if (!heights[0][0] && heights[1][0] && heights[0][1] && heights[1][1]) + { + if (x < 0 || y < 0) continue; + } + } + else + { + if (x > 0 || y > 0) continue; + } + + if (x + ox > mapedge || x + ox<0 || y + oy>mapedge || y + oy < 0) + continue; + + FIELDDATA* cur_f = Map->GetFielddataAt(i + x + y * mapedge); + + int cur_ground = cur_f->wGround; + if (cur_ground == 0xFFFF) cur_ground = 0; + int cur_set; + if ((*tiledata)[cur_ground].wTileSet != (*tiledata)[o_ground].wTileSet) + { + + if (((*tiledata)[o_ground].wTileSet == cliffset || (*tiledata)[o_ground].wTileSet == slopesetpiecesset) && (*tiledata)[cur_ground].bMorphable) + { + int height_diff = f1->bHeight - cur_f->bHeight; + if (o_ground >= 8 + iCliffStart && o_ground <= 13 + iCliffStart && (*tiledata)[o_ground].tiles[cur_f->bSubTile].bZHeight == 0) height_diff += 4; + int need_diff = height_diff;//(*tiledata)[o_ground].tiles[f1->bSubTile].bZHeight-(*tiledata)[cur_ground].tiles[cur_f->bSubTile].bZHeight; + //if((*tiledata)[o_ground].tiles[f1->bSubTile].bZ + if (abs(height_diff) > 1) + { + //ChangeTileHeight(i+x+y*mapedge,f1->bHeight,FALSE, FALSE); + int height = f1->bHeight; + if (o_ground >= 8 + iCliffStart && o_ground <= 13 + iCliffStart && (*tiledata)[o_ground].tiles[cur_f->bSubTile].bZHeight == 0) height = f1->bHeight + 4; + Map->SetHeightAt(i + x + y * mapedge, height); + bChanged[i + x + y * mapedge] = TRUE; + } + else if (height_diff) + Map->CreateSlopesAt(i + x + y * mapedge); + //bChanged[i+x+y*mapedge]=TRUE; + } + } + } + } + } + + for (i = 0;i < mapsize;i++) + { + + if (bChanged[i]) + { + int e; + for (e = 0;e < Map->GetIsoSize() * Map->GetIsoSize();e++) + Map->SetReserved(e, 0); + ChangeTileHeight(i, Map->GetHeightAt(i), FALSE, FALSE); + } + + } + + /* delete[] bXSearch; + delete[] bYSearch;*/ + + if (bChanged) delete[] bChanged; + + RedrawWindow(); + + Map->TakeSnapshot(); + Map->Undo(); +} + +inline void ToIso3d_NoAccessCheck(int* x, int* y) +{ + int cx = *x, cy = *y; + + ToIso(&cx, &cy); + + int i, e = 0; + + + for (i = 15;i >= 0;i--) + { + for (e = 0;e < 3;e++) + { + int a; + + + int m, n; + int px, py; + m = cx + i; + n = cy + i; + + if (e == 1) m -= 1; + if (e == 2) n -= 1; + + px = m; + py = n; + + if (m >= 0 && n >= 0 && m < Map->GetIsoSize() && n < Map->GetIsoSize()) + { + FIELDDATA mfd = *Map->GetFielddataAt(px + py * Map->GetIsoSize()); + int ground = mfd.wGround; + if (ground == 0xFFFF) ground = 0; + //if(mfd.bHide==FALSE && !(*tiledata)[ground].bHide) + { + + ToPhys3d(&m, &n); + + // now m and n hold the pixel coordinates for the current field... + // we now need to check if cx and cy are in this field + //if(*x >= m && *x<= m+f_x && *y>=n && *y<=n+f_y) + { + int dx = *x - m; + int dy = *y - n - f_y / 2;//-f_y/2; + int dx1 = dx; + int dy1 = dy; + + dx = ((float)dy1) / ((float)f_y) - ((float)dx1) / ((float)f_x) + 1.0f;//+ 1 + (float)0.5 +1; + dy = ((float)dx1) / ((float)f_x) + ((float)dy1) / ((float)f_y) + 0.0f;//- 1-(float)0.5 +1; + + if (((dx == 0 && dy == 0) || (!bAllowAccessBehindCliffs && *y - n > f_y))) + { + *x = px - 0; + *y = py + 0; + return; + } + } + } + } + } + } + + /* +for(i=15;i>=0;i--) + { + for(e=0;e<3;e++) + { + int a; + + + int m,n; + int px,py; + m=cx+i; + n=cy+i; + + if(e==1) m-=1; + if(e==2) n-=1; + + px=m; + py=n; + + if(m>=0 && n>=0 && m< Map->GetIsoSize() && nGetIsoSize()) + { + + ToPhys3d(&m, &n); + + // just find at least one tile if possible... + + if(*x>m && *y>n) + { + *x=px; + *y=py; + return; + } + } + } + }*/ + + + *x = cx;//-1; + *y = cy;//-1; +} + + + +void CIsoView::DrawMap() +{ + const CMapData* const Map = ::Map; + + if (bNoDraw) return; + + if (bCancelDraw) + { + bCancelDraw = FALSE; + return; + } + + last_succeeded_operation = 100; + + if (lpds == NULL || b_IsLoading || tiledata == NULL || (*tiledata) == NULL || (*tiledata_count == 0)) return; // just to make sure... + + if (lpds->IsLost() != DD_OK) + { + // we lost our surfaces, we need to reinitialize directdraw and all associated objects + ReInitializeDDraw(); + return; + } + + + + if (Map->GetIsoSize() == 0) return; + + auto startTime = std::chrono::steady_clock::now(); + + // draw a white background + DDBLTFX fx; + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize = sizeof(DDBLTFX); + fx.dwFillColor = RGB(255, 255, 255); + lpdsBack->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &fx); + + + // get the window rect + + RECT r = GetScaledDisplayRect(); + + // the code here draws the coordinate system + int i; + + + // now, we draw all the objects + + + int left, right, top, bottom; + + { + RECT cr; + GetClientRect(&cr); + auto topLeft = GetMapCoordinatesFromClientCoordinates(CPoint(0, 0), false, true); + auto topRight = GetMapCoordinatesFromClientCoordinates(CPoint(cr.right, 0), false, true); + auto bottomLeft = GetMapCoordinatesFromClientCoordinates(CPoint(0, cr.bottom), false, true); + auto bottomRight = GetMapCoordinatesFromClientCoordinates(CPoint(cr.right, cr.bottom), false, true); + left = min(topLeft.x, topRight.x); + top = min(topLeft.y, topRight.y); + right = max(bottomLeft.x, bottomRight.x); + bottom = max(bottomLeft.y, bottomRight.y); + } + + // some large buildings may be out of reach: + left -= 2; + top -= 2; + right += 7; + bottom += 7; + + + + // validate the coordinates + if (left < 0) left = 0; + if (bottom >= Map->GetIsoSize() || bottom < top) bottom = Map->GetIsoSize(); + if (right >= Map->GetIsoSize() || right < left) right = Map->GetIsoSize(); + if (top < 0) top = 0; + + + BOOL bMarbleHeight = TRUE; + //if(Map->GetTheater()==THEATER4 || Map->GetTheater()==THEATER3) bMarbleHeight=FALSE; + + // Now left, right, top & bottom contain the needed values + + DWORD MM_heightstart = tilesets_start[atoi((*tiles).sections["General"].values["HeightBase"])]; + + // now draw everything + int u, v, z; + int mapwidth, mapheight; + mapwidth = Map->GetWidth(); + mapheight = Map->GetHeight(); + + DDSURFACEDESC2 ddsd; + ZeroMemory(&ddsd, sizeof(ddsd)); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; + + lpdsBack->GetSurfaceDesc(&ddsd); + + +#ifdef NOSURFACES + lpdsBack->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL); +#endif + + // we render texts and waypoints last as they should be always visible anyway and because text rendering is currently done using GDI -> getting a DC for every text is too slow nowadays + m_texts_to_render.clear(); + m_waypoints_to_render.clear(); + + for (u = left;u < right;u++) + { + for (v = top;v < bottom;v++) + { + const MapCoords mapCoords(u, v); + if (bCancelDraw) + { + bCancelDraw = FALSE; + } + + if (u < 1 || v < 1 || u + vmapwidth + mapheight * 2 || (v + 1 > mapwidth && u - 1 < v - mapwidth) || (u + 1 > mapwidth && v + mapwidth - 1 < u)) + continue; + + + FIELDDATA m = *Map->GetFielddataAt(mapCoords); + const auto drawCoords = GetRenderTargetCoordinates(mapCoords); + + // draw terrain + if (m.wGround >= (*tiledata_count)) + m.wGround = 0; + + DWORD dwOrigGround = m.wGround; + + if (theApp.m_Options.bMarbleMadness) + { + if ((*tiledata)[m.wGround].wMarbleGround != 0xFFFF) + { + + m.wGround = (*tiledata)[m.wGround].wMarbleGround; + } + else if (bMarbleHeight) + { + //drawy+=f_y*m.bHeight; + + m.wGround = MM_heightstart + m.bHeight; + m.bSubTile = 0; + } + } + + if (!m.bRedrawTerrain) + { + + TILEDATA* td = &(*tiledata)[m.wGround]; + if (td->bReplacementCount) + { + if (m.bRNDImage > 0) + { + m.bRNDImage <= td->bReplacementCount ? td = &td->lpReplacements[m.bRNDImage - 1] : td = &td->lpReplacements[td->bReplacementCount - 1]; + } + } + + if (m.bSubTile < td->wTileCount && td->tiles[m.bSubTile].pic != NULL) + { + const SUBTILE& st = td->tiles[m.bSubTile]; + const auto stDrawCoords = drawCoords + st.drawOffset(); + + + if (!m.bHide && (*tiledata)[dwOrigGround].bHide == FALSE) + { +#ifndef NOSURFACES + Blit(st.pic, stDrawCoords.x, stDrawCoords.y, st.wWidth, st.wHeight); +#else + BlitTerrain(ddsd.lpSurface, stDrawCoords.x, stDrawCoords.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, st); +#endif + } + else // draw soemthing representing the tile + { +#ifndef NOSURFACES + DrawCell(stDrawCoords.x, stDrawCoords.y, 1, 1, RGB(0, 140, 0), FALSE, FALSE); +#else + BlitTerrainHalfTransp(ddsd.lpSurface, stDrawCoords.x, stDrawCoords.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, st); +#endif + + } + } + + } + + } + } + + + for (u = left;u < right;u++) + { + for (v = top;v < bottom;v++) + { + const MapCoords mapCoords(u, v); + if (bCancelDraw) + { + bCancelDraw = FALSE; + } + + if (u < 1 || v < 1 || u + vmapwidth + mapheight * 2 || (v + 1 > mapwidth && u - 1 < v - mapwidth) || (u + 1 > mapwidth && v + mapwidth - 1 < u)) + continue; + + FIELDDATA m = *Map->GetFielddataAt(mapCoords); // copy + const auto drawCoords = GetRenderTargetCoordinates(mapCoords); + + if (m.wGround == 0xFFFF) + m.wGround = 0; + + DWORD dwOrigGround = m.wGround; + + if (theApp.m_Options.bMarbleMadness) + { + if ((*tiledata)[m.wGround].wMarbleGround != 0xFFFF) + { + m.wGround = (*tiledata)[m.wGround].wMarbleGround; + } + else if (bMarbleHeight) + { + //y+=f_y*m.bHeight; + m.wGround = MM_heightstart + m.bHeight; + m.bSubTile = 0; + } + } + + if (m.bRedrawTerrain) + { + // draw cliff again to hide buildings behind + + if (m.wGround < *tiledata_count) + { + TILEDATA* td = &(*tiledata)[m.wGround]; + if (td->bReplacementCount) + { + if (m.bRNDImage > 0) + { + m.bRNDImage <= td->bReplacementCount ? td = &td->lpReplacements[m.bRNDImage - 1] : td = &td->lpReplacements[td->bReplacementCount - 1]; + } + } + + if (m.bSubTile < td->wTileCount && td->tiles[m.bSubTile].pic != NULL) + { + const SUBTILE& st = td->tiles[m.bSubTile]; + const auto stDrawCoords = drawCoords + st.drawOffset(); + + + if (!m.bHide && (*tiledata)[dwOrigGround].bHide == FALSE) + { +#ifndef NOSURFACES + Blit(st.pic, stDrawCoords.x, stDrawCoords.y, st.wWidth, st.wHeight); +#else + BlitTerrain(ddsd.lpSurface, stDrawCoords.x, stDrawCoords.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, st); + if (st.anim) + { + const auto animDrawCoords = drawCoords + ProjectedVec(f_x / 2 - st.anim->wMaxWidth / 2, f_y / 2 - st.anim->wMaxHeight / 2) + st.anim->drawOffset(); + BlitPic(ddsd.lpSurface, animDrawCoords.x, animDrawCoords.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, *st.anim); + } +#endif + + } + else // draw soemthing representing the tile + { +#ifndef NOSURFACES + DrawCell(stDrawCoords.x, stDrawCoords.y, 1, 1, RGB(0, 140, 0), FALSE, FALSE); +#else + BlitTerrainHalfTransp(ddsd.lpSurface, stDrawCoords.x, stDrawCoords.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, st); +#endif + + } + } + + } + } + + // draw terrain animation (tunnel tops, waterfalls) + // tunnel tops might be repainted later so that units do not appear on top - this probably could be done in CLoading so that instead of a back tile a front tile is responsible for drawing the animation + { + if (m.wGround < *tiledata_count) + { + TILEDATA* td = &(*tiledata)[m.wGround]; + + if (m.bSubTile < td->wTileCount) + { + const SUBTILE& st = td->tiles[m.bSubTile]; + + if (!m.bHide && (*tiledata)[dwOrigGround].bHide == FALSE && st.anim) + { +#ifndef NOSURFACES +#else + const auto animDrawCoords = drawCoords + ProjectedVec(f_x / 2 - st.anim->wMaxWidth / 2, f_y / 2 - st.anim->wMaxHeight / 2) + st.anim->drawOffset(); + BlitPic(ddsd.lpSurface, animDrawCoords.x, animDrawCoords.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, *st.anim); +#endif + } + + } + } + } + + // draw overlay + if (m.overlay != 0xFF) + { + PICDATA pic; + pic.pic = NULL; + + if (ovrlpics[m.overlay][m.overlaydata] != NULL) + { + pic = *ovrlpics[m.overlay][m.overlaydata]; + } + + + if (pic.pic == NULL) + { + if (!pic.bTried) + { + SetError("Loading graphics"); + theApp.m_loading->LoadOverlayGraphic(*rules.sections["OverlayTypes"].GetValue(m.overlay), m.overlay); + UpdateOverlayPictures(m.overlay); + if (ovrlpics[m.overlay][m.overlaydata] != NULL) + pic = *ovrlpics[m.overlay][m.overlaydata]; + } + + if (pic.pic == NULL) + { + if (!(m.overlay >= 0x4a && m.overlay <= 0x65) && !(m.overlay >= 0xcd && m.overlay <= 0xec)) + { + char cd[50]; + cd[0] = '0'; + cd[1] = 'x'; + itoa(m.overlay, cd + 2, 16); + + m_texts_to_render.push_back({ cd, drawCoords.x + f_x / 2, drawCoords.y + f_y / 2, RGB(0,0,0), false, true, true}); + // TextOut(drawx,drawy, cd, RGB(0,0,0)); + } + } + } + + if (pic.pic != NULL) + { + ProjectedVec offset(f_x / 2 - pic.wMaxWidth / 2, -pic.wMaxHeight / 2); + + if (m.overlay == OVRL_VEINHOLE) // veinhole, big, special case + { + offset.y -= f_y * 3 / 2; + } + else if (isBigBridge(m.overlay)) // bridge special case + { + // drawy-=f_y; + if (m.overlaydata >= 0x09 && m.overlaydata <= 0x11) + { + offset.y -= f_y / 2; + } + + offset.x -= 1; // hmm... strange, but this is needed + + } + else if (isTrack(m.overlay)) + offset.y += f_y / 2; + + if (m.overlay >= 0x4a && m.overlay <= 0x65) offset.y += f_y / 2; + if (m.overlay >= 0xcd && m.overlay <= 0xec) offset.y += f_y / 2; + + + const auto drawCoordsOvrl = drawCoords + offset; + +#ifndef NOSURFACES + Blit(pic.pic, drawCoordsOvrl.x, drawCoordsOvrl.y); +#else + +#ifdef RA2_MODE + BlitPic(ddsd.lpSurface, drawCoordsOvrl.x, drawCoordsOvrl.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, pic); +#endif +#ifdef TS_MODE + if (!isGreenTiberium(m.overlay) && !(m.overlay == 0x7f)) // no tib + BlitPic(ddsd.lpSurface, drawCoordsOvrl.x, drawCoordsOvrl.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, pic); + else if (m.overlay == 0x7f) // blue tib + { + int n = RGB(200, 0, 0); + BlitPic(ddsd.lpSurface, drawCoordsOvrl.x, drawCoordsOvrl.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, pic, &n); + } + else + { + int n = RGB(0, 200, 0); + BlitPic(ddsd.lpSurface, drawCoordsOvrl.x, drawCoordsOvrl.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, pic, &n); + } +#endif + +#endif + + } + } + + if (m.structure != -1) + { + last_succeeded_operation = 10101; + + // for structures we need to check if they weren´t drawn earlier + // (every field that this building achieves has this building as .structure) + if (Map->GetStructureAt(mapCoords - MapVec(-1, 0)) != m.structure && Map->GetStructureAt(mapCoords - MapVec(0, -1)) != m.structure) + { + + STRUCTUREPAINT objp; + Map->GetStructurePaint(m.structure, &objp); + + const auto drawCoordsBld = GetRenderTargetCoordinates(MapCoords(objp.x, objp.y)); + int id = m.structuretype; + + + int w = 1, h = 1; + PICDATA pic; + if (id > -1 && id < 0x0F00) + { + w = buildinginfo[id].w; + h = buildinginfo[id].h; + int dir = objp.direction / 32; + + // MW April 13th 2001: fix for building direction + dir = (7 - dir) % 8; + + pic = buildinginfo[id].pic[dir]; + if (pic.pic == NULL) pic = buildinginfo[id].pic[0]; + + } + +#ifndef NOSURFACES + DrawCell(drawCoordsBld.x, drawCoordsBld.y, w, h, colorref_conv[objp.col]); +#else + // MW 07/19/01: Paint cell if user chose so... + if (theApp.m_Options.bShowCells) + { + DrawCell(ddsd.lpSurface, ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch, drawCoordsBld.x, drawCoordsBld.y, w, h, colorref_conv[objp.col]); + } +#endif + + + if (pic.pic == NULL) + { + if (!missingimages[objp.type]) + { + SetError("Loading graphics"); + theApp.m_loading->LoadUnitGraphic(objp.type); + ::Map->UpdateBuildingInfo(objp.type); + int dir = (7 - objp.direction / 32) % 8; + pic = buildinginfo[id].pic[dir]; + if (pic.pic == NULL) pic = buildinginfo[id].pic[0]; + } + if (pic.pic == NULL) + { +#ifndef NOSURFACES + Blit(pics["HOUSE"].pic, drawCoordsBld.x, drawCoordsBld.y - 19); // draw a ugly house +#endif + missingimages[objp.type] = TRUE; + } + } + + if (pic.pic) // picture + { + + // it was that easy! just center on top end!!! + const auto drawCoordsBldShp = drawCoordsBld + ProjectedVec(f_x / 2 - pic.wMaxWidth / 2, -pic.wMaxHeight / 2); + +#ifndef NOSURFACES + Blit(pic.pic, drawCoordsBldShp.x, drawCoordsBldShp.y, pic.wMaxWidth, pic.wMaxHeight); +#else + + BlitPic(ddsd.lpSurface, drawCoordsBldShp.x, drawCoordsBldShp.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, pic, &colorref_conv[objp.col]); +#endif + + for (int upgrade = 0; upgrade < objp.upradecount; ++upgrade) + { + const auto& upg = upgrade == 0 ? objp.upgrade1 : (upgrade == 1 ? objp.upgrade2 : objp.upgrade3); + if (upg.GetLength() == 0) + continue; + + PICDATA pic; + int dir = (7 - objp.direction / 32) % 8; + pic = pics[GetUnitPictureFilename(upg, dir)]; + if (!missingimages[upg] && pic.pic == NULL) + { + SetError("Loading graphics"); + theApp.m_loading->LoadUnitGraphic(upg); + ::Map->UpdateBuildingInfo(upg); + pic = pics[GetUnitPictureFilename(upg, dir)]; + if (pic.pic == NULL) missingimages[upg] = TRUE; + } + + if (pic.pic != NULL) + { + static const CString LocLookup[3][2] = { {"PowerUp1LocXX", "PowerUp1LocYY"}, {"PowerUp2LocXX", "PowerUp2LocYY"}, {"PowerUp3LocXX", "PowerUp3LocYY"} }; + const auto drawCoordsPowerUp = drawCoordsBldShp + ProjectedVec( + atoi(art.sections[objp.type].values[LocLookup[upgrade][0]]), + atoi(art.sections[objp.type].values[LocLookup[upgrade][1]]) + ); + // py-=atoi(art.sections[obj.type].values["PowerUp1LocZZ"]); +#ifndef NOSURFACES + Blit(pic.pic, drawCoordsPowerUp.x, drawCoordsPowerUp.y); +#else + BlitPic(ddsd.lpSurface, drawCoordsPowerUp.x, drawCoordsPowerUp.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, pic, &colorref_conv[objp.col]); +#endif + + } + + } + + } + } + + } + + + if (m.node.type > -1) + { + last_succeeded_operation = 10102; + + CString house = m.node.house; + CString tmp; + + if (Map->GetNodeAt(mapCoords + MapVec(1, 0), tmp) != m.node.index && Map->GetNodeAt(mapCoords + MapVec(0, 1), tmp) != m.node.index) + { + const auto drawCoordsBld = GetRenderTargetCoordinates(mapCoords - MapVec(buildinginfo[m.node.type].h - 1, buildinginfo[m.node.type].w - 1)); + + COLORREF c; + c = GetColor(house); + + + int id = m.node.type; + int w = 1, h = 1; + PICDATA pic; + if (id > -1 && id < 0x0F00) + { + w = buildinginfo[id].w; + h = buildinginfo[id].h; + pic = buildinginfo[id].pic[0]; + } + + + //#ifndef NOSURFACES +#ifdef NOSURFACES + if (m.structure >= 0) // only paint cell if we have a structure preplaced, as we have a half transparent image + { +#endif + // place it 2 pixels lower so that user can see the dotted lines even if the building itself has the cells drawn + DrawCell(ddsd.lpSurface, ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch, drawCoordsBld.x, drawCoordsBld.y + 3, w, h, colorref_conv[c], true); + +#ifdef NOSURFACES + } +#endif + //#endif + + if (pic.pic == NULL) + { + if (!missingimages[*rules.sections["BuildingTypes"].GetValue(m.node.type)]) + { + SetError("Loading graphics"); + theApp.m_loading->LoadUnitGraphic(*rules.sections["BuildingTypes"].GetValue(m.node.type)); + ::Map->UpdateBuildingInfo(*rules.sections["BuildingTypes"].GetValue(m.node.type)); + pic = buildinginfo[id].pic[0]; + } + if (pic.pic == NULL); + { +#ifndef NOSURFACES + Blit(pics["HOUSE"].pic, drawCoordsBld.x, drawCoordsBld.y - 19); +#endif + missingimages[*rules.sections["BuildingTypes"].GetValue(m.node.type)] = TRUE; + } + } + + + if (pic.pic) // picture + { + const auto drawCoordsBldShp = drawCoordsBld + ProjectedVec(f_x / 2 - pic.wMaxWidth / 2, -pic.wMaxHeight / 2); + +#ifndef NOSURFACES + Blit(pic.pic, drawCoordsBldShp.x, drawCoordsBldShp.y); +#else + BlitPicHalfTransp(ddsd.lpSurface, drawCoordsBldShp.x, drawCoordsBldShp.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, pic, &colorref_conv[c]); +#endif + } + } + + } + if (m.unit != -1) + { + + UNIT obj; + Map->GetUnitData(m.unit, &obj); + + COLORREF c = GetColor(obj.house); + + + CString lpPicFile = GetUnitPictureFilename(obj.type, atoi(obj.direction) / 32); + +#ifndef NOSURFACES + DrawCell(drawCoords.x, drawCoords.y, 1, 1, c); +#endif + + PICDATA p = pics[lpPicFile]; + + if (p.pic == NULL || lpPicFile.GetLength() == 0) + { + if (!missingimages[obj.type]) + { + SetError("Loading graphics"); + theApp.m_loading->LoadUnitGraphic(obj.type); + lpPicFile = GetUnitPictureFilename(obj.type, atoi(obj.direction) / 32); + p = pics[lpPicFile]; + } + + if (p.pic == NULL) + { +#ifndef NOSURFACES + Blit(pics["TANK"].pic, drawCoords.x, drawCoords.y); + // TextOut(drawx+f_x/4,drawy+f_y/4, obj.type,c); + m_texts_to_render.push_back({ obj.type, drawCoords.x + f_x / 4, drawCoords.y + f_y / 4, m_color_converter->GetColor(c)}); +#endif + missingimages[obj.type] = TRUE; + } + } + + if (p.pic)// we have a picture! + { + const auto drawCoordsOffset = (p.bType == PICDATA_TYPE_BMP) ? ProjectedVec((f_y / 4) + p.x, (f_y - p.wHeight) + p.y) - p.drawOffset() : + (p.bType == PICDATA_TYPE_SHP) ? ProjectedVec(f_x / 2 - (p.wMaxWidth / 2), f_y / 2 - (p.wMaxHeight / 2)) : ProjectedVec(f_x / 2, f_y / 2) + p.drawOffset(); + auto drawCoordsUnit = drawCoords + drawCoordsOffset; + +#ifndef NOSURFACES + Blit(p.pic, drawCoordsUnit.x, drawCoordsUnit.y); +#else + BlitPic(ddsd.lpSurface, drawCoordsUnit.x, drawCoordsUnit.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, p, &colorref_conv[c]); +#endif + } + } + if (m.aircraft != -1) + { + last_succeeded_operation = 10102; + + AIRCRAFT obj; + Map->GetAircraftData(m.aircraft, &obj); + + COLORREF c = GetColor(obj.house); + + + CString lpPicFile = GetUnitPictureFilename(obj.type, atoi(obj.direction) / 32); + +#ifndef NOSURFACES + DrawCell(drawCoords.x, drawCoords.y, 1, 1, c); +#endif + + PICDATA p = pics[lpPicFile]; + + if (p.pic == NULL) + { + if (!missingimages[obj.type]) + { + SetError("Loading graphics"); + theApp.m_loading->LoadUnitGraphic(obj.type); + p = pics[lpPicFile]; + } + + if (p.pic == NULL) + { +#ifndef NOSURFACES + Blit(pics["TANK"].pic, drawCoords.x, drawCoords.y); + //TextOut(drawx+f_x/4,drawy+f_y/4, obj.type,c); + m_texts_to_render.push_back({ obj.type, drawCoords.x + f_x / 4, drawCoords.y + f_y / 4, m_color_converter->GetColor(c) }); +#endif + missingimages[obj.type] = TRUE; + } + } + + if (p.pic)// we have a picture! + { + const auto drawCoordsOffset = (p.bType == PICDATA_TYPE_BMP) ? ProjectedVec(f_x / 2 - p.wWidth / 2, f_y - p.wHeight) - p.drawOffset() : + (p.bType == PICDATA_TYPE_SHP) ? ProjectedVec(f_x / 2 - (p.wMaxWidth / 2), f_y / 2 - (p.wMaxHeight / 2)) : ProjectedVec(f_x / 2, f_y / 2) + p.drawOffset(); + auto drawCoordsAir = drawCoords + drawCoordsOffset; + +#ifndef NOSURFACES + Blit(p.pic, drawCoordsAir.x, drawCoordsAir.y); +#else + BlitPic(ddsd.lpSurface, drawCoordsAir.x, drawCoordsAir.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, p, &colorref_conv[c]); +#endif + } + } + int ic; + for (ic = 0;ic < SUBPOS_COUNT;ic++) + if (m.infantry[ic] != -1) + { + last_succeeded_operation = 10103; + + //errstream << "GetInfantryData()" << endl; + //errstream.flush(); + + INFANTRY obj; + Map->GetInfantryData(m.infantry[ic], &obj); + + //errstream << "Done " << (LPCSTR)obj.type << endl; + //errstream.flush(); + + + COLORREF c = GetColor(obj.house); + + + int dir = (7 - atoi(obj.direction) / 32) % 8; + CString lpPicFile = GetUnitPictureFilename(obj.type, dir); + +#ifndef NOSURFACES + DrawCell(drawCoords.x, drawCoords.y, 1, 1, c); +#endif + + static const ProjectedVec subPosLookup[5] = { ProjectedVec(0, -f_y / 4), ProjectedVec(f_x / 4 , 0), ProjectedVec(-f_x / 4, 0), ProjectedVec(0, f_y / 4), ProjectedVec()}; + auto drawCoordsInf = drawCoords + subPosLookup[ic > 4 ? 4 : ic]; + + PICDATA p = pics[lpPicFile]; + + if (p.pic == NULL) + { + if (!missingimages[obj.type]) + { + SetError("Loading graphics"); + theApp.m_loading->LoadUnitGraphic(obj.type); + p = pics[lpPicFile]; + } + + if (p.pic == NULL) + { +#ifndef NOSURFACES + Blit(pics["MAN"].pic, drawCoordsInf.x, drawCoordsInf.y); + // TextOut(drawx+f_x/4,drawy+f_y/4, obj.type,c); + m_texts_to_render.push_back({ obj.type, drawCoordsInf.x + f_x / 4, drawCoordsInf.y + f_y / 4, RGB(0,0,0) }); +#endif + missingimages[obj.type] = TRUE; + } + } + + + + if (p.pic)// we have a picture! + { + auto drawCoordsInfShp = drawCoordsInf + ProjectedVec(f_x / 2 - (p.wMaxWidth / 2), f_y / 2 - (p.wMaxHeight / 2)); + +#ifndef NOSURFACES + Blit(p.pic, drawCoordsInfShp.x, drawCoordsInfShp.y, p.wWidth, p.wHeight); +#else + BlitPic(ddsd.lpSurface, drawCoordsInfShp.x, drawCoordsInfShp.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, p, &colorref_conv[c]); +#endif + + } + + } + if (m.terrain != -1) + { + last_succeeded_operation = 10104; + + + int id = m.terraintype; + int w = 1, h = 1; + PICDATA pic; + if (id > -1 && id < 0x0F00) + { + w = treeinfo[id].w; + h = treeinfo[id].h; + pic = treeinfo[id].pic; + } + + //CString lpPicFile=GetUnitPictureFilename(type, 0); + + if (pic.pic == NULL) + { + CString type; + Map->GetTerrainData(m.terrain, &type); + + if (missingimages.find(type) == missingimages.end()) + { + SetError("Loading graphics"); + theApp.m_loading->LoadUnitGraphic(type); + ::Map->UpdateTreeInfo(type); + pic = treeinfo[id].pic; + } + if (pic.pic == NULL) + { +#ifndef NOSURFACES + Blit(pics["TREE"].pic, drawCoords.x, drawCoords.y - 19); +#endif + missingimages[type] = TRUE; + } + } + + if (pic.pic); + { + + auto drawCoordsTerrain = drawCoords + ProjectedVec(f_x / 2 - (pic.wMaxWidth / 2), f_y / 2 - 3 - (pic.wMaxHeight / 2)); + +#ifndef NOSURFACES + Blit(pic.pic, drawCoordsTerrain.x, drawCoordsTerrain.y); +#else + BlitPic(ddsd.lpSurface, drawCoordsTerrain.x, drawCoordsTerrain.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, pic); + +#endif + + + } + + } + + +#ifdef SMUDGE_SUPP + if (m.smudge != -1) + { + last_succeeded_operation = 10104; + + + int id = m.smudgetype; + + PICDATA pic; + if (id > -1 && id < 0x0F00) + { + pic = smudgeinfo[id].pic; + } + + if (pic.pic == NULL) + { + SMUDGE data; + CString& type = data.type; + Map->GetSmudgeData(m.smudge, &data); + + if (missingimages.find(type) == missingimages.end()) + { + SetError("Loading graphics"); + theApp.m_loading->LoadUnitGraphic(type); + ::Map->UpdateSmudgeInfo(type); + pic = smudgeinfo[id].pic; + } + if (pic.pic == NULL) + { +#ifndef NOSURFACES + // Blit(pics["TREE"].pic,drawCoords.x,drawCoords.y-19); +#endif + missingimages[type] = TRUE; + } + } + + if (pic.pic) + { + auto drawCoordsSmudge = drawCoords + ProjectedVec(f_x / 2 - (pic.wMaxWidth / 2), /*f_y / 2 - 3*/ - (pic.wMaxHeight / 2)); + +#ifndef NOSURFACES + Blit(pic.pic, drawCoordsSmudge.x, drawCoordsSmudge.y); +#else + BlitPic(ddsd.lpSurface, drawCoordsSmudge.x, drawCoordsSmudge.y, r.left, r.top, ddsd.lPitch, r.right, r.bottom, pic); + +#endif + + + } + + } +#endif + + + if (m.celltag != -1) + { + +#ifdef NOSURFACES + lpdsBack->Unlock(NULL); +#endif + Blit((LPDIRECTDRAWSURFACE4)pics["CELLTAG"].pic, drawCoords.x - 1, drawCoords.y - 1); + +#ifdef NOSURFACES + lpdsBack->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL); +#endif + } + + if (m.waypoint != -1) + { + + DWORD dwPos; + CString ID; + Map->GetWaypointData(m.waypoint, &ID, &dwPos); + + +#ifdef NOSURFACES + lpdsBack->Unlock(NULL); +#endif + + // move the graphic and text into place +#ifdef RA2_MODE + int image_fudge_x = 4; + int image_fudge_y = -20; + int text_fudge_x = 12; + int text_fudge_y = -24; +#else + int image_fudge_x = 4; + int image_fudge_y = -15; + int text_fudge_x = 9; + int text_fudge_y = -17; +#endif + + const ProjectedVec waypointImageOffset(image_fudge_x, image_fudge_y); + const ProjectedVec waypointTextOffset((f_x / 2) + text_fudge_x, (f_y / 2) + text_fudge_y); +#ifdef RA2_MODE + bool useFont9 = false; +#else + bool useFont9 = true; +#endif + const auto waypointImageCoords = ProjectedCoords({ drawCoords.x, drawCoords.y }) + waypointImageOffset; + const auto waypointTextCoords = ProjectedCoords({ drawCoords.x, drawCoords.y }) + waypointTextOffset; + m_waypoints_to_render.push_back({ waypointImageCoords.x, waypointImageCoords.y }); + m_texts_to_render.push_back({ ID.GetString(), waypointTextCoords.x, waypointTextCoords.y, RGB(0,0,255), false, useFont9, true}); +#ifdef NOSURFACES + lpdsBack->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL); +#endif + } + + } + + } + + for (const auto& tube : Map->GetTubes()) + { + DrawTube(*tube, &ddsd); + } + +#ifdef NOSURFACES + lpdsBack->Unlock(NULL); +#endif + + // delayed waypoint rendering + for (const auto& wp : m_waypoints_to_render) + { + Blit((LPDIRECTDRAWSURFACE4)pics["FLAG"].pic, wp.drawx, wp.drawy); + } + + // map tool rendering + if (AD.mode == ACTIONMODE_MAPTOOL) + { + if (AD.tool) + AD.tool->render(); + } + + lpdsTemp->Blt(NULL, lpdsBack, NULL, 0, 0); // lpdsTemp always holds the scene drawn above, unscaled to the window + + if (m_cellCursor != MapCoords(-1, -1)) + { + SurfaceLocker locker(lpdsBack); + auto desc = locker.ensure_locked(); + if (desc) + DrawCellCursor(m_cellCursor, *desc); + } + + auto renderDuration = std::chrono::duration_cast>(std::chrono::steady_clock::now() - startTime); // not including text output, ReleaseDC, waitForVerticalBlank etc below + + if (bDrawStats) + { + if (theApp.m_Options.bShowStats) + { + auto systemStats = std::format("ms: {0} Left: {1} Top: {2} Right: {3} Bottom: {4}", renderDuration.count(), left, top, right, bottom); + m_texts_to_render.push_back({ systemStats.c_str(), r.left + 10, r.top + 10 + (-m_fontDefaultHeight) * 3 / 2, RGB(0,0,0), true }); + } + + auto moneyStr = std::format("Credits on map: {0}", Map->GetMoneyOnMap()); + m_texts_to_render.push_back({ moneyStr.c_str(), r.left + 10, r.top + 10, RGB(0,0,0), true }); + } + + if (rscroll) + { + const auto& sc = pics["SCROLLCURSOR"]; + Blit((LPDIRECTDRAWSURFACE4)sc.pic, rclick_x * m_viewScale.x + r.left - sc.wWidth / 2, rclick_y * m_viewScale.y + r.top - sc.wHeight / 2); + } + + BlitBackbufferToHighRes(); // lpdsBackHighRes contains the same graphic, but scaled to the whole window + + RenderUIOverlay(); + if (theApp.m_Options.bVSync) + dd->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, NULL); + FlipHighResBuffer(); + last_succeeded_operation = 10100; + +} + +void CIsoView::RenderUIOverlay() +{ + if (!m_textDefault) + updateFontScaled(); + + LPDIRECTDRAWSURFACE4 dds = lpdsBack; + bool useHighRes = false; + if (m_viewScale != Vec2(1.0f, 1.0f) && lpdsBackHighRes) + { + dds = lpdsBackHighRes; + useHighRes = true; + } + + DDSURFACEDESC2 ddsd; + ZeroMemory(&ddsd, sizeof(ddsd)); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; + + dds->GetSurfaceDesc(&ddsd); + + dds->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL); + LineDrawer d(ddsd.lpSurface, bpp, ddsd.dwWidth, ddsd.dwHeight, ddsd.lPitch); + + int lr, lt, ll, lb; + + ll = Map->GetWidth(); + lt = 1; + lr = Map->GetHeight(); + lb = Map->GetIsoSize() - 1; + + int h_lefttop = 0;//Map->GetHeightAt(ll+lt*Map->GetIsoSize()); + int h_leftbottom = 0;//Map->GetHeightAt(lr+lb*Map->GetIsoSize()); + + ToPhys((int*)&ll, (int*)<); + ToPhys((int*)&lr, (int*)&lb); + ll -= m_viewOffset.x - f_x / 2; + lt -= m_viewOffset.y - f_y / 2; + lr -= m_viewOffset.x - f_x / 2; + lb -= m_viewOffset.y - f_y / 2; + + lt -= h_lefttop * f_y / 2; + lb -= h_leftbottom * f_y / 2; + + auto sllt = useHighRes ? ScaleBackToFrontBuffer(ProjectedCoords(ll, lt)) : ProjectedCoords(ll, lt); + auto slbr = useHighRes ? ScaleBackToFrontBuffer(ProjectedCoords(lr, lb)) : ProjectedCoords(lr, lb); + + RECT ls; + Map->GetLocalSize(&ls); + ProjectedCoords l_lt( + ll + ls.left * f_x - f_x / 2, + lt + (ls.top - 4) * f_y + ); + ProjectedCoords l_br( + ll + ls.left * f_x + ls.right * f_x - f_x / 2, + lt + (ls.top - 4 + 4) * f_y + ls.bottom * f_y + ); + auto ls_lt = useHighRes ? ScaleBackToFrontBuffer(l_lt) : l_lt; + auto ls_br = useHighRes ? ScaleBackToFrontBuffer(l_br) : l_br; + + auto red = m_color_converter->GetColor(255, 0, 0); + auto blue = m_color_converter->GetColor(0, 0, 255); + d.Rectangle(sllt.x, sllt.y, slbr.x, slbr.y, red); + d.Rectangle(sllt.x-1, sllt.y-1, slbr.x+1, slbr.y+1, red); + d.Rectangle(ls_lt.x, ls_lt.y, ls_br.x, ls_br.y, blue); + d.Rectangle(ls_lt.x+1, ls_lt.y+1, ls_br.x-1, ls_br.y-1, blue); + + dds->Unlock(NULL); + + RECT r; + GetWindowRect(&r); + + for (const auto& s : m_texts_to_render) + { + const bool blue = s.color == RGB(0, 0, 255); // TODO: TextRenderer should support setting the color at render time + if (s.fixedScreenPos || !useHighRes) + { + auto textRenderer = s.useFont9 ? (blue ? *m_textBlue9 : *m_text9) : (blue ? *m_textBlue : *m_textDefault); + textRenderer.RenderText(dds, s.drawx, s.drawy, s.text, s.centered); + } + else + { + auto textRenderer = s.useFont9 ? (blue ? *m_textBlue9Scaled : *m_text9Scaled) : (blue ? *m_textBlueScaled : *m_textScaled); + textRenderer.RenderText(dds, r.left + (s.drawx - r.left) / m_viewScale.x, r.top + (s.drawy - r.top) / m_viewScale.y, s.text, s.centered); + } + } +} + + +void CIsoView::OnRButtonDown(UINT nFlags, CPoint point) +{ + rclick_x = point.x; + rclick_y = point.y; + rscroll = FALSE; + + CView::OnRButtonDown(nFlags, point); +} + +void CIsoView::SetScroll(int xscroll, int yscroll) +{ + RECT r; + GetWindowRect(&r); + + m_viewOffset = ProjectedVec(xscroll, yscroll); + + + if (m_viewOffset.x < (Map->GetHeight() / 2 - 14 - r.left / f_x) * f_x) + m_viewOffset.x = (Map->GetHeight() / 2 - 14 - r.left / f_x) * f_x; + if (m_viewOffset.x + r.right * m_viewScale.x > (Map->GetHeight() / 2 + Map->GetWidth() + 14) * f_x) + m_viewOffset.x = (Map->GetHeight() / 2 + Map->GetWidth() + 14) * f_x - r.right * m_viewScale.x; + if (m_viewOffset.y < (Map->GetWidth() / 2 - 14 - r.top / f_y) * f_y) + m_viewOffset.y = (Map->GetWidth() / 2 - 14 - r.top / f_y) * f_y; + if (m_viewOffset.y + r.bottom * m_viewScale.y > (Map->GetWidth() / 2 + Map->GetHeight() + 4) * f_y) + m_viewOffset.y = (Map->GetWidth() / 2 + Map->GetHeight() + 4) * f_y - r.bottom * m_viewScale.y; + + SetScrollPos(SB_VERT, (m_viewOffset.y / f_y - Map->GetWidth() / 2 + 4), TRUE); + SetScrollPos(SB_HORZ, (m_viewOffset.x / f_x - Map->GetHeight() / 2 + 1), TRUE); + +} + +RECT CIsoView::GetScaledDisplayRect() const +{ + RECT r; + GetWindowRect(&r); + r.right = r.right - (r.right - r.left) * (1.0f - m_viewScale.x); + r.bottom = r.bottom - (r.bottom - r.top) * (1.0f - m_viewScale.y); + return r; // RVO +} + +void CIsoView::GetScroll(int& xscroll, int& yscroll) const +{ + xscroll = m_viewOffset.x; + yscroll = m_viewOffset.y; +} + +void CIsoView::OnKillFocus(CWnd* pNewWnd) +{ + CView::OnKillFocus(pNewWnd); + + if (rscroll) + { + errstream << "Killing scroll" << endl; + errstream.flush(); + + ReleaseCapture(); + KillTimer(11); + ShowCursor(TRUE); + rscroll = FALSE; + bDoNotAllowScroll = TRUE; + } + +} + +// takes an index, not an waypoint id! +void CIsoView::FocusWaypoint(int index) +{ + int x, y; + + DWORD dwPos; + + Map->GetWaypointData(index, NULL, &dwPos); + + x = dwPos % Map->GetIsoSize(); + y = dwPos / Map->GetIsoSize(); + + ToPhys3d(&x, &y); + + RECT r; + GetWindowRect(&r); + + auto pos = ProjectedVec((x - (r.right - r.left) / 2 * m_viewScale.x) - r.left, (y - (r.bottom - r.top) / 2 * m_viewScale.y) - r.top); + SetScroll(pos.x, pos.y); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); +} + + +BOOL CIsoView::OnMouseWheel(UINT nFlags, short zDelta, CPoint ptScreen) +{ + CPoint pt = ptScreen; + ScreenToClient(&pt); // Attention: MouseWheel event has screen coordinates in contrast to e.g. MouseMove + + float smoothF = float(zDelta) / std::numeric_limits::max(); + float fixedF = zDelta > 0 ? std::numeric_limits::max() : std::numeric_limits::min(); + + Zoom(pt, theApp.m_Options.viewScaleUseSteps ? fixedF : smoothF); + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + CMyViewFrame& dlg = *(CMyViewFrame*)owner; + dlg.m_minimap.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + return CView::OnMouseWheel(nFlags, zDelta, pt); +} + +void CIsoView::Zoom(CPoint& pt, float f) +{ + auto oldScaledMPos = GetProjectedCoordinatesFromClientCoordinates(pt); + + auto oldScale = m_viewScale; + + auto oldViewScaleControl = m_viewScaleControl; + m_viewScaleControl *= (1.0f - f * theApp.m_Options.viewScaleSpeed); + if (m_viewScaleControl > 1.0f) + m_viewScaleControl = 1.0f; + if (m_viewScaleControl < 0.1f) + m_viewScaleControl = 0.1f; + + if (!theApp.m_Options.viewScaleUseSteps) + m_viewScale.set(m_viewScaleControl, m_viewScaleControl); + else + { + // find previous step + auto prevStepIt = std::find_if(theApp.m_Options.viewScaleSteps.rbegin(), theApp.m_Options.viewScaleSteps.rend(), [oldScale](auto f) {return f >= oldScale.x;}); + auto stepIt = std::find_if(theApp.m_Options.viewScaleSteps.rbegin(), theApp.m_Options.viewScaleSteps.rend(), [this](auto f) {return f >= m_viewScaleControl;}); + if (stepIt > prevStepIt) + stepIt = prevStepIt + 1; + if (stepIt < prevStepIt) + stepIt = prevStepIt - 1; + auto nextScale = stepIt == theApp.m_Options.viewScaleSteps.rend() ? 1.0f : *stepIt; + m_viewScale.set(nextScale, nextScale); + } + + auto newScaledMPos = GetProjectedCoordinatesFromClientCoordinates(pt); + + m_viewOffset = m_viewOffset + ((oldScaledMPos - newScaledMPos)).convertT(); // this lets the mouse cursor pixel stay constant + + UpdateScrollRanges(); + SetScroll(m_viewOffset.x, m_viewOffset.y); + updateFontScaled(); +} + + +void CIsoView::OnMButtonDown(UINT nFlags, CPoint point) +{ + // TODO: FĂ¼gen Sie hier Ihren Meldungshandlercode ein, und/oder benutzen Sie den Standard. + m_MButtonDown = point; + m_MButtonMoveZooming = point; + m_zooming = true; + CView::OnMButtonDown(nFlags, point); +} + + +void CIsoView::OnMButtonUp(UINT nFlags, CPoint point) +{ + // TODO: FĂ¼gen Sie hier Ihren Meldungshandlercode ein, und/oder benutzen Sie den Standard. + m_zooming = false; + CView::OnMButtonUp(nFlags, point); +} diff --git a/MissionEditor/IsoView.h b/MissionEditor/IsoView.h new file mode 100644 index 0000000..41b3e8d --- /dev/null +++ b/MissionEditor/IsoView.h @@ -0,0 +1,392 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_ISOVIEW_H__7FB6D6A0_7B52_11D3_99E1_DA6DFD21E706__INCLUDED_) +#define AFX_ISOVIEW_H__7FB6D6A0_7B52_11D3_99E1_DA6DFD21E706__INCLUDED_ + + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// IsoView.h : header file +// + + + +///////////////////////////////////////////////////////////////////////////// +// View CIsoView + +#include +#include +#include "MissionEditorPackLib.h" +#include "Structs.h" + + + +struct TextToRender +{ + std::string text; + int drawx; + int drawy; + int color; + bool fixedScreenPos = false; + bool useFont9 = false; + bool centered = false; +}; + +struct WaypointToRender +{ + int drawx; + int drawy; +}; + +class TextDrawer; +class CTube; + + +class CIsoView : public CView +{ +protected: + DECLARE_DYNCREATE(CIsoView) + +// attributes +public: + INT m_mapx; + INT m_mapy; + int m_FlattenHeight; // for flatten ground + int m_FlattenLastX; + int m_FlattenLastY; + int m_TileChangeCount; + BOOL bThreadPainting; + +private: + ProjectedVec m_viewOffset; + Vec2 m_viewScale; // this is used for display and may e.g. be locked to zoom steps + float m_viewScaleControl; // you control these with your mouse + CPoint m_MButtonDown; + CPoint m_MButtonMoveZooming; + + int rclick_x; // scroll pixel coordinates + int rclick_y; + int cur_x_mouse; + int cur_y_mouse; + BOOL rscroll; + BOOL m_bAltCliff; + bool m_zooming; + + std::vector m_texts_to_render; + std::vector m_waypoints_to_render; + + + +// operations +public: + CIsoView(); + virtual ~CIsoView(); + +// overwriteables + //{{AFX_VIRTUAL(CIsoView) + public: + virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL); + protected: + virtual void OnDraw(CDC* pDC); // Ăœberschrieben zum Zeichnen dieser Ansicht + virtual void OnInitialUpdate(); // Zum ersten Mal nach der Konstruktion + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// implementation +protected: + +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + + // generated message maps + //{{AFX_MSG(CIsoView) + afx_msg void OnSysCommand(UINT nID, LPARAM lParam); + afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); + afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnRButtonUp(UINT nFlags, CPoint point); + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnMove(int x, int y); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnDeadChar(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnTimer(UINT nIDEvent); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnKillFocus(CWnd* pNewWnd); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + void FocusWaypoint(int index); + RECT m_funcRect; + Vec2 GetViewScale() const + { + return m_viewScale; + } + ProjectedVec GetViewOffset() const + { + return m_viewOffset; + } + RECT GetScaledDisplayRect() const; + void GetScroll(int& xscroll, int& yscroll) const; + void SetScroll(int xscroll, int yscroll); + void DrawMap(); + void AutoLevel(); + void FillArea(DWORD dwX, DWORD dwY, DWORD dwID, BYTE bSubTile); + BOOL m_NoMove; + void PlaceCurrentObjectAt(int x, int y); + void PlaceTile(const int x, const int y, const UINT nMouseFlags); + void ShowAllTileSets(); + void HideTileSet(DWORD dwTileSet); + void FlipHighResBuffer(); + void BlitBackbufferToHighRes(); + void RenderUIOverlay(); + int m_BrushSize_x; + int m_BrushSize_y; + BOOL ReachableFrom(DWORD dwStart, DWORD dwEnd); + void __fastcall ChangeTileHeight(DWORD dwPos, DWORD dwNewHeight, BOOL bNonMorphableMove, BOOL bOnlyThisTile=FALSE, BOOL bNoSlopes=FALSE); + void UpdateOverlayPictures(int id=-1); + void UpdateStatusBar(int x, int y); + void DrawCell(int x, int y, int w, int h, COLORREF col, BOOL dotted=FALSE, HDC hDC=nullptr); + void DrawCell(void* dest, int dest_width, int dest_height, int dest_pitch, int x, int y, int w, int h, int col, bool dotted=false, bool touchNeighbours=false, int colNeighbour=CLR_INVALID) const; + void DrawCellCursor(const MapCoords& mapCoords, const DDSURFACEDESC2& desc); + void DrawTube(const CTube& tube, const DDSURFACEDESC2* ddsd=nullptr, const COLORREF* color=nullptr) const; + + /// + /// Converts from (world) pixel coordinates to logical map coordinates + /// + /// World pixel coordinates + /// Logical map coordinates + MapCoords GetMapCoordinates(const ProjectedCoords& projCoords, bool bAllowAccessBehindCliffs=false, bool ignoreHideFlags = false) const; + + /// + /// Converts from view / render target pixel coordinates (0/0 is top left corner of screen) to logical map coordinates + /// If you use mouse-move coordinates you need to + /// + /// Texel coordinates of the backbuffer render target + /// Logical map coordinates + MapCoords GetMapCoordinatesFromRenderTargetCoordinates(const ProjectedCoords& screenViewCoords, bool bAllowAccessBehindCliffs = false, bool ignoreHideFlags = false) const; + + /// + /// Converts from Win32 window client coordinates (0/0 at the top left corner of the view window) to logical map coordinates + /// + /// Client coordinates as given e.g. by window messages + /// Logical map coordinates + MapCoords GetMapCoordinatesFromClientCoordinates(const CPoint& clientPt, bool bAllowAccessBehindCliffs = false, bool ignoreHideFlags = false) const; + + /// + /// Converts from Win32 window client coordinates (0/0 at the top left corner of the view window) to (world) pixel coordinates + /// + /// Client coordinates as given e.g. by window messages + /// World pixel coordinates + ProjectedCoords GetProjectedCoordinatesFromClientCoordinates(const CPoint& clientPt) const; + + /// + /// Converts from logical map coordinates to (world) pixel coordinates + /// + /// Logical map coordinates + /// World pixel coordinates + ProjectedCoords GetProjectedCoordinates(const MapCoords& mapCoords) const; + + /// + /// Converts from logical map coordinates to (world) pixel coordinates + /// + /// Logical map coordinates + /// Fixed logical height + /// World pixel coordinates + ProjectedCoords GetProjectedCoordinates(const MapCoords& mapCoords, int mapZ) const; + + /// + /// Converts from logical map coordinates to view / render target pixel coordinates (screen backbuffer, e.g. currently not yet scaled by view zoom) + /// + /// Logical map coordinates + /// Texel coordinates of the screen backbuffer + ProjectedCoords GetRenderTargetCoordinates(const MapCoords& mapCoords) const; + + /// + /// Converts from logical map coordinates to view / render target pixel coordinates (screen backbuffer, e.g. currently not yet scaled by view zoom) + /// + /// Logical map coordinates + /// Fixed logical height + /// Texel coordinates of the screen backbuffer + ProjectedCoords GetRenderTargetCoordinates(const MapCoords& mapCoords, int mapZ) const; + + /// + /// Converts from logical map coordinates to Win32 window client coordinates (0/0 at the top left corner of the view window) + /// + /// Logical map coordinates + /// Texel coordinates of the backbuffer render target + CPoint GetClientCoordinates(const MapCoords& mapCoords) const; + + /// + /// Converts from (world) pixel coordinates to Win32 window client coordinates (0/0 at the top left corner of the view window) + /// + /// World pixel coordinates + /// Client coordinates as given e.g. by window messages + CPoint GetClientCoordinatesFromWorld(const ProjectedCoords& projectedCoords) const; + + /// + /// Applies the scaling as it is being done when blitting from back to frontbuffer, required e.g. for drawing calls directly to the frontbuffer + /// If you use mouse-move coordinates you need to + /// + /// Texel coordinates of the backbuffer render target + /// Texel coordinates of the frontbuffer render target + ProjectedCoords ScaleBackToFrontBuffer(const ProjectedCoords& backBufferCoords) const; + + void HandleTrail(int x, int y); + int GetOverlayDirection(int x, int y); + void SetError(const char* text); + CWnd* owner; + void ReInitializeDDraw(); + COLORREF GetColor(const char* house, const char* color=NULL); + void Blit(LPDIRECTDRAWSURFACE4 pic, int x, int y, int width=-1, int height=-1) + { + if(pic==NULL) return; + + x+=1; + y+=1; + //y-=f_y; + + RECT r; + GetDesktopWindow()->GetWindowRect(&r); + //GetWindowRect(&r); + + if(width==-1 || height==-1) + { + DDSURFACEDESC2 ddsd; + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize=sizeof(DDSURFACEDESC2); + ddsd.dwFlags=DDSD_WIDTH | DDSD_HEIGHT; + pic->GetSurfaceDesc(&ddsd); + width=ddsd.dwWidth; + height=ddsd.dwHeight; + } + + if(x+width<0 || y+height<0) return; + if(x>r.right || y>r.bottom) return; + + if(x<0 || y<0 || x+width>=r.right || y+height>=r.bottom) + { + + + RECT blrect; + RECT srcRect; + srcRect.left=0; + srcRect.top=0; + srcRect.right=width; + srcRect.bottom=height; + blrect.left=x; + if(blrect.left<0) + { + srcRect.left=r.left+1-blrect.left; + blrect.left=r.left+1; + } + blrect.top=y; + if(blrect.top<0) + { + + //errstream << "BlRect.top=" << blrect.top << endl; + srcRect.top=(r.top+1)-blrect.top; //(r.top-blrect.top); + blrect.top=r.top+1;//r.top; + // errstream << blrect.top << " " << srcRect.top << endl; + } + blrect.right=(x+width); + if(x+width>r.right) + { + srcRect.right=width-((x+width)-r.right);// -(-blrect.right+r.right); + blrect.right=r.right; + } + blrect.bottom=(y+height); + if(y+height>r.bottom) + { + srcRect.bottom=height-((y+height)-r.bottom); // -(-blrect.bottom+r.bottom); + blrect.bottom=r.bottom; + } + DDBLTFX fx; + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + lpdsBack->Blt(&blrect, pic, &srcRect, DDBLT_KEYSRC, &fx); + } + else + lpdsBack->BltFast(x,y, pic, NULL, DDBLTFAST_SRCCOLORKEY); + } + void updateFontScaled(); + void TextOut(int x, int y, const char* text, COLORREF col); + void TextOut(HDC hDC, int x, int y, const char* text, COLORREF col); + LPDIRECTDRAWSURFACE4 lpdsBack; + LPDIRECTDRAWSURFACE4 lpdsTemp; // used for saving the isoview when drawing current tile + LPDIRECTDRAWSURFACE4 lpdsBackHighRes; // used for rendering text and some lines in high-res + LPDIRECTDRAWSURFACE4 lpds; + DDPIXELFORMAT pf; + std::unique_ptr m_color_converter; + LPDIRECTDRAW4 dd; + LPDIRECTDRAW dd_1; + HGLRC m_hglrc; + void HandleProperties(int n, int type); + void UpdateDialog(BOOL bRepos=TRUE); + CMenu m_menu; + BOOL b_IsLoading; + int m_fontDefaultHeight; + int m_Font9Height; + std::unique_ptr m_textDefault; + std::unique_ptr m_textScaled; + std::unique_ptr m_text9; + std::unique_ptr m_text9Scaled; + std::unique_ptr m_textBlue; + std::unique_ptr m_textBlue9; + std::unique_ptr m_textBlueScaled; + std::unique_ptr m_textBlue9Scaled; + +private: + void UpdateScrollRanges(); + +private: + RECT m_myRect; + + + // mapdata* _map; + COLORREF m_linecolor; + RECT line; + int m_type; + int m_id; + BOOL m_drag; + BOOL m_moved; + MapCoords m_cellCursor; +public: + afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); + void Zoom(CPoint& pt, float f); + afx_msg void OnMButtonDown(UINT nFlags, CPoint point); + afx_msg void OnMButtonUp(UINT nFlags, CPoint point); +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} + +#endif // AFX_ISOVIEW_H__7FB6D6A0_7B52_11D3_99E1_DA6DFD21E706__INCLUDED_ diff --git a/MissionEditor/Lighting.cpp b/MissionEditor/Lighting.cpp new file mode 100644 index 0000000..5470b06 --- /dev/null +++ b/MissionEditor/Lighting.cpp @@ -0,0 +1,226 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Lighting.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "Lighting.h" +#include "mapdata.h" +#include "variables.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Eigenschaftenseite CLighting + +IMPLEMENT_DYNCREATE(CLighting, CDialog) + +CLighting::CLighting() : CDialog(CLighting::IDD) +{ + //{{AFX_DATA_INIT(CLighting) + //}}AFX_DATA_INIT +} + +CLighting::~CLighting() +{ +} + +void CLighting::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CLighting) + DDX_Control(pDX, IDC_RED2, m_Red2); + DDX_Control(pDX, IDC_RED, m_Red); + DDX_Control(pDX, IDC_LEVEL2, m_Level2); + DDX_Control(pDX, IDC_LEVEL, m_Level); + DDX_Control(pDX, IDC_GREEN2, m_Green2); + DDX_Control(pDX, IDC_GREEN, m_Green); + DDX_Control(pDX, IDC_BLUE2, m_Blue2); + DDX_Control(pDX, IDC_BLUE, m_Blue); + DDX_Control(pDX, IDC_AMBIENT2, m_Ambient2); + DDX_Control(pDX, IDC_AMBIENT, m_Ambient); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CLighting, CDialog) + //{{AFX_MSG_MAP(CLighting) + ON_EN_CHANGE(IDC_AMBIENT, OnChangeAmbient) + ON_EN_CHANGE(IDC_LEVEL, OnChangeLevel) + ON_EN_KILLFOCUS(IDC_AMBIENT, OnKillfocusAmbient) + ON_EN_CHANGE(IDC_RED, OnChangeRed) + ON_EN_CHANGE(IDC_GREEN, OnChangeGreen) + ON_EN_CHANGE(IDC_BLUE, OnChangeBlue) + ON_EN_CHANGE(IDC_AMBIENT2, OnChangeAmbient2) + ON_EN_CHANGE(IDC_LEVEL2, OnChangeLevel2) + ON_EN_CHANGE(IDC_RED2, OnChangeRed2) + ON_EN_CHANGE(IDC_GREEN2, OnChangeGreen2) + ON_EN_CHANGE(IDC_BLUE2, OnChangeBlue2) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CLighting + +void CLighting::UpdateDialog() +{ + CIniFile& ini=Map->GetIniFile(); + + m_Ambient.SetWindowText(ini.sections["Lighting"].values["Ambient"]); + m_Ambient2.SetWindowText(ini.sections["Lighting"].values["IonAmbient"]); + m_Level.SetWindowText(ini.sections["Lighting"].values["Level"]); + m_Level2.SetWindowText(ini.sections["Lighting"].values["IonLevel"]); + m_Red.SetWindowText(ini.sections["Lighting"].values["Red"]); + m_Red2.SetWindowText(ini.sections["Lighting"].values["IonRed"]); + m_Green.SetWindowText(ini.sections["Lighting"].values["Green"]); + m_Green2.SetWindowText(ini.sections["Lighting"].values["IonGreen"]); + m_Blue.SetWindowText(ini.sections["Lighting"].values["Blue"]); + m_Blue2.SetWindowText(ini.sections["Lighting"].values["IonBlue"]); + //MessageBox(ini.sections["Lightning"].values["Ambient"]); +} + +BOOL CLighting::OnInitDialog() +{ + CDialog::OnInitDialog(); + +#ifdef RA2_MODE + SetDlgItemText(IDC_LIONSTORM, "Weather Storm Settings"); +#endif + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} + + + + + +void CLighting::OnChangeAmbient() +{ + CIniFile& ini=Map->GetIniFile(); + + CString ctext; + m_Ambient.GetWindowText(ctext); + CString text=(char*)(LPCTSTR)ctext; + ini.sections["Lighting"].values["Ambient"]=text; + +} + +void CLighting::OnChangeLevel() +{ + CIniFile& ini=Map->GetIniFile(); + + CString ctext; + m_Level.GetWindowText(ctext); + CString text=(char*)(LPCTSTR)ctext; + ini.sections["Lighting"].values["Level"]=text; + +} + +void CLighting::OnKillfocusAmbient() +{ + +} + +void CLighting::OnChangeRed() +{ + CIniFile& ini=Map->GetIniFile(); + + CString ctext; + m_Red.GetWindowText(ctext); + CString text=(char*)(LPCTSTR)ctext; + ini.sections["Lighting"].values["Red"]=text; +} + +void CLighting::OnChangeGreen() +{ + CIniFile& ini=Map->GetIniFile(); + + CString ctext; + m_Green.GetWindowText(ctext); + CString text=(char*)(LPCTSTR)ctext; + ini.sections["Lighting"].values["Green"]=text; +} + +void CLighting::OnChangeBlue() +{ + CIniFile& ini=Map->GetIniFile(); + + CString ctext; + m_Blue.GetWindowText(ctext); + CString text=(char*)(LPCTSTR)ctext; + ini.sections["Lighting"].values["Blue"]=text; +} + +void CLighting::OnChangeAmbient2() +{ + CIniFile& ini=Map->GetIniFile(); + + CString ctext; + m_Ambient2.GetWindowText(ctext); + CString text=(char*)(LPCTSTR)ctext; + ini.sections["Lighting"].values["IonAmbient"]=text; +} + +void CLighting::OnChangeLevel2() +{ + CIniFile& ini=Map->GetIniFile(); + + CString ctext; + m_Level2.GetWindowText(ctext); + CString text=(char*)(LPCTSTR)ctext; + ini.sections["Lighting"].values["IonLevel"]=text; +} + +void CLighting::OnChangeRed2() +{ + CIniFile& ini=Map->GetIniFile(); + + CString ctext; + m_Red2.GetWindowText(ctext); + CString text=(char*)(LPCTSTR)ctext; + ini.sections["Lighting"].values["IonRed"]=text; +} + +void CLighting::OnChangeGreen2() +{ + CIniFile& ini=Map->GetIniFile(); + + CString ctext; + m_Green2.GetWindowText(ctext); + CString text=(char*)(LPCTSTR)ctext; + ini.sections["Lighting"].values["IonGreen"]=text; +} + +void CLighting::OnChangeBlue2() +{ + CIniFile& ini=Map->GetIniFile(); + + CString ctext; + m_Blue2.GetWindowText(ctext); + CString text=(char*)(LPCTSTR)ctext; + ini.sections["Lighting"].values["IonBlue"]=text; +} diff --git a/MissionEditor/Lighting.h b/MissionEditor/Lighting.h new file mode 100644 index 0000000..a371a1d --- /dev/null +++ b/MissionEditor/Lighting.h @@ -0,0 +1,92 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_LIGHTNING_H__9DC7B326_6DF2_11D3_99E1_D14A1D4DCF07__INCLUDED_) +#define AFX_LIGHTNING_H__9DC7B326_6DF2_11D3_99E1_D14A1D4DCF07__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Lightning.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CLighting + + + +class CLighting : public CDialog +{ + DECLARE_DYNCREATE(CLighting) + +// Konstruktion +public: + void UpdateDialog(); + CLighting(); + ~CLighting(); + +// Dialogfelddaten + //{{AFX_DATA(CLighting) + enum { IDD = IDD_LIGHTING }; + CFloatEdit m_Red2; + CFloatEdit m_Red; + CFloatEdit m_Level2; + CFloatEdit m_Level; + CFloatEdit m_Green2; + CFloatEdit m_Green; + CFloatEdit m_Blue2; + CFloatEdit m_Blue; + CFloatEdit m_Ambient2; + CFloatEdit m_Ambient; + //}}AFX_DATA + + +// Ăœberschreibungen + // Der Klassen-Assistent generiert virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CLighting) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CLighting) + virtual BOOL OnInitDialog(); + afx_msg void OnChangeAmbient(); + afx_msg void OnChangeLevel(); + afx_msg void OnKillfocusAmbient(); + afx_msg void OnChangeRed(); + afx_msg void OnChangeGreen(); + afx_msg void OnChangeBlue(); + afx_msg void OnChangeAmbient2(); + afx_msg void OnChangeLevel2(); + afx_msg void OnChangeRed2(); + afx_msg void OnChangeGreen2(); + afx_msg void OnChangeBlue2(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_LIGHTNING_H__9DC7B326_6DF2_11D3_99E1_D14A1D4DCF07__INCLUDED_ diff --git a/MissionEditor/LineDrawer.cpp b/MissionEditor/LineDrawer.cpp new file mode 100644 index 0000000..a7d9ce5 --- /dev/null +++ b/MissionEditor/LineDrawer.cpp @@ -0,0 +1,148 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "StdAfx.h" +#include "LineDrawer.h" +#include +#include + +static int ModLookup[] = { + 1, + 2, + 3, + 4 +}; + +LineDrawer::LineDrawer(void* dest, int bytes_per_pixel, int width, int height, int pitch): + m_dest(dest), + m_bytes_per_pixel(bytes_per_pixel), + m_width(width), + m_height(height), + m_pitch(pitch), + m_last_x(0), + m_last_y(0) +{ +} + +void LineDrawer::MoveTo(int to_x, int to_y) +{ + m_last_x = to_x; + m_last_y = to_y; +} + +void LineDrawer::LineTo(int to_x, int to_y, int color, LineStyle style) +{ + DrawLine(m_last_x, m_last_y, to_x, to_y, color, style); +} + +void LineDrawer::DrawLine(int from_x, int from_y, int to_x, int to_y, int color, LineStyle style) +{ + const int w = to_x - from_x; + const int h = to_y - from_y; + m_last_x = to_x; + m_last_y = to_y; + if (abs(w) >= abs(h)) { + return w >= 0 ? DrawLineImplX(from_x, from_y, to_x, to_y, color, style) : DrawLineImplX(to_x, to_y, from_x, from_y, color, style); + } + else { + return h >= 0 ? DrawLineImplY(from_x, from_y, to_x, to_y, color, style) : DrawLineImplY(to_x, to_y, from_x, from_y, color, style); + } +} + +void LineDrawer::Rectangle(int from_x, int from_y, int to_x, int to_y, int color, LineStyle style) +{ + MoveTo(from_x, from_y); + LineTo(to_x, from_y, color, style); + LineTo(to_x, to_y, color, style); + LineTo(from_x, to_y, color, style); + LineTo(from_x, from_y, color, style); +} + +void LineDrawer::SetPixel(char* const dest, const int cur_x, const int cur_y, const int color) +{ + if (cur_x >= 0 && cur_y >= 0 && cur_x < m_width && cur_y < m_height) + memcpy(&dest[cur_x * m_bytes_per_pixel + cur_y * m_pitch], &color, m_bytes_per_pixel); +} + +void LineDrawer::DrawLineImplX(const int from_x, const int from_y, const int to_x, const int to_y, const int color, const LineStyle style) +{ + // X major line drawing + + assert (from_x <= to_x); + const int w = to_x - from_x; + const int h = abs(to_y - from_y); + assert (w >= h); + const int increment_e = 2 * h; + const int increment_ne = 2 * (h - w); + const int y_inc = (to_y - from_y) < 0 ? -1 : 1; + int d = 2 * h - w; + int cur_x = from_x; + int cur_y = from_y; + const int mod = ModLookup[static_cast(style)]; + + char* dest = reinterpret_cast(m_dest); + SetPixel(dest, cur_x, cur_y, color); + + for(; cur_x < to_x; ++cur_x) + { + if (d < 0) { + d += increment_e; + } + else { + d += increment_ne; + cur_y += y_inc; + } + if (mod == 1 || (cur_x - from_x) % mod == 0) + SetPixel(dest, cur_x, cur_y, color); + } +} + +void LineDrawer::DrawLineImplY(const int from_x, const int from_y, const int to_x, const int to_y, const int color, LineStyle style) +{ + // Y major line drawing + + assert(from_y <= to_y); + const int w = abs(to_x - from_x); + const int h = to_y - from_y; + assert(h >= w); + const int increment_e = 2 * w; + const int increment_ne = 2 * (w - h); + const int x_inc = (to_x - from_x) < 0 ? -1 : 1; + int d = 2 * w - h; + int cur_x = from_x; + int cur_y = from_y; + const int mod = ModLookup[static_cast(style)]; + + char* dest = reinterpret_cast(m_dest); + SetPixel(dest, cur_x, cur_y, color); + + for (; cur_y < to_y; ++cur_y) + { + if (d < 0) { + d += increment_e; + } + else { + d += increment_ne; + cur_x += x_inc; + } + if (mod == 1 || (cur_y - from_y) % mod == 0) + SetPixel(dest, cur_x, cur_y, color); + } +} diff --git a/MissionEditor/LineDrawer.h b/MissionEditor/LineDrawer.h new file mode 100644 index 0000000..550b24c --- /dev/null +++ b/MissionEditor/LineDrawer.h @@ -0,0 +1,56 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include + +enum class LineStyle: int +{ + Standard, + Dotted_2, + Dotted_3, + Dotted_4, +}; + +class LineDrawer +{ +public: + LineDrawer(void* dest, int bytes_per_pixel, int width, int height, int pitch); + + void MoveTo(int to_x, int to_y); + void LineTo(int to_x, int to_y, int color, LineStyle style = LineStyle::Standard); + void DrawLine(int from_x, int from_y, int to_x, int to_y, int color, LineStyle style = LineStyle::Standard); + void Rectangle(int from_x, int from_y, int to_x, int to_y, int color, LineStyle style = LineStyle::Standard); + +private: + void SetPixel(char* dest, int cur_x, int cur_y, int color); + void DrawLineImplX(int from_x, int from_y, int to_x, int to_y, int color, LineStyle style); + void DrawLineImplY(int from_x, int from_y, int to_x, int to_y, int color, LineStyle style); + +private: + void* m_dest; + int m_bytes_per_pixel; + int m_width; + int m_height; + int m_pitch; + int m_last_x; + int m_last_y; +}; \ No newline at end of file diff --git a/MissionEditor/Loading.cpp b/MissionEditor/Loading.cpp new file mode 100644 index 0000000..f41bd9b --- /dev/null +++ b/MissionEditor/Loading.cpp @@ -0,0 +1,6972 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Loading.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "Loading.h" +#include +#include +#include +#include +#include +#include "resource.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" +#include "inlines.h" +#include "MissionEditorPackLib.h" +#include +#include +#include "VoxelNormals.h" +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CLoading + + +CLoading::CLoading(CWnd* pParent /*=NULL*/) + : CDialog(CLoading::IDD, pParent) +{ + //{{AFX_DATA_INIT(CLoading) + //}}AFX_DATA_INIT + + Create(CLoading::IDD, pParent); + + loaded=FALSE; + cur_theat='T'; + + + + m_hCache=NULL; + m_hConquer=NULL; + m_hIsoSnow=NULL; + m_hIsoTemp=NULL; + m_hLocal=NULL; + m_hTemperat=NULL; + m_hTibSun=NULL; + m_hLangMD=NULL; + m_pic_count=0; + + s_tiledata=NULL; + t_tiledata=NULL; + u_tiledata=NULL; + s_tiledata_count=0; + t_tiledata_count=0; + u_tiledata_count=0; + tiledata=NULL; + tiledata_count=0; + + int i=0; + for(i=0;i<101; i++) + { + + m_hExpand[i].hExpand=NULL; + } + for(i=0;i<100; i++) + { + + m_hECache[i]=NULL; + } + + errstream << "CLoading::CLoading() called" << endl; + errstream.flush(); +} + + +void CLoading::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CLoading) + DDX_Control(pDX, IDC_VERSION, m_Version); + DDX_Control(pDX, IDC_BUILTBY, m_BuiltBy); + DDX_Control(pDX, IDC_CAP, m_cap); + DDX_Control(pDX, IDC_PROGRESS1, m_progress); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CLoading, CDialog) + //{{AFX_MSG_MAP(CLoading) + ON_WM_DESTROY() + ON_WM_PAINT() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// message handlers CLoading + +BOOL bUseFirestorm=TRUE; + +void CLoading::Load() +{ + auto startTime = std::chrono::steady_clock::now(); + + + CString artFile; + + + + + // show a wait cursor + SetCursor(LoadCursor(NULL, IDC_WAIT)); + + // write a log + errstream << "CLoading::Load() called" << std::endl << std::endl; + errstream.flush(); + + + // initialize the FSunPackLib::XCC + errstream << "Initializing FSunPackLib::XCC" << std::endl; + errstream.flush(); + FSunPackLib::XCC_Initialize(TRUE); + m_cap.SetWindowText(GetLanguageStringACP("LoadExtractStdMixFiles")); + + errstream << "Initializing mix files" << std::endl; + errstream.flush(); + MEMORYSTATUS ms; + ms.dwLength=sizeof(MEMORYSTATUS); + GlobalMemoryStatus(&ms); + int cs=ms.dwAvailPhys+ms.dwAvailPageFile; + InitMixFiles(); + errstream << "Loading palettes" << std::endl << std::endl; + errstream.flush(); + InitPalettes(); + + // Load voxel normal tables + InitVoxelNormalTables(); + + + // create a ini file containing some info XCC Mixer needs + CreateINI(); + + // set progress bar range to 0-2 + m_progress.SetRange(0,2); + + // rules.ini + m_cap.SetWindowText(GetLanguageStringACP("LoadLoadRules")); + m_progress.SetPos(1); + UpdateWindow(); + LoadTSIni("Rules.ini", &rules, FALSE); + +#ifdef TS_MODE + if(bUseFirestorm) + { + // very special case, the types list don´t have any order according to the original rules! + CIniFile fstorm; + LoadTSIni("firestrm.ini", &fstorm, TRUE); + + int i; + CString cuSection; + cuSection="InfantryTypes"; + for(i=0;i0) + { + rules=rulesmd; + } + } +#endif + + m_progress.SetPos(2); + //rules.DeleteLeadingSpaces(TRUE, TRUE); + //rules.DeleteEndingSpaces(TRUE, TRUE); + + PrepareHouses(); + HackRules(); + + UpdateWindow(); + + + // art.ini + m_cap.SetWindowText(GetLanguageStringACP("LoadLoadArt")); + m_progress.SetPos(1); + UpdateWindow(); + LoadTSIni("Art.ini", &art, FALSE); +#ifdef TS_MODE + if(bUseFirestorm) // LoadTSIni("ArtFs.ini", &art, TRUE); + { + CIniFile artfs; + LoadTSIni("artfs.ini", &artfs, TRUE); + + // MW April 8th: bugfix... we erased Movies even if there was no new data!!! + if(artfs.sections.size()) + { + + int i; + CString cuSection; + cuSection="Movies"; + art.sections.erase(cuSection); + /*for(i=0;i0) + { + art.Clear(); + art=artmd; + } + } +#endif + + + + m_progress.SetPos(2); + //art.DeleteLeadingSpaces(TRUE, TRUE); + //art.DeleteEndingSpaces(TRUE, TRUE); + UpdateWindow(); + + // tutorial.ini + m_cap.SetWindowText(GetLanguageStringACP("LoadLoadTutorial")); + m_progress.SetPos(1); + UpdateWindow(); + LoadTSIni("Tutorial.ini", &tutorial, FALSE); + + // sound.ini + m_cap.SetWindowText(GetLanguageStringACP("LoadLoadSound")); + m_progress.SetPos(1); + UpdateWindow(); + + + if(bUseFirestorm) + { + int b; + for(b=99;b>0;b--) + { + char p[50]; + itoa(b, p, 10); + CString name="Sound"; + if(strlen(p)<2) name+="0"; + name+=p; + name+=".ini"; + + LoadTSIni(name, &sound, FALSE); + if(sound.sections.size()>0) break; + } + + } else LoadTSIni("Sound01.ini", &sound, FALSE); + if(sound.sections.size()==0) LoadTSIni("Sound.ini", &sound, FALSE); + + m_progress.SetPos(2); + UpdateWindow(); + + // eva.INI + m_cap.SetWindowText(GetLanguageStringACP("LoadLoadEva")); + m_progress.SetPos(1); + UpdateWindow(); + LoadTSIni("eva.ini", &eva, FALSE); + m_progress.SetPos(2); + UpdateWindow(); + + // theme.INI + m_cap.SetWindowText(GetLanguageStringACP("LoadLoadTheme")); + m_progress.SetPos(1); + UpdateWindow(); + LoadTSIni("theme.ini", &theme, FALSE); + m_progress.SetPos(2); + UpdateWindow(); + + + // AI.INI + m_cap.SetWindowText(GetLanguageStringACP("LoadLoadAI")); + m_progress.SetPos(1); + UpdateWindow(); + LoadTSIni("Ai.ini", &ai, FALSE); +#ifdef TS_MODE + if(bUseFirestorm) LoadTSIni("aifs.ini", &ai, TRUE);; +#else + if(bUseFirestorm && yuri_mode) LoadTSIni("aimd.ini", &ai, TRUE); // YR +#endif + m_progress.SetPos(2); + UpdateWindow(); + + + const BOOL preferLocalTheater = theApp.m_Options.bPreferLocalTheaterFiles ? TRUE : FALSE; + + // Temperat.INI + m_cap.SetWindowText(GetLanguageStringACP("LoadLoadTemperat")); + m_progress.SetPos(1); + UpdateWindow(); + LoadTSIni("Temperat.ini", &tiles_t, FALSE, preferLocalTheater); + if(yuri_mode) LoadTSIni("TemperatMD.ini", &tiles_t, TRUE, preferLocalTheater); + m_progress.SetPos(2); + UpdateWindow(); + + // Snow.INI + m_cap.SetWindowText(GetLanguageStringACP("LoadLoadSnow")); + m_progress.SetPos(1); + UpdateWindow(); + LoadTSIni("Snow.ini", &tiles_s, FALSE, preferLocalTheater); + if(yuri_mode) LoadTSIni("SnowMD.ini", &tiles_s, TRUE, preferLocalTheater); + m_progress.SetPos(2); + UpdateWindow(); + + // Urban.INI + m_cap.SetWindowText(GetLanguageStringACP("LoadLoadUrban")); + m_progress.SetPos(1); + UpdateWindow(); + LoadTSIni("Urban.ini", &tiles_u, FALSE, preferLocalTheater); + if(yuri_mode) LoadTSIni("UrbanMD.ini", &tiles_u, TRUE, preferLocalTheater); + m_progress.SetPos(2); + UpdateWindow(); + + if(yuri_mode) + { + m_cap.SetWindowText(GetLanguageStringACP("LoadLoadUrbanN")); + m_progress.SetPos(1); + UpdateWindow(); + LoadTSIni("UrbanNMD.ini", &tiles_un, FALSE, preferLocalTheater); + m_progress.SetPos(2); + UpdateWindow(); + + // MW FIX: MAKE URBAN RAMPS MORPHABLE: + if(tiles_un.sections["TileSet0117"].FindName("Morphable")<0) + tiles_un.sections["TileSet0117"].values["Morphable"]="true"; + + m_cap.SetWindowText(GetLanguageStringACP("LoadLoadLunar")); + m_progress.SetPos(1); + UpdateWindow(); + LoadTSIni("LunarMD.ini", &tiles_l, FALSE, preferLocalTheater); + m_progress.SetPos(2); + UpdateWindow(); + + m_cap.SetWindowText(GetLanguageStringACP("LoadLoadDesert")); + m_progress.SetPos(1); + UpdateWindow(); + LoadTSIni("DesertMD.ini", &tiles_d, FALSE, preferLocalTheater); + m_progress.SetPos(2); + UpdateWindow(); + } + + + + // load Command & Conquer Rules.ini section names + LoadStrings(); + + + // ok now directdraw + m_cap.SetWindowText(GetLanguageStringACP("LoadInitDDraw")); + m_progress.SetRange(0,4); + + InitDirectDraw(); + + m_progress.SetPos(3); + UpdateWindow(); + + /*errstream << "Now calling InitPics()\n"; + errstream.flush(); + m_cap.SetWindowText(GetLanguageStringACP("LoadInitPics")); + InitPics(); + errstream << "InitPics() finished\n\n\n"; + errstream.flush();*/ + + auto delay = std::chrono::duration(theApp.m_Options.fLoadScreenDelayInSeconds); + if ((std::chrono::steady_clock::now() - startTime) < delay) + { + std::this_thread::sleep_until(startTime + delay); + } + + DestroyWindow(); + +} + + + +// +// InitPics loads all graphics except terrain graphics! +void CLoading::InitPics(CProgressCtrl* prog) +{ + MEMORYSTATUS ms; + ms.dwLength=sizeof(MEMORYSTATUS); + GlobalMemoryStatus(&ms); + int cs=ms.dwAvailPhys+ms.dwAvailPageFile; + + errstream << "InitPics() called. Available memory: " << cs << endl; + errstream.flush(); + + + + + CalcPicCount(); + + if(m_progress.m_hWnd!=NULL) m_progress.SetRange(0,m_pic_count/15+1); + + if(!theApp.m_Options.bDoNotLoadBMPs) + { + int k; + CFileFind ff; + CString bmps=(CString)AppPath+"\\pics2\\*.bmp"; + if(ff.FindFile(bmps)) + { + + BOOL lastFile=FALSE; + + for(k=0;km_view.m_isoview->dd, *BitmapFromFile(ff.GetFilePath())).Detach(); + + DDSURFACEDESC2 desc; + memset(&desc, 0, sizeof(DDSURFACEDESC2)); + desc.dwSize = sizeof(DDSURFACEDESC2); + desc.dwFlags = DDSD_HEIGHT | DDSD_WIDTH; + ((LPDIRECTDRAWSURFACE4)pics[(LPCTSTR)ff.GetFileName()].pic)->GetSurfaceDesc(&desc); + pics[(LPCTSTR)ff.GetFileName()].wHeight = desc.dwHeight; + pics[(LPCTSTR)ff.GetFileName()].wWidth = desc.dwWidth; + pics[(LPCTSTR)ff.GetFileName()].wMaxWidth = desc.dwWidth; + pics[(LPCTSTR)ff.GetFileName()].wMaxHeight = desc.dwHeight; + pics[(LPCTSTR)ff.GetFileName()].bType = PICDATA_TYPE_BMP; + + FSunPackLib::SetColorKey(((LPDIRECTDRAWSURFACE4)(pics[(LPCTSTR)ff.GetFileName()].pic)), -1); + } + catch (const BitmapNotFound&) + { + } + + if(m_progress.m_hWnd!=NULL && k%15==0) + { + m_progress.SetPos(m_progress.GetPos()+1); + UpdateWindow(); + } + } + } + } + + DDSURFACEDESC2 desc; + + try { + pics["SCROLLCURSOR"].pic = BitmapToSurface(((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->dd, *BitmapFromResource(IDB_SCROLLCURSOR)).Detach(); + FSunPackLib::SetColorKey((LPDIRECTDRAWSURFACE4)pics["SCROLLCURSOR"].pic, -1); + memset(&desc, 0, sizeof(DDSURFACEDESC2)); + desc.dwSize = sizeof(DDSURFACEDESC2); + desc.dwFlags = DDSD_HEIGHT | DDSD_WIDTH; + ((LPDIRECTDRAWSURFACE4)pics["SCROLLCURSOR"].pic)->GetSurfaceDesc(&desc); + pics["SCROLLCURSOR"].wHeight = desc.dwHeight; + pics["SCROLLCURSOR"].wWidth = desc.dwWidth; + pics["SCROLLCURSOR"].bType = PICDATA_TYPE_BMP; + } + catch (const BitmapNotFound&) + { + } + + try { + pics["CELLTAG"].pic = BitmapToSurface(((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->dd, *BitmapFromResource(IDB_CELLTAG)).Detach(); + FSunPackLib::SetColorKey((LPDIRECTDRAWSURFACE4)pics["CELLTAG"].pic, CLR_INVALID); + memset(&desc, 0, sizeof(DDSURFACEDESC2)); + desc.dwSize = sizeof(DDSURFACEDESC2); + desc.dwFlags = DDSD_HEIGHT | DDSD_WIDTH; + ((LPDIRECTDRAWSURFACE4)pics["CELLTAG"].pic)->GetSurfaceDesc(&desc); + pics["CELLTAG"].wHeight = desc.dwHeight; + pics["CELLTAG"].wWidth = desc.dwWidth; +#ifdef RA2_MODE + pics["CELLTAG"].x = -1; + pics["CELLTAG"].y = 0; +#else + pics["CELLTAG"].x = -1; + pics["CELLTAG"].y = -1; +#endif + pics["CELLTAG"].bType = PICDATA_TYPE_BMP; + } + catch (const BitmapNotFound&) + { + } + + try + { + pics["FLAG"].pic = BitmapToSurface(((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->dd, *BitmapFromResource(IDB_FLAG)).Detach(); + FSunPackLib::SetColorKey((LPDIRECTDRAWSURFACE4)pics["FLAG"].pic, -1); + memset(&desc, 0, sizeof(DDSURFACEDESC2)); + desc.dwSize = sizeof(DDSURFACEDESC2); + desc.dwFlags = DDSD_HEIGHT | DDSD_WIDTH; + ((LPDIRECTDRAWSURFACE4)pics["FLAG"].pic)->GetSurfaceDesc(&desc); + pics["FLAG"].wHeight = desc.dwHeight; + pics["FLAG"].wWidth = desc.dwWidth; + pics["FLAG"].bType = PICDATA_TYPE_BMP; + } + catch (const BitmapNotFound&) + { + } + + + + // MW April 2nd, 2001 + // prepare 1x1 hidden tile replacement + DDSURFACEDESC2 ddsd; + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize=sizeof(DDSURFACEDESC2); + ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN; + ddsd.dwFlags=DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.dwWidth=f_x; + ddsd.dwHeight=f_y; + + LPDIRECTDRAWSURFACE4 srf=NULL; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->dd->CreateSurface(&ddsd, &srf, 0); + + pics["HTILE"].pic=srf; + pics["HTILE"].wHeight=ddsd.dwHeight; + pics["HTILE"].wWidth=ddsd.dwWidth; + pics["HTILE"].bType=PICDATA_TYPE_BMP; + + HDC hDC; + srf->GetDC(&hDC); + + HPEN p; + int width=1; + p=CreatePen(PS_DOT, 0, RGB(0,120,0)); + + SelectObject(hDC,p); + + POINT p1, p2, p3, p4; + p1.x=f_x/2; + p1.y=0; + p2.x=f_x/2+f_x/2; + p2.y=f_y/2; + p3.x=f_x/2-f_x/2+f_x/2-1; + p3.y=f_y/2+f_y/2-1; + p4.x=f_x/2+f_x/2-1; + p4.y=f_y/2-1; + + + SetBkMode(hDC, TRANSPARENT); + MoveToEx(hDC, p1.x,p1.y-1,NULL); + LineTo(hDC, p2.x+1,p2.y); + LineTo(hDC, p3.x,p3.y+1); + LineTo(hDC, p4.x-1, p4.y); + LineTo(hDC, p1.x, p1.y-1); + + srf->ReleaseDC(hDC); + + DeleteObject(p); + + + // new: Prepare building terrain information: + int i; + for(i=0;iLoadFile(u8AppDataPath + lpFilename, TRUE); + else + lpIniFile->InsertFile(u8AppDataPath + lpFilename, NULL, TRUE); + return; + } + + // check if file is available in the editors root folder + if(DoesFileExist(CString(AppPath) + lpFilename)) + { + errstream << "File found in Mission Editor directory (" << AppPath << ")" << endl; + errstream.flush(); + if(!bIsExpansion) + lpIniFile->LoadFile((CString)AppPath+lpFilename, TRUE); + else + lpIniFile->InsertFile((CString)AppPath+lpFilename, NULL, TRUE); + return; + } + } + + if(theApp.m_Options.bSearchLikeTS) + { + + + // check if Rules.ini is available + if(DoesFileExist((CString)TSPath+lpFilename)) + { + errstream << "File found in TS directory (" << TSPath << ")" << endl; + errstream.flush(); + if(!bIsExpansion) + lpIniFile->LoadFile((CString)TSPath+lpFilename, TRUE); + else + lpIniFile->InsertFile((CString)TSPath+lpFilename, NULL, TRUE); + return; + } + + + BOOL bExpandFound=FALSE; + + + + /*int i; + for(i=1;i<101;i++) + { + if(m_hExpand[i].hExpand!=NULL) + { + if(FSunPackLib::XCC_ExtractFile(lpFilename, (CString)TSPath+(CString)"FinalSun"+lpFilename, m_hExpand[i].hExpand)) + { + + errstream << lpFilename << " found in expansion #" << i << endl; + errstream.flush(); + + //if(!bIsExpansion) + // lpIniFile->InsertFile((CString)TSPath+(CString)"FinalSun"+lpFilename, NULL); + //else + lpIniFile->InsertFile((CString)TSPath+(CString)"FinalSun"+lpFilename, NULL, TRUE); + + DeleteFile((CString)TSPath+(CString)"FinalSun"+lpFilename); + + bExpandFound=TRUE; + } + + } + }*/ + + HMIXFILE hMix=FindFileInMix(lpFilename); + if(hMix) + { + if(FSunPackLib::XCC_ExtractFile(lpFilename, (CString)TSPath+(CString)"FinalSun"+lpFilename, hMix)) + { + + errstream << lpFilename << " found " << endl; + errstream.flush(); + + //if(!bIsExpansion) + // lpIniFile->InsertFile((CString)TSPath+(CString)"FinalSun"+lpFilename, NULL); + //else + lpIniFile->InsertFile((CString)TSPath+(CString)"FinalSun"+lpFilename, NULL, TRUE); + + DeleteFile((CString)TSPath+(CString)"FinalSun"+lpFilename); + + bExpandFound=TRUE; + } + } + + if(!bIsExpansion && !bExpandFound) + { + // not found, go ahead if this is not a expansion only file... + FSunPackLib::XCC_ExtractFile(lpFilename,(CString)TSPath+(CString)"FinalSun"+lpFilename, m_hLocal); + + lpIniFile->LoadFile((CString)TSPath+(CString)"FinalSun"+lpFilename, TRUE); + + DeleteFile((CString)TSPath+(CString)"FinalSun"+lpFilename); + } + + + } + else if(bIsExpansion==FALSE) + { + FSunPackLib::XCC_ExtractFile(lpFilename,(CString)TSPath+(CString)"FinalSun"+lpFilename, m_hLocal); + + lpIniFile->LoadFile((CString)TSPath+(CString)"FinalSun"+lpFilename, TRUE); + DeleteFile((CString)TSPath+(CString)"FinalSun"+lpFilename); + return; + } +} + + +void CLoading::InitSHPs(CProgressCtrl* prog) +{ + MEMORYSTATUS ms; + ms.dwLength=sizeof(MEMORYSTATUS); + GlobalMemoryStatus(&ms); + int cs=ms.dwAvailPhys+ms.dwAvailPageFile; + + errstream << "InitSHPs() called. Available memory: " << cs << endl; + errstream.flush(); + + int i; + + // overlay: + if(!theApp.m_Options.bDoNotLoadOverlayGraphics) + for(i=0;i=dwidth || y>=dheight) return; + + + RECT blrect; + RECT srcRect; + srcRect.left=0; + srcRect.top=0; + srcRect.right=swidth; + srcRect.bottom=sheight; + blrect.left=x; + if(blrect.left<0) + { + srcRect.left=1-blrect.left; + blrect.left=1; + } + blrect.top=y; + if(blrect.top<0) + { + srcRect.top=1-blrect.top; + blrect.top=1; + } + blrect.right=(x+swidth); + if(x+swidth>dwidth) + { + srcRect.right=swidth-((x+swidth)-dwidth); + blrect.right=dwidth; + } + blrect.bottom=(y+sheight); + if(y+sheight>dheight) + { + srcRect.bottom=sheight-((y+sheight)-dheight); + blrect.bottom=dheight; + } + + + int i,e; + for(i=srcRect.left;i=dwidth || blrect.top>=dheight) return; + + int x=blrect.left; + int y=blrect.top; + + int i,e; + for(i=srcRect.left;i0 && blrect.top+e>0 && blrect.left+i CLoading::FindUnitShp(const CString& image, char preferred_theat, const CIniFileSection& artSection) +{ + if (image.IsEmpty()) + return std::nullopt; + + const char kTheatersToTry[] = { preferred_theat, 'G', 'T', 'A', 'U', 'N', 'D', 'L', 0}; + const CString kSuffixesToTry[] = { theatToSuffix(preferred_theat), ".tem", ".sno", ".urb", ".lun", ".des", ".ubn", ""}; + + const char first = image.GetAt(0); + const bool firstCharSupportsTheater = first == 'G' || first == 'N' || first == 'C' || first == 'Y'; + + HTSPALETTE forcedPalette = 0; + const auto& unitPalettePrefixes = g_data.sections["ForceUnitPalettePrefix"]; + if (unitPalettePrefixes.end() != std::find_if(unitPalettePrefixes.begin(), unitPalettePrefixes.end(), [&image](const auto& pair) {return image.Find(pair.second) == 0;})) + { + forcedPalette = GetUnitPalette(preferred_theat); + } + + const auto& isoPalettePrefixes = g_data.sections["ForceIsoPalettePrefix"]; + if (isoPalettePrefixes.end() != std::find_if(isoPalettePrefixes.begin(), isoPalettePrefixes.end(), [&image](const auto& pair) {return image.Find(pair.second) == 0;})) + { + forcedPalette = GetIsoPalette(preferred_theat); + } + + const bool isTheater = isTrue(artSection.GetValueByName("Theater")); + const bool isNewTheater = isTrue(artSection.GetValueByName("NewTheater")); + const bool terrainPalette = isTrue(artSection.GetValueByName("TerrainPalette")); + + auto unitOrIsoPalette = terrainPalette ? GetIsoPalette(preferred_theat) : GetUnitPalette(preferred_theat); + + HMIXFILE curMixFile = 0; + CString curFilename = image + ".shp"; + TheaterChar curMixTheater = TheaterChar::None; + char curTheater = 'G'; + CString curSuffix; + + // Phase 0: theater with .tem, .sno etc + if (isTheater) + { + for (int t = 0; !(curSuffix = kSuffixesToTry[t]).IsEmpty(); ++t) + { + curFilename = image + curSuffix; + curFilename.MakeLower(); + curMixFile = FindFileInMix(curFilename, &curMixTheater); + if (curMixFile) + return FindShpResult(curMixFile, curMixTheater, curFilename, toTheaterChar(suffixToTheat(curSuffix)), forcedPalette ? forcedPalette : GetIsoPalette(suffixToTheat(curSuffix))); + } + } + // Phase 1: if NewTheater is enabled and first character indicates support, try with real theater, then in order of kTheatersToTry + // Otherwise, + if (isNewTheater) + { + if (firstCharSupportsTheater) + { + /*curFilename.SetAt(1, preferred_theat); + curMixFile = FindFileInMix(curFilename, &curMixTheater); + if (curMixFile) + return FindShpResult(curMixFile, curMixTheater, curFilename, toTheaterChar(preferred_theat), GetUnitPalette(preferred_theat));*/ + for (int t = 0; curTheater=kTheatersToTry[t]; ++t) + { + curFilename.SetAt(1, curTheater); + curMixFile = FindFileInMix(curFilename, &curMixTheater); + if (curMixFile) + return FindShpResult(curMixFile, curMixTheater, curFilename, toTheaterChar(curTheater), forcedPalette ? forcedPalette : unitOrIsoPalette); + } + } + } + // Phase 2: try again even if isNewTheater is not true but the first char signals it should support theaters + if (firstCharSupportsTheater) + { + /*curFilename.SetAt(1, preferred_theat); + curMixFile = FindFileInMix(curFilename, &curMixTheater); + if (curMixFile) + return FindShpResult(curMixFile, curMixTheater, curFilename, toTheaterChar(preferred_theat), GetUnitPalette(preferred_theat));*/ + for (int t = 0; curTheater = kTheatersToTry[t]; ++t) + { + curFilename.SetAt(1, curTheater); + curMixFile = FindFileInMix(curFilename, &curMixTheater); + if (curMixFile) + return FindShpResult(curMixFile, curMixTheater, curFilename, toTheaterChar(curTheater), forcedPalette ? forcedPalette : unitOrIsoPalette); + } + } + // Phase 3: try unchanged filename + curFilename = image + ".shp"; + curMixFile = FindFileInMix(curFilename, &curMixTheater); + if (curMixFile) + return FindShpResult(curMixFile, curMixTheater, curFilename, toTheaterChar(preferred_theat), forcedPalette ? forcedPalette : unitOrIsoPalette); + // Phase 4: try lowercase and otherwise unchanged filename + curFilename = image + ".shp"; + curFilename.MakeLower(); + curMixFile = FindFileInMix(curFilename, &curMixTheater); + if (curMixFile) + return FindShpResult(curMixFile, curMixTheater, curFilename, toTheaterChar(preferred_theat), forcedPalette ? forcedPalette : unitOrIsoPalette); + // Phase 5: try with .tem, .sno etc endings with preferred theater + for (int t = 0; !(curSuffix = kSuffixesToTry[t]).IsEmpty(); ++t) + { + curFilename = image + curSuffix; + curFilename.MakeLower(); + curMixFile = FindFileInMix(curFilename, &curMixTheater); + if (curMixFile) + return FindShpResult(curMixFile, curMixTheater, curFilename, toTheaterChar(suffixToTheat(curSuffix)), forcedPalette ? forcedPalette : GetIsoPalette(suffixToTheat(curSuffix))); + } + // Phase 6: try with theater in 2nd char even if first char does not indicate support + curFilename = image + ".shp"; + for (int t = 0; curTheater = kTheatersToTry[t]; ++t) + { + curFilename.SetAt(1, curTheater); + curMixFile = FindFileInMix(curFilename, &curMixTheater); + if (curMixFile) + return FindShpResult(curMixFile, curMixTheater, curFilename, toTheaterChar(curTheater), forcedPalette ? forcedPalette : GetIsoPalette(curTheater)); + } + + return std::nullopt; +} + +int lepton_to_screen_y(int leptons) +{ + return leptons * f_y / 256; +} + +BOOL CLoading::LoadUnitGraphic(LPCTSTR lpUnittype) +{ + errstream << "Loading: " << lpUnittype << endl; + errstream.flush(); + + last_succeeded_operation=10; + + CString _rules_image; // the image used + CString filename; // filename of the image + char theat=cur_theat; // standard theater char is t (Temperat). a is snow. + + BOOL bAlwaysSetChar=FALSE; // second char is always theater, even if NewTheater not specified! + WORD wStep=1; // step is 1 for infantry, buildings, etc, and for shp vehicles it specifies the step rate between every direction + WORD wStartWalkFrame=0; // for examply cyborg reaper has another walk starting frame + int iTurretOffset=0; // used for centering y pos of turret (if existing) (for vehicles) + const BOOL bStructure=rules.sections["BuildingTypes"].FindValue(lpUnittype)>=0; // is this a structure? + const BOOL bVehicle = rules.sections["VehicleTypes"].FindValue(lpUnittype) >= 0; // is this a structure? + + BOOL bPowerUp=rules.sections[lpUnittype].values["PowersUpBuilding"]!=""; + + + CIsoView& v=*((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; + + _rules_image=lpUnittype; + if(rules.sections[lpUnittype].values.find("Image")!=rules.sections[lpUnittype].values.end()) + _rules_image=rules.sections[lpUnittype].values["Image"]; + + CString _art_image = _rules_image; + if(art.sections[_rules_image].values.find("Image")!=art.sections[_rules_image].values.end()) + { + if(!isTrue(g_data.sections["IgnoreArtImage"].values[_rules_image])) + _art_image=art.sections[_rules_image].values["Image"]; + } + + const CString& image = _art_image; + const auto& rulesSection = rules.sections[lpUnittype]; + const auto& artSection = art.sections[image]; + + if(!isTrue(art.sections[image].values["Voxel"])) // is it a shp graphic? + { + try + { + + auto shp = FindUnitShp(image, cur_theat, artSection); + if (!shp) + { + errstream << "Building SHP in theater " << cur_theat << " not found: " << image << endl; + errstream.flush(); + missingimages[lpUnittype] = TRUE; + return FALSE; + } + + filename = shp->filename; + HTSPALETTE hPalette = shp->palette; + const auto hShpMix = shp->mixfile; + theat = static_cast(shp->theat); + auto limited_to_theater = isTrue(artSection.GetValueByName("TerrainPalette")) ? shp->mixfile_theater : TheaterChar::None; + + + SHPHEADER head; + int superanim_1_zadjust=0; + int superanim_2_zadjust=0; + int superanim_3_zadjust=0; + int superanim_4_zadjust=0; + + CString turretanim_name; + CString turretanim_filename; + CString barrelanim_filename; + BYTE* bib=NULL; + SHPHEADER bib_h; + BYTE* activeanim=NULL; + SHPHEADER activeanim_h; + BYTE* idleanim=NULL; + SHPHEADER idleanim_h; + BYTE* activeanim2=NULL; + SHPHEADER activeanim2_h; + BYTE* activeanim3=NULL; + SHPHEADER activeanim3_h; + BYTE* superanim1=NULL; + SHPHEADER superanim1_h; + BYTE* superanim2=NULL; + SHPHEADER superanim2_h; + BYTE* superanim3=NULL; + SHPHEADER superanim3_h; + BYTE* superanim4=NULL; + SHPHEADER superanim4_h; + BYTE* specialanim1=NULL; + SHPHEADER specialanim1_h; + BYTE* specialanim2=NULL; + SHPHEADER specialanim2_h; + BYTE* specialanim3=NULL; + SHPHEADER specialanim3_h; + BYTE* specialanim4=NULL; + SHPHEADER specialanim4_h; + BYTE** lpT=NULL; + SHPHEADER* lpT_h=NULL; + std::vector turretColors[8]; + std::vector turretLighting[8]; + std::vector vxlBarrelColors[8]; + std::vector vxlBarrelLighting[8]; + SHPHEADER turrets_h[8]; + SHPIMAGEHEADER turretinfo[8]; + SHPHEADER barrels_h[8]; + SHPIMAGEHEADER barrelinfo[8]; + + + if(hShpMix>0) + { + + std::string shp_mixfile; + if (FSunPackLib::XCC_GetMixName(hShpMix, shp_mixfile)) + { + errstream << (LPCTSTR)filename << " found "; + errstream << " in " << shp_mixfile << endl; + errstream.flush(); + } + //hShpMix=20; + + + if(rules.sections[lpUnittype].values["Bib"]!="no") // seems to be ignored by TS, art.ini overwrites??? + { + LoadBuildingSubGraphic("BibShape", artSection, bAlwaysSetChar, theat, hShpMix, bib_h, bib); + } + + LoadBuildingSubGraphic("ActiveAnim", artSection, bAlwaysSetChar, theat, hShpMix, activeanim_h, activeanim); + LoadBuildingSubGraphic("IdleAnim", artSection, bAlwaysSetChar, theat, hShpMix, idleanim_h, idleanim); + LoadBuildingSubGraphic("ActiveAnim2", artSection, bAlwaysSetChar, theat, hShpMix, activeanim2_h, activeanim2); + LoadBuildingSubGraphic("ActiveAnim3", artSection, bAlwaysSetChar, theat, hShpMix, activeanim3_h, activeanim3); + if (!isTrue(g_data.sections["IgnoreSuperAnim1"].values[image])) + LoadBuildingSubGraphic("SuperAnim", artSection, bAlwaysSetChar, theat, hShpMix, superanim1_h, superanim1); + if (!isTrue(g_data.sections["IgnoreSuperAnim2"].values[image])) + LoadBuildingSubGraphic("SuperAnimTwo", artSection, bAlwaysSetChar, theat, hShpMix, superanim2_h, superanim2); + if (!isTrue(g_data.sections["IgnoreSuperAnim3"].values[image])) + LoadBuildingSubGraphic("SuperAnimThree", artSection, bAlwaysSetChar, theat, hShpMix, superanim3_h, superanim3); + if (!isTrue(g_data.sections["IgnoreSuperAnim4"].values[image])) + LoadBuildingSubGraphic("SuperAnimFour", artSection, bAlwaysSetChar, theat, hShpMix, superanim4_h, superanim4); + LoadBuildingSubGraphic("SpecialAnim", artSection, bAlwaysSetChar, theat, hShpMix, specialanim1_h, specialanim1); + LoadBuildingSubGraphic("SpecialAnimTwo", artSection, bAlwaysSetChar, theat, hShpMix, specialanim2_h, specialanim2); + LoadBuildingSubGraphic("SpecialAnimThree", artSection, bAlwaysSetChar, theat, hShpMix, specialanim3_h, specialanim3); + LoadBuildingSubGraphic("SpecialAnimFour", artSection, bAlwaysSetChar, theat, hShpMix, specialanim4_h, specialanim4); + + BOOL bVoxelTurret = FALSE; + BOOL bVoxelBarrel = FALSE; + + FSunPackLib::VoxelNormalClass vnc = FSunPackLib::VoxelNormalClass::Unknown; + + if (isTrue(rules.sections[image].values["Turret"])) + { + turretanim_name = rules.sections[image].values["TurretAnim"]; + auto vxl_turretanim_filename = turretanim_name.IsEmpty() ? image + "tur.vxl" : turretanim_name + ".vxl"; + auto vxl_barrelanim_filename = image + "barl.vxl"; + if (art.sections[turretanim_name].values.find("Image") != art.sections[turretanim_name].values.end()) + vxl_turretanim_filename = art.sections[turretanim_name].values["Image"] + ".vxl"; + + if (bStructure && turretanim_name.GetLength() > 0 && isFalse(rules.sections[image].values["TurretAnimIsVoxel"])) + { + turretanim_filename = turretanim_name + ".shp"; + if (art.sections[turretanim_name].values.find("Image") != art.sections[turretanim_name].values.end()) turretanim_filename = art.sections[turretanim_name].values["Image"] + ".shp"; + + if (isTrue(artSection.GetValueByName("NewTheater"))) + { + auto tmp = turretanim_filename; + tmp.SetAt(1, theat); + if (FSunPackLib::XCC_DoesFileExist(tmp, hShpMix)) + turretanim_filename = tmp; + } + + + FSunPackLib::SetCurrentSHP(turretanim_filename, hShpMix); + FSunPackLib::XCC_GetSHPHeader(&head); + + int iStartTurret = 0; + const WORD wAnimCount = 4; // anims between each "normal" direction, seems to be hardcoded + + int i; + + for (i = 0;i < 8;i++) + { + if (iStartTurret + i * wAnimCount < head.c_images) + { + FSunPackLib::XCC_GetSHPImageHeader(iStartTurret + i * wAnimCount, &turretinfo[i]); + FSunPackLib::XCC_GetSHPHeader(&turrets_h[i]); + FSunPackLib::LoadSHPImage(iStartTurret + i * wAnimCount, turretColors[i]); + turretLighting[i].clear(); + } + + } + } + else if ( + (bStructure && turretanim_name.GetLength() > 0 && isTrue(rules.sections[image].values["TurretAnimIsVoxel"])) + || (!bStructure && (FindFileInMix(vxl_turretanim_filename) || FindFileInMix(vxl_barrelanim_filename))) + ) + { + turretanim_filename = vxl_turretanim_filename; + barrelanim_filename = vxl_barrelanim_filename; + + HMIXFILE hVXL = FindFileInMix(vxl_turretanim_filename); + HMIXFILE hBarl = FindFileInMix(vxl_barrelanim_filename); + + if (artSection.values.find("TurretOffset") != art.sections[image].values.end()) + iTurretOffset = atoi(art.sections[image].values["TurretOffset"]); + Vec3f turretModelOffset(iTurretOffset / 6.0f, 0.0f, 0.0f); + + + if (hVXL) + { + bVoxelTurret = TRUE; + + if ( + FSunPackLib::SetCurrentVXL(turretanim_filename, hVXL) + ) + { + // we assume the voxel normal class is always the same for the combined voxels + FSunPackLib::GetVXLSectionInfo(0, vnc); + + int i; + + for (i = 0;i < 8;i++) + { + float r_x, r_y, r_z; + + + const int dir = bVehicle ? ((i + 1) % 8) : i; + r_x = 300; + r_y = 0; + r_z = 45 * dir + 90; + + // convert + const double pi = 3.141592654; + const Vec3f rotation(r_x / 180.0f * pi, r_y / 180.0f * pi, r_z / 180.0f * pi); + + + RECT r; + int center_x, center_y; + if (! + FSunPackLib::LoadVXLImage(*m_voxelNormalTables, lightDirection, rotation, turretModelOffset, turretColors[i], turretLighting[i], ¢er_x, ¢er_y, 0, 0, 0, 0, 0, &r) + ) + { + + } + else + { + turrets_h[i].cx = r.right - r.left; + turrets_h[i].cy = r.bottom - r.top; + + turretinfo[i].x = center_x; + turretinfo[i].y = center_y; + turretinfo[i].cx = r.right - r.left; + turretinfo[i].cy = r.bottom - r.top; + + } + + } + } + } + if (hBarl) + { + bVoxelBarrel = TRUE; + + if ( + FSunPackLib::SetCurrentVXL(barrelanim_filename, hBarl) + ) + { + // we assume the voxel normal class is always the same for the combined voxels + FSunPackLib::GetVXLSectionInfo(0, vnc); + + int i; + + for (i = 0;i < 8;i++) + { + float r_x, r_y, r_z; + + + const int dir = bVehicle ? ((i + 1) % 8) : i; + r_x = 300; + r_y = 0; + r_z = 45 * dir + 90; + + // convert + const double pi = 3.141592654; + const Vec3f rotation(r_x / 180.0f * pi, r_y / 180.0f * pi, r_z / 180.0f * pi); + + + RECT r; + int center_x, center_y; + if (! + FSunPackLib::LoadVXLImage(*m_voxelNormalTables, lightDirection, rotation, turretModelOffset, vxlBarrelColors[i], vxlBarrelLighting[i], ¢er_x, ¢er_y, atoi(rules.sections[image].values["TurretAnimZAdjust"]), 0, 0, 0, 0, &r) + ) + { + + } + else + { + barrels_h[i].cx = r.right - r.left; + barrels_h[i].cy = r.bottom - r.top; + + barrelinfo[i].x = center_x; + barrelinfo[i].y = center_y; + barrelinfo[i].cx = r.right - r.left; + barrelinfo[i].cy = r.bottom - r.top; + + } + + } + } + } + } + } + + + if(art.sections[image].values.find("WalkFrames")!=art.sections[image].values.end()) + wStep=atoi(art.sections[image].values["WalkFrames"]); + if(art.sections[image].values.find("StartWalkFrame")!=art.sections[image].values.end()) + wStartWalkFrame=atoi(art.sections[image].values["StartWalkFrame"]); + + if(art.sections[image].values["Palette"]=="lib") + hPalette=m_hPalLib; + + BOOL bSuccess=FSunPackLib::SetCurrentSHP(filename, hShpMix); + if( + !bSuccess + ) + { + filename=image+".sno"; + if(cur_theat=='T' || cur_theat=='U' /* || cur_theat=='N' ? */) hPalette=m_hPalIsoTemp; + HMIXFILE hShpMix=FindFileInMix(filename); + bSuccess=FSunPackLib::SetCurrentSHP(filename, hShpMix); + + if(!bSuccess) + { + missingimages[lpUnittype]=TRUE; + } + } + + if(bSuccess) + { + + FSunPackLib::XCC_GetSHPHeader(&head); + int i; + int maxPics=head.c_images; + if(maxPics>8) maxPics=8; // we only need 8 pictures for every direction! + if(bStructure && !bPowerUp && !isTrue(rules.sections[image].values["Turret"])) maxPics=1; + if(bVoxelTurret) maxPics=8; + + + + if(!bStructure && rules.sections[image].values["Turret"]=="yes") + { + int iStartTurret=wStartWalkFrame+8*wStep; + const WORD wAnimCount=4; // anims between each "normal" direction, seems to be hardcoded + + int i; + + for(i=0;i<8;i++) + { + if(iStartTurret+i*wAnimCount> lighting(maxPics); + std::vector shp_image_headers(maxPics); + + if(bVoxelTurret && bStructure) + { + for(i=0;iBlt(NULL, bib, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, bib, bib_h.cx, bib_h.cy); + + imghead.cx=head.cx-imghead.x; // update size of main graphic + imghead.cy=head.cy-imghead.y; + + } + + if(activeanim!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + //lpT[i]->Blt(NULL, activeanim, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, activeanim, activeanim_h.cx, activeanim_h.cy); + + + } + + if(idleanim!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + //lpT[i]->Blt(NULL, idleanim, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, idleanim, idleanim_h.cx, idleanim_h.cy); + + + } + + if(activeanim2!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + //lpT[i]->Blt(NULL, activeanim2, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, activeanim2, activeanim2_h.cx, activeanim2_h.cy); + + } + + if(activeanim3!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + //lpT[i]->Blt(NULL, activeanim3, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, activeanim3, activeanim3_h.cx, activeanim3_h.cy); + + } + + if(superanim1!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + //lpT[i]->Blt(NULL, superanim1, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + Blit_Pal(lpT[i], 0, superanim_1_zadjust, head.cx, head.cy, superanim1, superanim1_h.cx, superanim1_h.cy); + + + } + + if(superanim2!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + //lpT[i]->Blt(NULL, superanim2, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + Blit_Pal(lpT[i], 0, superanim_2_zadjust, head.cx, head.cy, superanim2, superanim2_h.cx, superanim2_h.cy); + + + } + + if(superanim3!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + //lpT[i]->Blt(NULL, superanim3, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + Blit_Pal(lpT[i], 0, superanim_3_zadjust, head.cx, head.cy, superanim3, superanim3_h.cx, superanim3_h.cy); + + + } + + if(superanim4!=NULL && strcmp(lpUnittype, "YAGNTC")!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + //lpT[i]->Blt(NULL, superanim4, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + Blit_Pal(lpT[i], 0, superanim_4_zadjust, head.cx, head.cy, superanim4, superanim4_h.cx, superanim4_h.cy); + + + } + + if(specialanim1!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + //lpT[i]->Blt(NULL, specialanim1, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, specialanim1, specialanim1_h.cx, specialanim1_h.cy); + + + } + + if(specialanim2!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + //lpT[i]->Blt(NULL, specialanim2, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, specialanim2, specialanim2_h.cx, specialanim2_h.cy); + + } + + if(specialanim3!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + //lpT[i]->Blt(NULL, specialanim3, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, specialanim3, specialanim3_h.cx, specialanim3_h.cy); + + + } + + if(specialanim4!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + //lpT[i]->Blt(NULL, specialanim4, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + Blit_Pal(lpT[i], 0, 0, head.cx, head.cy, specialanim4, specialanim4_h.cx, specialanim4_h.cy); + + } + + if (!vxlBarrelLighting[i].empty() || !turretLighting[i].empty()) + lighting[i].resize(head.cx * head.cy, 46); // value needs to lead to 1.0 lighting + + // barrels hidden behind turret: + if(!vxlBarrelColors[i].empty() && (i == 1 || i == 0 || i == 7)) + { + DDSURFACEDESC2 ddsd; + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; + ddsd.dwWidth = barrels_h[i].cx; + ddsd.dwHeight = barrels_h[i].cy; + + int XMover, YMover; + char c[50]; + itoa(i, c, 10); +#ifdef RA2_MODE + XMover = atoi(g_data.sections["BuildingVoxelBarrelsRA2"].values[(CString)lpUnittype + "X"]); + YMover = atoi(g_data.sections["BuildingVoxelBarrelsRA2"].values[(CString)lpUnittype + "Y"]); + XMover += atoi(g_data.sections["BuildingVoxelBarrelsRA2"].values[(CString)lpUnittype + (CString)"X" + c]); + YMover += atoi(g_data.sections["BuildingVoxelBarrelsRA2"].values[(CString)lpUnittype + (CString)"Y" + c]); +#else + XMover = atoi(g_data.sections["BuildingVoxelBarrels"].values[(CString)lpUnittype + "X"]); + YMover = atoi(g_data.sections["BuildingVoxelBarrels"].values[(CString)lpUnittype + "Y"]); +#endif + + RECT srcRect, destRect; + + int mx = head.cx / 2 + atoi(rules.sections[image].values["TurretAnimX"]) - barrelinfo[i].x; + int my = head.cy / 2 + atoi(rules.sections[image].values["TurretAnimY"]) - barrelinfo[i].y; + + srcRect.top = 0; + srcRect.left = 0; + srcRect.right = ddsd.dwWidth; + srcRect.bottom = ddsd.dwHeight; + destRect.top = YMover + my; + destRect.left = XMover + mx; + destRect.right = destRect.left + ddsd.dwWidth; + destRect.bottom = destRect.top + ddsd.dwHeight; + + + errstream << "vxl barrel: " << i << " size: " << ddsd.dwWidth << " " << ddsd.dwHeight << " at " << destRect.left << " " << destRect.top << endl; + errstream.flush(); + Blit_PalD(lpT[i], destRect, vxlBarrelColors[i].data(), srcRect, ddsd.dwWidth, head.cx, ddsd.dwHeight, head.cy); + Blit_PalD(lighting[i].data(), destRect, vxlBarrelLighting[i].data(), srcRect, ddsd.dwWidth, head.cx, ddsd.dwHeight, head.cy, vxlBarrelColors[i].data()); + + } + + + if(!turretColors[i].empty()) + { + DDSURFACEDESC2 ddsd; + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize=sizeof(DDSURFACEDESC2); + ddsd.dwFlags=DDSD_WIDTH | DDSD_HEIGHT; + //turrets[i]->GetSurfaceDesc(&ddsd); + // replace DX code: + ddsd.dwWidth=turrets_h[i].cx; + ddsd.dwHeight=turrets_h[i].cy; + + int XMover, YMover; + char c[50]; + itoa(i, c, 10); +#ifdef RA2_MODE + XMover = atoi(g_data.sections["BuildingVoxelTurretsRA2"].values[(CString)lpUnittype + "X"]); + YMover = atoi(g_data.sections["BuildingVoxelTurretsRA2"].values[(CString)lpUnittype + "Y"]); + XMover += atoi(g_data.sections["BuildingVoxelTurretsRA2"].values[(CString)lpUnittype + (CString)"X" + c]); + YMover += atoi(g_data.sections["BuildingVoxelTurretsRA2"].values[(CString)lpUnittype + (CString)"Y" + c]); +#else + XMover = atoi(g_data.sections["BuildingVoxelTurrets"].values[(CString)lpUnittype + "X"]); + YMover = atoi(g_data.sections["BuildingVoxelTurrets"].values[(CString)lpUnittype + "Y"]); +#endif + + RECT srcRect, destRect; + + if (bVoxelTurret) + { + int mx = head.cx / 2 + atoi(rules.sections[image].values["TurretAnimX"]) - turretinfo[i].x; + int my = head.cy / 2 + atoi(rules.sections[image].values["TurretAnimY"]) - turretinfo[i].y; + + srcRect.top=0; + srcRect.left=0; + srcRect.right=ddsd.dwWidth; + srcRect.bottom=ddsd.dwHeight; + destRect.top=YMover+my; + destRect.left=XMover+mx; + destRect.right=destRect.left+ddsd.dwWidth;; + destRect.bottom=destRect.top+ddsd.dwHeight; + + } + else // !bVoxelTurret + { + + int mx = atoi(rules.sections[image].values["TurretAnimX"]); + int my = atoi(rules.sections[image].values["TurretAnimY"]);//+atoi(rules.sections[image].values["barrelAnimZAdjust"]); + + + + srcRect.top = 0; + srcRect.left = 0; + srcRect.right = turrets_h[i].cx; + srcRect.bottom = turrets_h[i].cy; + destRect.top = YMover + my; + destRect.left = XMover + mx; + destRect.right = destRect.left + srcRect.right; + destRect.bottom = destRect.top + srcRect.bottom; + } + + errstream << "vxl turret: " << i << " size: " << ddsd.dwWidth << " " << ddsd.dwHeight << " at " << destRect.left << " " << destRect.top << endl; + errstream.flush(); + Blit_PalD(lpT[i], destRect, turretColors[i].data(), srcRect, ddsd.dwWidth, head.cx, ddsd.dwHeight, head.cy); + Blit_PalD(lighting[i].data(), destRect, turretLighting[i].data(), srcRect, ddsd.dwWidth, head.cx, ddsd.dwHeight, head.cy, turretColors[i].data()); + + } + + // barrels in front of turret + if(!vxlBarrelColors[i].empty() && i!=1 && i!=0 && i!=7) + { + DDSURFACEDESC2 ddsd; + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; + ddsd.dwWidth = barrels_h[i].cx; + ddsd.dwHeight = barrels_h[i].cy; + + int XMover, YMover; + char c[50]; + itoa(i, c, 10); +#ifdef RA2_MODE + XMover = atoi(g_data.sections["BuildingVoxelBarrelsRA2"].values[(CString)lpUnittype + "X"]); + YMover = atoi(g_data.sections["BuildingVoxelBarrelsRA2"].values[(CString)lpUnittype + "Y"]); + XMover += atoi(g_data.sections["BuildingVoxelBarrelsRA2"].values[(CString)lpUnittype + (CString)"X" + c]); + YMover += atoi(g_data.sections["BuildingVoxelBarrelsRA2"].values[(CString)lpUnittype + (CString)"Y" + c]); +#else + XMover = atoi(g_data.sections["BuildingVoxelBarrels"].values[(CString)lpUnittype + "X"]); + YMover = atoi(g_data.sections["BuildingVoxelBarrels"].values[(CString)lpUnittype + "Y"]); +#endif + + RECT srcRect, destRect; + + int mx = head.cx / 2 + atoi(rules.sections[image].values["TurretAnimX"]) - barrelinfo[i].x; + int my = head.cy / 2 + atoi(rules.sections[image].values["TurretAnimY"]) - barrelinfo[i].y; + + srcRect.top = 0; + srcRect.left = 0; + srcRect.right = ddsd.dwWidth; + srcRect.bottom = ddsd.dwHeight; + destRect.top = YMover + my; + destRect.left = XMover + mx; + destRect.right = destRect.left + ddsd.dwWidth; + destRect.bottom = destRect.top + ddsd.dwHeight; + + + errstream << "vxl barrel: " << i << " size: " << ddsd.dwWidth << " " << ddsd.dwHeight << " at " << destRect.left << " " << destRect.top << endl; + errstream.flush(); + Blit_PalD(lpT[i], destRect, vxlBarrelColors[i].data(), srcRect, ddsd.dwWidth, head.cx, ddsd.dwHeight, head.cy); + Blit_PalD(lighting[i].data(), destRect, vxlBarrelLighting[i].data(), srcRect, ddsd.dwWidth, head.cx, ddsd.dwHeight, head.cy, vxlBarrelColors[i].data()); + + + } + + if(!bPowerUp && i!=0 && (imghead.unknown==0 && !isTrue(g_data.sections["Debug"].values["IgnoreSHPImageHeadUnused"])) && bStructure) + { + if(lpT[i]) delete[] lpT[i]; + lpT[i]=NULL; + } + else + { + char ic[50]; + itoa(i, ic, 10); + + PICDATA p; + p.pic=lpT[i]; + if (std::find_if(lighting[i].begin(), lighting[i].end(), [](const BYTE b) { return b != 255; }) != lighting[i].end()) + p.lighting = std::shared_ptr>(new std::vector(std::move(lighting[i]))); + else + lighting[i].clear(); + p.vborder=new(VBORDER[head.cy]); + int k; + for(k=0;k finished as " << (LPCSTR)(image+ic) << endl; + //errstream.flush(); + } + + + } + + delete[] lpT; + + + if(bib) delete[] bib; + if(activeanim) delete[] activeanim; + if(idleanim) delete[] idleanim; + if(activeanim2) delete[] activeanim2; + if(activeanim3) delete[] activeanim3; + if(superanim1) delete[] superanim1; + if(superanim2) delete[] superanim2; + if(superanim3) delete[] superanim3; + if(superanim4) delete[] superanim4; + if(specialanim1) delete[] specialanim1; + if(specialanim2) delete[] specialanim2; + if(specialanim3) delete[] specialanim3; + if(specialanim4) delete[] specialanim4; + + //for(i=0;i<8;i++) + // if(turrets[i]) delete[] turrets[i]; + + } + + //errstream << " --> Finished" << endl; + //errstream.flush(); + } + + else + { + errstream << "File in theater " << cur_theat << " not found: " << (LPCTSTR)filename << endl; + errstream.flush(); + + missingimages[lpUnittype]=TRUE; + } + + } + catch(...) + { + errstream << " exception " << endl; + errstream.flush(); + } + + + } + else + { + filename=image+".vxl"; + + HMIXFILE hMix=FindFileInMix(filename); + if(hMix==FALSE) + { + missingimages[lpUnittype]=TRUE; + return FALSE; + } + + int XMover, YMover; +#ifdef RA2_MODE + XMover=atoi(g_data.sections["VehicleVoxelTurretsRA2"].values[(CString)lpUnittype+"X"]); + YMover=atoi(g_data.sections["VehicleVoxelTurretsRA2"].values[(CString)lpUnittype+"Y"]); +#else + XMover=atoi(g_data.sections["VehicleVoxelTurrets"].values[(CString)lpUnittype+"X"]); + YMover=atoi(g_data.sections["VehicleVoxelTurrets"].values[(CString)lpUnittype+"Y"]); +#endif + + if (artSection.values.find("TurretOffset") != art.sections[image].values.end()) + iTurretOffset = atoi(art.sections[image].values["TurretOffset"]); + + int i; + + for(i=0;i<8;i++) + { + float r_x,r_y,r_z; + + + r_x = 300; + r_y=0; + r_z=45*i+90; + + //r_x = 0; + //r_y = 0; + //r_z = 0; + + // convert + const double pi = 3.141592654; + Vec3f rotation(r_x / 180.0f * pi, r_y / 180.0f * pi, r_z / 180.0f * pi); + Vec3f turretModelOffset(iTurretOffset / 6.0f, 0.0f, 0.0f); + + + std::vector colors; + std::shared_ptr> pLighting(new std::vector); + auto& lighting = *pLighting; + std::vector turretColors; + std::vector turretNormals; + std::vector barrelColors; + std::vector barrelNormals; + RECT lprT; + RECT lprB; + int turret_x,turret_y,turret_x_zmax,turret_y_zmax,barrel_x,barrel_y; + + if(isTrue(rules.sections[lpUnittype].values["Turret"])) + { + if(FSunPackLib::SetCurrentVXL(image+"tur.vxl", hMix)) + { + FSunPackLib::LoadVXLImage(*m_voxelNormalTables, lightDirection, rotation, turretModelOffset, turretColors, turretNormals, &turret_x,&turret_y, 0, &turret_x_zmax, &turret_y_zmax,-1,-1,&lprT); + } + if(FSunPackLib::SetCurrentVXL(image+"barl.vxl", hMix)) + { + FSunPackLib::LoadVXLImage(*m_voxelNormalTables, lightDirection, rotation, turretModelOffset, barrelColors, barrelNormals, &barrel_x,&barrel_y, 0, NULL, NULL, 0, 0, &lprB); + } + } + + + if(!FSunPackLib::SetCurrentVXL(filename, hMix)) + { + return FALSE; + } + + + + int xcenter,ycenter,xcenter_zmax,ycenter_zmax; + + RECT r; + + if(! + FSunPackLib::LoadVXLImage(*m_voxelNormalTables, lightDirection, rotation, Vec3f(), colors, lighting, &xcenter, &ycenter,0, &xcenter_zmax, &ycenter_zmax,-1,-1,&r) + ) + { + return FALSE; + } + + FSunPackLib::VoxelNormalClass vnc = FSunPackLib::VoxelNormalClass::Unknown; + FSunPackLib::GetVXLSectionInfo(0, vnc); // we assume the normal class for all voxels sections and turrets or barrels is the same + + DDSURFACEDESC2 ddsd; + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize=sizeof(DDSURFACEDESC2); + ddsd.dwFlags=DDSD_WIDTH | DDSD_HEIGHT; + ddsd.dwWidth=r.right-r.left; + ddsd.dwHeight=r.bottom-r.top; + + //lpT->GetSurfaceDesc(&ddsd); + + // turret + if(turretColors.size()) + { + DDSURFACEDESC2 ddsdT; + memset(&ddsdT, 0, sizeof(DDSURFACEDESC2)); + ddsdT.dwSize=sizeof(DDSURFACEDESC2); + ddsdT.dwFlags=DDSD_WIDTH | DDSD_HEIGHT; + ddsdT.dwWidth=lprT.right-lprT.left; + ddsdT.dwHeight=lprT.bottom-lprT.top; + //lpTurret->GetSurfaceDesc(&ddsdT); + + DDBLTFX fx; + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + + RECT srcRect, destRect; + srcRect.left=0; + srcRect.right=ddsdT.dwWidth; + destRect.left=xcenter - turret_x + XMover; + destRect.right=destRect.left+ddsdT.dwWidth; + srcRect.top=0; + srcRect.bottom=ddsdT.dwHeight; + destRect.top=ycenter - turret_y + YMover; + destRect.bottom=destRect.top+ddsdT.dwHeight; + + errstream << destRect.left << " " << destRect.top << endl; + errstream.flush(); + + Blit_PalD(colors.data(), destRect, turretColors.data(), srcRect, ddsdT.dwWidth, ddsd.dwWidth, ddsdT.dwHeight, ddsd.dwHeight); + Blit_PalD(lighting.data(), destRect, turretNormals.data(), srcRect, ddsdT.dwWidth, ddsd.dwWidth, ddsdT.dwHeight, ddsd.dwHeight, turretColors.data()); + //AssertNormals(turretColors, turretNormals); + + } + + // barrel + if(barrelColors.size()) + { + DDSURFACEDESC2 ddsdB; + memset(&ddsdB, 0, sizeof(DDSURFACEDESC2)); + ddsdB.dwSize=sizeof(DDSURFACEDESC2); + ddsdB.dwFlags=DDSD_WIDTH | DDSD_HEIGHT; + ddsdB.dwWidth=lprB.right-lprB.left; + ddsdB.dwHeight=lprB.bottom-lprB.top; + //lpBarrel->GetSurfaceDesc(&ddsdB); + + DDSURFACEDESC2 ddsdT; + memset(&ddsdT, 0, sizeof(DDSURFACEDESC2)); + ddsdT.dwSize=sizeof(DDSURFACEDESC2); + ddsdT.dwFlags=DDSD_WIDTH | DDSD_HEIGHT; + + if(turretColors.size()) + { + ddsdT.dwWidth=lprT.right-lprT.left; + ddsdT.dwHeight=lprT.bottom-lprT.top; + //lpTurret->GetSurfaceDesc(&ddsdT); + } + + + DDBLTFX fx; + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + RECT srcRect, destRect; + srcRect.left=0; + srcRect.right=ddsdB.dwWidth; + destRect.left=xcenter-barrel_x+XMover; + destRect.right=destRect.left+ddsdB.dwWidth; + srcRect.top=0; + srcRect.bottom=ddsdB.dwHeight; + destRect.top=ycenter-barrel_y+YMover; + destRect.bottom=destRect.top+ddsdB.dwHeight; + + Blit_PalD(colors.data(), destRect, barrelColors.data(), srcRect, ddsdB.dwWidth, ddsd.dwWidth, ddsdB.dwHeight, ddsd.dwHeight); + Blit_PalD(lighting.data(), destRect, barrelNormals.data(), srcRect, ddsdB.dwWidth, ddsd.dwWidth, ddsdB.dwHeight, ddsd.dwHeight, barrelColors.data()); + //AssertNormals(vxlBarrelColors, barrelNormals); + + } + + // all VXL, so every non-transparent area should have a normal + //AssertNormals(colors, lighting); + + char ic[50]; + itoa(7-i, ic, 10); + + errstream << ddsd.dwWidth << " " << ddsd.dwHeight << "\n"; + PICDATA p; + p.pic = new(BYTE[colors.size()]); + memcpy(p.pic, colors.data(), colors.size()); + p.lighting = pLighting; + p.normalClass = vnc; + + p.vborder=new(VBORDER[ddsd.dwHeight]); + int k; + for(k=0;k 0) + { + auto res = FindUnitShp(subname, theat, artSection); + /*CString subfilename = subname + ".shp"; + + if (isTrue(artSection.GetValueByName("NewTheater")) || bAlwaysSetChar || subfilename.GetAt(0) == 'G' || subfilename.GetAt(0) == 'N' || subfilename.GetAt(0) == 'Y' || subfilename.GetAt(0) == 'C') + { + auto subfilename_theat = subfilename; + subfilename_theat.SetAt(1, theat); + if (FSunPackLib::XCC_DoesFileExist(subfilename_theat, hShpMix)) + subfilename = subfilename_theat; + }*/ + + if (res && FSunPackLib::XCC_DoesFileExist(res->filename, res->mixfile)) + { + FSunPackLib::SetCurrentSHP(res->filename, res->mixfile); + FSunPackLib::XCC_GetSHPHeader(&shp_h); + FSunPackLib::LoadSHPImage(0, 1, &shp); + + } + } +} +#else // surfaces +BOOL CLoading::LoadUnitGraphic(LPCTSTR lpUnittype) +{ + last_succeeded_operation=10; + + CString _rules_image; // the image used + CString filename; // filename of the image + char theat=cur_theat; // standard theater char is t (Temperat). a is snow. + + BOOL bAlwaysSetChar; // second char is always theater, even if NewTheater not specified! + WORD wStep=1; // step is 1 for infantry, buildings, etc, and for shp vehicles it specifies the step rate between every direction + WORD wStartWalkFrame=0; // for examply cyborg reaper has another walk starting frame + int iTurretOffset=0; // used for centering y pos of turret (if existing) + BOOL bStructure=rules.sections["BuildingTypes"].FindValue(lpUnittype)>=0; // is this a structure? + + BOOL bPowerUp=rules.sections[lpUnittype].values["PowersUpBuilding"]!=""; + + HTSPALETTE hPalette; + if(theat=='T') hPalette=m_hPalIsoTemp; + if(theat=='A') hPalette=m_hPalIsoSnow; + if(theat=='U') hPalette=m_hPalIsoUrb; + + CIsoView& v=*((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; + + _rules_image = lpUnittype; + if (rules.sections[lpUnittype].values.find("Image") != rules.sections[lpUnittype].values.end()) + _rules_image = rules.sections[lpUnittype].values["Image"]; + + CString _art_image = _rules_image; + if (art.sections[_rules_image].values.find("Image") != art.sections[_rules_image].values.end()) + { + if (!isTrue(g_data.sections["IgnoreArtImage"].values[_rules_image])) + _art_image = art.sections[_rules_image].values["Image"]; + } + + const CString& image = _art_image; + const auto& rulesSection = rules.sections[lpUnittype]; + const auto& artSection = art.sections[image]; + + if(!isTrue(art.sections[image].values["Voxel"])) // is it a shp graphic? + { + try + { + + filename=image+".shp"; + + + BYTE bTerrain=0; + + + + BOOL isNewTerrain=FALSE; + if(isTrue(art.sections[image].values["NewTheater"]))//&& isTrue(artSection.GetValueByName("TerrainPalette")))//(filename.GetAt(0)=='G' || filename.GetAt(0)=='N' || filename.GetAt(0)=='C') && filename.GetAt(1)=='A') + { + hPalette=m_hPalUnitTemp; + if(theat=='A') hPalette=m_hPalUnitSnow; + if(theat=='U') hPalette=m_hPalUnitUrb; + filename.SetAt(1, theat); + isNewTerrain=TRUE; + } + + + HMIXFILE hShpMix=FindFileInMix(filename, &bTerrain); + + BYTE bIgnoreTerrain=TRUE; + + if(hShpMix==NULL && isNewTerrain) + { + filename.SetAt(1, 'G'); + hShpMix=FindFileInMix(filename, &bTerrain); + if(hShpMix) theat='G'; + + } + + + + if(hShpMix==NULL && isNewTerrain) + { + filename.SetAt(1, 'A'); + hShpMix=FindFileInMix(filename, &bTerrain); + if(hShpMix) theat='A'; + } + + if(hShpMix==NULL && isNewTerrain) + { + filename.SetAt(1, 'T'); + hShpMix=FindFileInMix(filename, &bTerrain); + if(hShpMix){ + theat='T'; + hPalette=m_hIsoTemp; + } + } + + + if(isTrue(artSection.GetValueByName("TerrainPalette"))) + { + bIgnoreTerrain=FALSE; + + if(cur_theat=='T') + hPalette=m_hPalIsoTemp; + else if(cur_theat=='A') + hPalette=m_hPalIsoSnow; + else if (cur_theat=='U') + hPalette=m_hPalIsoUrb; + + + + } + + + + if(hShpMix==0) + { + filename=image; + filename+=".shp"; + hShpMix=FindFileInMix(filename, &bTerrain); + + + + if(hShpMix==NULL) + { + filename=image; + if(theat=='T') filename+=".tem"; + if(theat=='A') filename+=".sno"; + if(theat=='U') filename+=".urb"; + filename.MakeLower(); + hShpMix=FindFileInMix(filename, &bTerrain); + + if(hShpMix==NULL) + { + filename=image; + filename+=".tem"; + hShpMix=FindFileInMix(filename, &bTerrain); + if(hShpMix) + { + hPalette=m_hPalIsoTemp; + } + } + + if(hShpMix!=NULL) + { + + + + } + else + { + filename=image+".shp"; + + filename.SetAt(1, 'A'); + + hShpMix=FindFileInMix(filename); + + if(hShpMix!=NULL) + { + bAlwaysSetChar=TRUE; + } + else + { + filename.SetAt(1, 'A'); + hShpMix=FindFileInMix(filename); + + if(hShpMix!=NULL) + { + theat='A'; + bAlwaysSetChar=TRUE; + } + else + { + filename.SetAt(1, 'U'); + hShpMix=FindFileInMix(filename); + if(hShpMix) theat='U'; + else + { + filename.SetAt(1, 'T'); + hShpMix=FindFileInMix(filename); + if(hShpMix) theat='T'; + } + } + } + } + } + else + { + theat='T'; + } + + } + else + { + + // now we need to find out the palette + + if(isTrue(artSection.GetValueByName("TerrainPalette"))) // it´s a file in isotemp.mix/isosno.mix + { + + } + else // it´s a file in temperat.mix/snow.mix + { + if(cur_theat=='T') hPalette=m_hPalUnitTemp; + if(cur_theat=='A') hPalette=m_hPalUnitSnow; + if(cur_theat=='U') hPalette=m_hPalUnitUrb; + } + + } + + + + if(filename=="tibtre01.tem" || filename=="tibtre02.tem" || filename=="tibtre03.tem" || filename=="veinhole.tem") + { + hPalette=m_hPalUnitTemp; + } + + + SHPHEADER head; + CString bibname; + CString bibfilename; + CString activeanim_name; + CString activeanim_filename; + CString idleanim_name; + CString idleanim_filename; + CString activeanim2_name; + CString activeanim2_filename; + CString activeanim3_name; + CString activeanim3_filename; + CString superanim1_name,superanim1_filename; + CString superanim2_name,superanim2_filename; + CString superanim3_name,superanim3_filename; + CString superanim4_name,superanim4_filename; + CString specialanim1_name,specialanim1_filename; + CString specialanim2_name,specialanim2_filename; + CString specialanim3_name,specialanim3_filename; + CString specialanim4_name,specialanim4_filename; + + CString turretanim_name; + CString turretanim_filename; + LPDIRECTDRAWSURFACE4 bib=NULL; + LPDIRECTDRAWSURFACE4 activeanim=NULL; + LPDIRECTDRAWSURFACE4 idleanim=NULL; + LPDIRECTDRAWSURFACE4 activeanim2=NULL; + LPDIRECTDRAWSURFACE4 activeanim3=NULL; + LPDIRECTDRAWSURFACE4 superanim1=NULL; + LPDIRECTDRAWSURFACE4 superanim2=NULL; + LPDIRECTDRAWSURFACE4 superanim3=NULL; + LPDIRECTDRAWSURFACE4 superanim4=NULL; + LPDIRECTDRAWSURFACE4 specialanim1=NULL; + LPDIRECTDRAWSURFACE4 specialanim2=NULL; + LPDIRECTDRAWSURFACE4 specialanim3=NULL; + LPDIRECTDRAWSURFACE4 specialanim4=NULL; + LPDIRECTDRAWSURFACE4* lpT=NULL; + LPDIRECTDRAWSURFACE4 turrets[8] = { 0 }; + SHPIMAGEHEADER turretinfo[8]; + + if(hShpMix>0) + { + + + //errstream << (LPCTSTR)filename << " found " ; + //errstream.flush(); + + + if(rules.sections[lpUnittype].values["Bib"]!="no") // seems to be ignored by TS, art.ini overwrites??? + { + + bibname=art.sections[image].values["BibShape"]; + if(bibname.GetLength()>0) + { + bibfilename=bibname+".shp"; + + if(isTrue(art.sections[image].values["NewTheater"])) + bibfilename.SetAt(1, theat); + + if(bAlwaysSetChar) bibfilename.SetAt(1, theat); + + if(FSunPackLib::XCC_DoesFileExist(bibfilename, hShpMix)) + { + FSunPackLib::SetCurrentSHP(bibfilename, hShpMix); + FSunPackLib::LoadSHPImageInSurface(v.dd, hPalette, 0, 1, &bib); + + } + } + } + + activeanim_name=art.sections[image].values["ActiveAnim"]; + if(activeanim_name.GetLength()>0) + { + activeanim_filename=activeanim_name+".shp"; + + if(isTrue(art.sections[image].values["NewTheater"])) + activeanim_filename.SetAt(1, theat); + + if(bAlwaysSetChar) activeanim_filename.SetAt(1, theat); + + if(FSunPackLib::XCC_DoesFileExist(activeanim_filename, hShpMix)) + { + FSunPackLib::SetCurrentSHP(activeanim_filename, hShpMix); + + FSunPackLib::LoadSHPImageInSurface(v.dd, hPalette, 0, 1, &activeanim); + + + } + } + + idleanim_name=art.sections[image].values["IdleAnim"]; + if(idleanim_name.GetLength()>0) + { + idleanim_filename=idleanim_name+".shp"; + + if(isTrue(art.sections[image].values["NewTheater"])) + idleanim_filename.SetAt(1, theat); + + if(bAlwaysSetChar) idleanim_filename.SetAt(1, theat); + + if(FSunPackLib::XCC_DoesFileExist(idleanim_filename, hShpMix)) + { + FSunPackLib::SetCurrentSHP(idleanim_filename, hShpMix); + + FSunPackLib::LoadSHPImageInSurface(v.dd, hPalette, 0, 1, &idleanim); + } + } + + + activeanim2_name=art.sections[image].values["ActiveAnimTwo"]; + if(activeanim2_name.GetLength()>0) + { + activeanim2_filename=activeanim2_name+".shp"; + + if(isTrue(art.sections[image].values["NewTheater"])) + activeanim2_filename.SetAt(1, theat); + + if(bAlwaysSetChar) activeanim2_filename.SetAt(1, theat); + + if(FSunPackLib::XCC_DoesFileExist(activeanim2_filename, hShpMix)) + { + FSunPackLib::SetCurrentSHP(activeanim2_filename, hShpMix); + + FSunPackLib::LoadSHPImageInSurface(v.dd, hPalette, 0, 1, &activeanim2); + + } + } + + activeanim3_name=art.sections[image].values["ActiveAnimThree"]; + if(activeanim3_name.GetLength()>0) + { + activeanim3_filename=activeanim3_name+".shp"; + + if(isTrue(art.sections[image].values["NewTheater"])) + activeanim3_filename.SetAt(1, theat); + + if(bAlwaysSetChar) activeanim3_filename.SetAt(1, theat); + + if(FSunPackLib::XCC_DoesFileExist(activeanim3_filename, hShpMix)) + { + FSunPackLib::SetCurrentSHP(activeanim3_filename, hShpMix); + + FSunPackLib::LoadSHPImageInSurface(v.dd, hPalette, 0, 1, &activeanim3); + + } + } + + superanim1_name=art.sections[image].values["SuperAnim"]; + if(superanim1_name.GetLength()>0) + { + superanim1_filename=superanim1_name+".shp"; + + if(isTrue(art.sections[image].values["NewTheater"])) + superanim1_filename.SetAt(1, theat); + + if(bAlwaysSetChar) superanim1_filename.SetAt(1, theat); + + if(FSunPackLib::XCC_DoesFileExist(superanim1_filename, hShpMix)) + { + FSunPackLib::SetCurrentSHP(superanim1_filename, hShpMix); + FSunPackLib::LoadSHPImageInSurface(v.dd, hPalette, 0, 1, &superanim1); + } + } + + superanim2_name=art.sections[image].values["SuperAnimTwo"]; + if(superanim2_name.GetLength()>0) + { + superanim2_filename=superanim2_name+".shp"; + + if(isTrue(art.sections[image].values["NewTheater"])) + superanim2_filename.SetAt(1, theat); + + if(bAlwaysSetChar) superanim2_filename.SetAt(1, theat); + + if(FSunPackLib::XCC_DoesFileExist(superanim2_filename, hShpMix)) + { + FSunPackLib::SetCurrentSHP(superanim2_filename, hShpMix); + FSunPackLib::LoadSHPImageInSurface(v.dd, hPalette, 0, 1, &superanim2); + } + } + + superanim3_name=art.sections[image].values["SuperAnimThree"]; + if(superanim3_name.GetLength()>0) + { + superanim3_filename=superanim3_name+".shp"; + + if(isTrue(art.sections[image].values["NewTheater"])) + superanim3_filename.SetAt(1, theat); + + if(bAlwaysSetChar) superanim3_filename.SetAt(1, theat); + + if(FSunPackLib::XCC_DoesFileExist(superanim3_filename, hShpMix)) + { + FSunPackLib::SetCurrentSHP(superanim3_filename, hShpMix); + FSunPackLib::LoadSHPImageInSurface(v.dd, hPalette, 0, 1, &superanim3); + } + } + + superanim4_name=art.sections[image].values["SuperAnimFour"]; + if(superanim4_name.GetLength()>0) + { + superanim4_filename=superanim4_name+".shp"; + + if(isTrue(art.sections[image].values["NewTheater"])) + superanim4_filename.SetAt(1, theat); + + if(bAlwaysSetChar) superanim4_filename.SetAt(1, theat); + + if(FSunPackLib::XCC_DoesFileExist(superanim4_filename, hShpMix)) + { + FSunPackLib::SetCurrentSHP(superanim4_filename, hShpMix); + FSunPackLib::LoadSHPImageInSurface(v.dd, hPalette, 0, 1, &superanim4); + } + } + + specialanim1_name=art.sections[image].values["SpecialAnim"]; + if(specialanim1_name.GetLength()>0) + { + specialanim1_filename=specialanim1_name+".shp"; + + if(isTrue(art.sections[image].values["NewTheater"])) + specialanim1_filename.SetAt(1, theat); + + if(bAlwaysSetChar) specialanim1_filename.SetAt(1, theat); + + if(FSunPackLib::XCC_DoesFileExist(specialanim1_filename, hShpMix)) + { + FSunPackLib::SetCurrentSHP(specialanim1_filename, hShpMix); + FSunPackLib::LoadSHPImageInSurface(v.dd, hPalette, 0, 1, &specialanim1); + } + } + + specialanim2_name=art.sections[image].values["SpecialAnimTwo"]; + if(specialanim2_name.GetLength()>0) + { + specialanim2_filename=specialanim2_name+".shp"; + + if(isTrue(art.sections[image].values["NewTheater"])) + specialanim2_filename.SetAt(1, theat); + + if(bAlwaysSetChar) specialanim2_filename.SetAt(1, theat); + + if(FSunPackLib::XCC_DoesFileExist(specialanim2_filename, hShpMix)) + { + FSunPackLib::SetCurrentSHP(specialanim2_filename, hShpMix); + FSunPackLib::LoadSHPImageInSurface(v.dd, hPalette, 0, 1, &specialanim2); + } + } + + specialanim3_name=art.sections[image].values["SpecialAnimThree"]; + if(specialanim3_name.GetLength()>0) + { + specialanim3_filename=specialanim3_name+".shp"; + + if(isTrue(art.sections[image].values["NewTheater"])) + specialanim3_filename.SetAt(1, theat); + + if(bAlwaysSetChar) specialanim3_filename.SetAt(1, theat); + + if(FSunPackLib::XCC_DoesFileExist(specialanim3_filename, hShpMix)) + { + FSunPackLib::SetCurrentSHP(specialanim3_filename, hShpMix); + FSunPackLib::LoadSHPImageInSurface(v.dd, hPalette, 0, 1, &specialanim3); + } + } + + specialanim4_name=art.sections[image].values["SpecialAnimFour"]; + if(specialanim4_name.GetLength()>0) + { + specialanim4_filename=specialanim4_name+".shp"; + + if(isTrue(art.sections[image].values["NewTheater"])) + specialanim4_filename.SetAt(1, theat); + + if(bAlwaysSetChar) specialanim4_filename.SetAt(1, theat); + + if(FSunPackLib::XCC_DoesFileExist(specialanim4_filename, hShpMix)) + { + FSunPackLib::SetCurrentSHP(specialanim4_filename, hShpMix); + FSunPackLib::LoadSHPImageInSurface(v.dd, hPalette, 0, 1, &specialanim4); + } + } + + BOOL bVoxelTurret=FALSE; + + turretanim_name=rules.sections[image].values["TurretAnim"]; + if(bStructure && rules.sections[image].values["Turret"]=="yes" && turretanim_name.GetLength()>0 && rules.sections[image].values["TurretAnimIsVoxel"]!="true") + { + turretanim_filename=turretanim_name+".shp"; + if(art.sections[turretanim_name].values.find("Image")!=art.sections[turretanim_name].values.end()) turretanim_filename=art.sections[turretanim_name].values["Image"]+".shp"; + + if(isTrue(art.sections[image].values["NewTheater"])) + turretanim_filename.SetAt(1, theat); + + + FSunPackLib::SetCurrentSHP(turretanim_filename, hShpMix); + FSunPackLib::XCC_GetSHPHeader(&head); + + int iStartTurret=0; + const WORD wAnimCount=4; // anims between each "normal" direction, seems to be hardcoded + + int i; + + for(i=0;i<8;i++) + { + if(iStartTurret+i*wAnimCount0 && rules.sections[image].values["TurretAnimIsVoxel"]=="true") + { + turretanim_filename=turretanim_name+".vxl"; + if(art.sections[turretanim_name].values.find("Image")!=art.sections[turretanim_name].values.end()) turretanim_filename=art.sections[turretanim_name].values["Image"]+".vxl"; + + //if(isTrue(art.sections[image].values["NewTheater"])) + // turretanim_filename.SetAt(1, theat); + + HMIXFILE hVXL=FindFileInMix(turretanim_filename); + + if(hVXL) + { + bVoxelTurret=TRUE; + + if( + FSunPackLib::SetCurrentVXL(turretanim_filename, hVXL) + ) + { + int i; + + for(i=0;i<8;i++) + { + float r_x,r_y,r_z; + + + r_x=300; + r_y=0; + r_z=45*i+90; + + // convert + const double pi = 3.141592654; + r_x=r_x/180.0f*pi; + r_y=r_y/180.0f*pi; + r_z=r_z/180.0f*pi; + + int center_x, center_y; + if(! + FSunPackLib::LoadVXLImageInSurface(*m_voxelNormalTables, lightDirection, v.dd, 0, 1, r_x, r_y, r_z, &turrets[i], hPalette,¢er_x, ¢er_y,atoi(rules.sections[image].values["TurretAnimZAdjust"])) + ) + { + + } + else + { + DDSURFACEDESC2 ddsd; + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize=sizeof(DDSURFACEDESC2); + ddsd.dwFlags=DDSD_WIDTH | DDSD_HEIGHT; + turrets[i]->GetSurfaceDesc(&ddsd); + turretinfo[i].x=-center_x; + turretinfo[i].y=-center_y; + turretinfo[i].cx=ddsd.dwWidth; + turretinfo[i].cy=ddsd.dwHeight; + } + + } + } + } + } + + + if(art.sections[image].values.find("WalkFrames")!=art.sections[image].values.end()) + wStep=atoi(art.sections[image].values["WalkFrames"]); + if(art.sections[image].values.find("StartWalkFrame")!=art.sections[image].values.end()) + wStartWalkFrame=atoi(art.sections[image].values["StartWalkFrame"]); + if(art.sections[image].values.find("TurretOffset")!=art.sections[image].values.end()) + iTurretOffset=atoi(art.sections[image].values["TurretOffset"]); + + + if(art.sections[image].values["Palette"]=="lib") + hPalette=m_hPalLib; + + BOOL bSuccess=FSunPackLib::SetCurrentSHP(filename, hShpMix); + if( + !bSuccess + ) + { + filename=image+=".sno"; + if(cur_theat=='T' || cur_theat=='U') hPalette=m_hPalIsoTemp; + hShpMix=FindFileInMix(filename, &bTerrain); + bSuccess=FSunPackLib::SetCurrentSHP(filename, hShpMix); + + if(!bSuccess) + { + missingimages[lpUnittype]=TRUE; + } + } + + if(bSuccess) + { + + FSunPackLib::XCC_GetSHPHeader(&head); + int i; + int maxPics=head.c_images; + if(maxPics>8) maxPics=8; // we only need 8 pictures for every direction! + if(bStructure && !bPowerUp) maxPics=1; + if(bVoxelTurret) maxPics=8; + + + if(!bStructure && rules.sections[image].values["Turret"]=="yes") + { + int iStartTurret=wStartWalkFrame+8*wStep; + const WORD wAnimCount=4; // anims between each "normal" direction, seems to be hardcoded + + int i; + + for(i=0;i<8;i++) + { + if(!bStructure && iStartTurret+i*wAnimCountBlt(NULL, bib, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + + imghead.cx=head.cx-imghead.x; // update size of main graphic + imghead.cy=head.cy-imghead.y; + + } + + if(activeanim!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + lpT[i]->Blt(NULL, activeanim, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + + + } + + if(idleanim!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + lpT[i]->Blt(NULL, idleanim, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + + + } + + if(activeanim2!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + lpT[i]->Blt(NULL, activeanim2, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + + + } + + if(activeanim3!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + lpT[i]->Blt(NULL, activeanim3, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + + + } + + if(superanim1!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + lpT[i]->Blt(NULL, superanim1, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + + + } + + if(superanim2!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + lpT[i]->Blt(NULL, superanim2, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + + + } + + if(superanim3!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + lpT[i]->Blt(NULL, superanim3, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + + + } + + if(superanim4!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + lpT[i]->Blt(NULL, superanim4, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + + + } + + if(specialanim1!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + lpT[i]->Blt(NULL, specialanim1, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + + + } + + if(specialanim2!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + lpT[i]->Blt(NULL, specialanim2, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + + + } + + if(specialanim3!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + lpT[i]->Blt(NULL, specialanim3, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + + + } + + if(specialanim4!=NULL) + { + DDBLTFX fx; + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + lpT[i]->Blt(NULL, specialanim4, NULL, DDBLT_KEYSRC | DDBLT_WAIT , &fx); + + + } + + + + if(turrets[i]!=NULL) + { + DDBLTFX fx; + int iMove=0; + + DDSURFACEDESC2 ddsd; + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize=sizeof(DDSURFACEDESC2); + ddsd.dwFlags=DDSD_WIDTH | DDSD_HEIGHT; + turrets[i]->GetSurfaceDesc(&ddsd); + + + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + RECT srcRect, destRect; + srcRect.left=0; + srcRect.right=ddsd.dwWidth; + destRect.left=(head.cx-ddsd.dwWidth)/2; + destRect.right=head.cx-destRect.left; + + if(iMove<0) + { + srcRect.top=-iMove; + srcRect.bottom=ddsd.dwHeight; + destRect.top=0; + destRect.bottom=head.cy+iMove-(head.cy-ddsd.dwHeight); + } + else + { + int mx=imghead.x/2+imghead.cx/2+(-turretinfo[i].x/2-turretinfo[i].cx)+ atoi(rules.sections[image].values["TurretAnimX"]); + int my=imghead.y/2+imghead.cy/2+(-turretinfo[i].y/2-turretinfo[i].cy) + atoi(rules.sections[image].values["TurretAnimY"]);//+atoi(rules.sections[image].values["TurretAnimZAdjust"]); + + if(ddsd.dwWidth!=head.cx || ddsd.dwHeight!=head.cy) + { + // voxel turret + //mx=head.cx/2-ddsd.dwWidth/2;//+atoi(rules.sections[image].values["TurretAnimX"]); + //my=head.cy/2-ddsd.dwHeight/2+atoi(rules.sections[image].values["TurretAnimY"])+atoi(rules.sections[image].values["TurretAnimZAdjust"])/2; + mx=imghead.x+imghead.cx/2+turretinfo[i].x+atoi(rules.sections[image].values["TurretAnimX"]); + my=imghead.y+imghead.cy/2+turretinfo[i].y+atoi(rules.sections[image].values["TurretAnimY"]);//+atoi(rules.sections[image].values["TurretAnimZAdjust"])/2; + + errstream << turretinfo[i].x << " y:" << turretinfo[i].y << " mx:" << mx << " my:" << my << endl; + errstream.flush(); + + int XMover, YMover; +#ifdef RA2_MODE + XMover=atoi(g_data.sections["BuildingVoxelTurretsRA2"].values[(CString)lpUnittype+"X"]); + YMover=atoi(g_data.sections["BuildingVoxelTurretsRA2"].values[(CString)lpUnittype+"Y"]); +#else + XMover=atoi(g_data.sections["BuildingVoxelTurrets"].values[(CString)lpUnittype+"X"]); + YMover=atoi(g_data.sections["BuildingVoxelTurrets"].values[(CString)lpUnittype+"Y"]); +#endif + + mx+=XMover; + my+=YMover; + + srcRect.top=0; + srcRect.left=0; + srcRect.right=ddsd.dwWidth; + srcRect.bottom=ddsd.dwHeight; + destRect.top=my; + destRect.left=mx; + destRect.right=destRect.left+ddsd.dwWidth; + destRect.bottom=destRect.top+ddsd.dwHeight; + if(destRect.top<0) + { + int old=destRect.top; + destRect.top=0; + srcRect.top-=old-destRect.top; + + } + if(destRect.right>=head.cx) + { + int old=destRect.right; + destRect.right=head.cx; + srcRect.right-=old-destRect.right; + } + if(destRect.bottom>=head.cy) + { + int old=destRect.bottom; + destRect.bottom=head.cy; + srcRect.bottom-=old-destRect.bottom; + } + } + else + { + + if(mx<0)mx=0; + if(my<0)my=0; + srcRect.top=0; + srcRect.right=ddsd.dwWidth-mx; + srcRect.bottom=ddsd.dwHeight-my; + destRect.top=my; + destRect.left=mx+(head.cx-ddsd.dwWidth)/2; + destRect.right=destRect.left+ddsd.dwWidth;; + destRect.bottom=destRect.top+ddsd.dwHeight; + } + } + + + + + if(lpT[i]->Blt(&destRect, turrets[i], &srcRect, DDBLT_KEYSRC | DDBLT_WAIT, &fx)!=DD_OK) + { + + errstream << "vxl turret: " << i << " size: " << ddsd.dwWidth << " " << ddsd.dwHeight << " failed" << endl; + errstream.flush(); + //exit(-99); + } + + + } + + if(!bPowerUp && i!=0 && imghead.unknown==0 && bStructure) + { + if(lpT[i]) lpT[i]->Release(); + } + else + { + char ic[50]; + itoa(i, ic, 10); + + PICDATA p; + p.pic=lpT[i]; + p.x=imghead.x; + p.y=imghead.y; + p.wHeight=imghead.cy; + p.wWidth=imghead.cx; + p.wMaxWidth=head.cx; + p.wMaxHeight=head.cy; + p.bType=PICDATA_TYPE_SHP; + p.bTerrain=bTerrain; + if(bIgnoreTerrain) p.bTerrain=0; + + + pics[image+ic]=p; + + //errstream << " --> finished as " << (LPCSTR)(image+ic) << endl; + //errstream.flush(); + } + + + } + + delete[] lpT; + + + if(bib) bib->Release(); + if(activeanim)activeanim->Release(); + if(idleanim)idleanim->Release(); + if(activeanim2)activeanim2->Release(); + if(activeanim3)activeanim3->Release(); + if(superanim1)superanim1->Release(); + if(superanim2)superanim2->Release(); + if(superanim3)superanim3->Release(); + if(superanim4)superanim4->Release(); + if(specialanim1)specialanim1->Release(); + if(specialanim2)specialanim2->Release(); + if(specialanim3)specialanim3->Release(); + if(specialanim4)specialanim4->Release(); + + for(i=0;i<8;i++) + if(turrets[i])turrets[i]->Release(); + + } + + //errstream << " --> Finished" << endl; + //errstream.flush(); + } + + else + { + errstream << "File in theater " << cur_theat << " not found: " << (LPCTSTR)filename << endl; + errstream.flush(); + + missingimages[lpUnittype]=TRUE; + } + + } + catch(...) + { + errstream << " exception " << endl; + errstream.flush(); + } + + + } + else + { + filename=image+".vxl"; + + HMIXFILE hMix=FindFileInMix(filename); + if(hMix==FALSE) + { + missingimages[lpUnittype]=TRUE; + return FALSE; + } + + + int i; + + try + { + + for(i=0;i<8;i++) + { + float r_x,r_y,r_z; + + + r_x=300; + r_y=0; + r_z=45*i+90; + + // convert + const double pi = 3.141592654; + r_x=r_x/180.0f*pi; + r_y=r_y/180.0f*pi; + r_z=r_z/180.0f*pi; + + + + LPDIRECTDRAWSURFACE4 lpT;//=new(LPDIRECTDRAWSURFACE4[1]); + LPDIRECTDRAWSURFACE4 lpTurret=NULL; + LPDIRECTDRAWSURFACE4 lpBarrel=NULL; + int turret_x,turret_y,turret_x_zmax,turret_y_zmax,barrel_x,barrel_y; + + if(isTrue(rules.sections[lpUnittype].values["Turret"])) + { + if(FSunPackLib::SetCurrentVXL(image+"tur.vxl", hMix)) + { + FSunPackLib::LoadVXLImageInSurface(*m_voxelNormalTables, lightDirection, v.dd, 0, 1, r_x, r_y, r_z, &lpTurret, m_hPalUnitTemp,&turret_x,&turret_y,0,&turret_x_zmax, &turret_y_zmax,-1,-1); + } + if(FSunPackLib::SetCurrentVXL(image+"barl.vxl", hMix)) + { + FSunPackLib::LoadVXLImageInSurface(*m_voxelNormalTables, lightDirection, v.dd, 0, 1, r_x, r_y, r_z, &lpBarrel, m_hPalUnitTemp,&barrel_x,&barrel_y,0,NULL,NULL,0,0); + } + } + + + if(!FSunPackLib::SetCurrentVXL(filename, hMix)) + { + return FALSE; + } + + + + int xcenter,ycenter,xcenter_zmax,ycenter_zmax; + + if(! + FSunPackLib::LoadVXLImageInSurface(*m_voxelNormalTables, lightDirection, v.dd, 0, 1, r_x, r_y, r_z, &lpT, m_hPalUnitTemp,&xcenter, &ycenter,0,&xcenter_zmax,&ycenter_zmax) + ) + { + return FALSE; + } + + DDSURFACEDESC2 ddsd; + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize=sizeof(DDSURFACEDESC2); + ddsd.dwFlags=DDSD_WIDTH | DDSD_HEIGHT; + lpT->GetSurfaceDesc(&ddsd); + + // turret + if(lpTurret) + { + DDSURFACEDESC2 ddsdT; + memset(&ddsdT, 0, sizeof(DDSURFACEDESC2)); + ddsdT.dwSize=sizeof(DDSURFACEDESC2); + ddsdT.dwFlags=DDSD_WIDTH | DDSD_HEIGHT; + lpTurret->GetSurfaceDesc(&ddsdT); + + DDBLTFX fx; + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + RECT srcRect, destRect; + srcRect.left=0; + srcRect.right=ddsdT.dwWidth; + destRect.left=xcenter_zmax-turret_x; + destRect.right=destRect.left+ddsdT.dwWidth; + srcRect.top=0; + srcRect.bottom=ddsdT.dwHeight; + destRect.top=ycenter_zmax-turret_y; + destRect.bottom=destRect.top+ddsdT.dwHeight; + + lpT->Blt(&destRect, lpTurret, &srcRect, DDBLT_KEYSRC | DDBLT_WAIT, &fx); + + } + + // barrel + if(lpBarrel) + { + DDSURFACEDESC2 ddsdB; + memset(&ddsdB, 0, sizeof(DDSURFACEDESC2)); + ddsdB.dwSize=sizeof(DDSURFACEDESC2); + ddsdB.dwFlags=DDSD_WIDTH | DDSD_HEIGHT; + lpBarrel->GetSurfaceDesc(&ddsdB); + + DDSURFACEDESC2 ddsdT; + memset(&ddsdT, 0, sizeof(DDSURFACEDESC2)); + ddsdT.dwSize=sizeof(DDSURFACEDESC2); + ddsdT.dwFlags=DDSD_WIDTH | DDSD_HEIGHT; + + if(lpTurret) lpTurret->GetSurfaceDesc(&ddsdT); + + + DDBLTFX fx; + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize=sizeof(DDBLTFX); + + RECT srcRect, destRect; + srcRect.left=0; + srcRect.right=ddsdB.dwWidth; + destRect.left=xcenter_zmax-barrel_x+(turret_x_zmax-turret_x); + destRect.right=destRect.left+ddsdB.dwWidth; + srcRect.top=0; + srcRect.bottom=ddsdB.dwHeight; + destRect.top=ycenter_zmax-barrel_y+(turret_y_zmax-turret_y); + destRect.bottom=destRect.top+ddsdB.dwHeight; + + lpT->Blt(&destRect, lpBarrel, &srcRect, DDBLT_KEYSRC | DDBLT_WAIT, &fx); + + } + + char ic[50]; + itoa(7-i, ic, 10); + + errstream << ddsd.dwWidth << " " << ddsd.dwHeight << "\n"; + PICDATA p; + p.pic=lpT; + p.x=-xcenter; + p.y=-ycenter; + p.wHeight=ddsd.dwHeight; + p.wWidth=ddsd.dwWidth; + p.wMaxWidth=ddsd.dwWidth; + p.wMaxHeight=ddsd.dwHeight; + p.bType=PICDATA_TYPE_VXL; + p.bTerrain=0; + + pics[image+ic]=p; + + errstream << "vxl saved as " << (LPCSTR)image << (LPCSTR)ic << endl; + errstream.flush(); + + if(lpBarrel) lpBarrel->Release(); + if(lpTurret) lpTurret->Release(); + + //delete[] lpT; + + } + } + catch(...) + { + + } + + } + + + + return FALSE; +} +#endif + + +BOOL CLoading::InitMixFiles() +{ + last_succeeded_operation=8; + + MEMORYSTATUS ms; + ms.dwLength=sizeof(MEMORYSTATUS); + GlobalMemoryStatus(&ms); + int cs=ms.dwAvailPhys+ms.dwAvailPageFile; + + errstream << "InitMixFiles() called. Available memory: " << cs << endl; + errstream.flush(); + + + // load tibsun.mix and local.mix + if(DoesFileExist((CString)TSPath+(CString)"\\"+MAINMIX)) + { + errstream << "Loading " MAINMIX ".mix" ; + errstream.flush(); + m_hTibSun=FSunPackLib::XCC_OpenMix((CString)TSPath+(CString)"\\"+MAINMIX, NULL); + if(m_hTibSun!=NULL) + { + errstream << " success" << endl; + errstream.flush(); + } + else + { + ShowWindow(SW_HIDE); + MessageBox(GetLanguageStringACP("Err_TSNotInstalled")); + exit(200); + } + + m_hLanguage=FSunPackLib::XCC_OpenMix((CString)TSPath+(CString)"\\Language.mix", NULL); + m_hLangMD=FSunPackLib::XCC_OpenMix((CString)TSPath+(CString)"\\Langmd.mix", NULL); + m_hMarble=FSunPackLib::XCC_OpenMix((CString)TSPath+(CString)"\\marble.mix", NULL); + + //if(!m_hLanguage) MessageBox("No language file found"); + + if(!m_hMarble) + { + m_hMarble=FSunPackLib::XCC_OpenMix((CString)AppPath+(CString)"\\marble.mix", NULL); + } + } + else + { + ShowWindow(SW_HIDE); + MessageBox(GetLanguageStringACP("Err_TSNotInstalled")); + exit(199); + } + + errstream << "Loading local.mix"; + errstream.flush(); + if(DoesFileExist((CString)TSPath+"\\Local.mix")==FALSE || theApp.m_Options.bSearchLikeTS==FALSE) + { + m_hLocal=FSunPackLib::XCC_OpenMix("Local.mix", m_hTibSun); + } + else + m_hLocal=FSunPackLib::XCC_OpenMix((CString)TSPath+"\\Local.mix", NULL); + errstream << " successful" << endl; + errstream.flush(); + + + + errstream << "Loading conquer.mix, temperat.mix, isotemp.mix, isosnow.mix, isourb.mix and cache.mix"; + errstream.flush(); + m_hConquer=FSunPackLib::XCC_OpenMix("conquer.mix", m_hTibSun); + m_hTemperat=FSunPackLib::XCC_OpenMix("temperat.mix", m_hTibSun); + m_hUrban=FSunPackLib::XCC_OpenMix("urban.mix", m_hTibSun); + m_hSnow=FSunPackLib::XCC_OpenMix("snow.mix", m_hTibSun); + m_hUrbanN=FSunPackLib::XCC_OpenMix("urbann.mix", m_hTibSun); + m_hLunar=FSunPackLib::XCC_OpenMix("lunar.mix", m_hTibSun); + m_hDesert=FSunPackLib::XCC_OpenMix("desert.mix", m_hTibSun); + m_hIsoTemp=FSunPackLib::XCC_OpenMix("isotemp.mix", m_hTibSun); + m_hIsoSnow=FSunPackLib::XCC_OpenMix("isosnow.mix", m_hTibSun); + m_hIsoUrb=FSunPackLib::XCC_OpenMix("isourb.mix", m_hTibSun); + m_hIsoUbn=FSunPackLib::XCC_OpenMix("isoubn.mix", m_hTibSun); + m_hIsoLun=FSunPackLib::XCC_OpenMix("isolun.mix", m_hTibSun); + m_hIsoDes=FSunPackLib::XCC_OpenMix("isodes.mix", m_hTibSun); + m_hIsoGen=FSunPackLib::XCC_OpenMix("isogen.mix", m_hTibSun); + //m_hBuildings=FSunPackLib::XCC_OpenMix("_ID1085587737", m_hTibSun); + m_hBuildings=FSunPackLib::XCC_OpenMix("Generic.mix", m_hTibSun); + m_hCache=FSunPackLib::XCC_OpenMix("cache.mix", m_hTibSun); + m_hTem=FSunPackLib::XCC_OpenMix("tem.mix", m_hTibSun); + m_hSno=FSunPackLib::XCC_OpenMix("sno.mix", m_hTibSun); + m_hUrb=FSunPackLib::XCC_OpenMix("urb.mix", m_hTibSun); + m_hUbn=FSunPackLib::XCC_OpenMix("ubn.mix", m_hTibSun); + m_hLun=FSunPackLib::XCC_OpenMix("lun.mix", m_hTibSun); + m_hDes=FSunPackLib::XCC_OpenMix("des.mix", m_hTibSun); + if(!m_hMarble) FSunPackLib::XCC_OpenMix("marble.mix", m_hTibSun); + + if(m_hMarble) theApp.m_Options.bSupportMarbleMadness=TRUE; + + errstream << " successful" << endl; + errstream.flush(); + + int i; + + yuri_mode=FALSE; + + + if(!theApp.m_Options.bSearchLikeTS) return TRUE; + + if(DoesFileExist((CString)TSPath+"\\ra2md.mix")) + yuri_mode=TRUE; // MW Apr 17th, make it available right here! + + // load expansion mix files + for(i=0;i<101;i++) + { + CString expand; + char n[50]; + + // MW April 17th, 2002: + // read expandxxmd.mix files in yurimode + + itoa(i, n, 10); + expand=TSPath; + expand+="\\Expand"; + if(yuri_mode) expand+="md"; + if(i<10) expand+="0"; + expand+=n; + expand+=".mix"; + + CString nappend=".mix"; + + CString append=".mix"; + if(i==100) append="md.mix"; + + + if(yuri_mode) append="md.mix"; + + + if(i==100) expand=(CString)TSPath+"\\ra2md.mix"; // support the mission disk!!! + + errstream << "Searching " << (LPCTSTR)expand << endl; + errstream.flush(); + + if(DoesFileExist(expand)) + { + + OutputDebugString(expand); + OutputDebugString(": "); + + + m_hExpand[i].hExpand=FSunPackLib::XCC_OpenMix(expand, NULL); + +#ifdef YR_MODE + if(i==100 && m_hExpand[i].hExpand) yuri_mode=TRUE; +#endif + + errstream << (LPCTSTR)expand << " found: loading "; + errstream.flush(); + + CString conquer="conquer"; + if(i==100) conquer="conq"; + if(FSunPackLib::XCC_DoesFileExist(conquer+append, m_hExpand[i].hExpand)) + { + OutputDebugString(conquer+append); + OutputDebugString(": "); + m_hExpand[i].hConquer=FSunPackLib::XCC_OpenMix((CString)conquer+append, m_hExpand[i].hExpand); + errstream << "conquer.mix, "; + } + if(FSunPackLib::XCC_DoesFileExist((CString)"local"+append, m_hExpand[i].hExpand)) + { + OutputDebugString((CString)"local"+append); + OutputDebugString(": "); + m_hExpand[i].hLocal=FSunPackLib::XCC_OpenMix((CString)"local"+append, m_hExpand[i].hExpand); + errstream << "local.mix, "; + } + //if(FSunPackLib::XCC_DoesFileExist("_ID1085587737", m_hExpand[i].hExpand)) + { + //m_hExpand[i].hConquer=FSunPackLib::XCC_OpenMix("_ID1085587737", m_hExpand[i].hExpand); + //errstream << "1085587737, "; + } + if(FSunPackLib::XCC_DoesFileExist((CString)"temperat"+append, m_hExpand[i].hExpand)) + { + OutputDebugString((CString)"temperat"+append); + OutputDebugString(": "); + m_hExpand[i].hTemperat=FSunPackLib::XCC_OpenMix((CString)"temperat"+append, m_hExpand[i].hExpand); + errstream << "temperat.mix, "; + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"urban"+append, m_hExpand[i].hExpand)) + { + OutputDebugString((CString)"urban"+append); + OutputDebugString(": "); + m_hExpand[i].hUrban=FSunPackLib::XCC_OpenMix((CString)"urban"+append, m_hExpand[i].hExpand); + errstream << "urban.mix, "; + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"snow"+append, m_hExpand[i].hExpand)) + { + OutputDebugString((CString)"snow"+append); + OutputDebugString(": "); + + FSunPackLib::_DEBUG_EnableLogs=true; + + HMIXFILE hM=FSunPackLib::XCC_OpenMix((CString)"snow"+append, m_hExpand[i].hExpand); + m_hExpand[i].hSnow=hM; + errstream << "snow.mix, "; + errstream.flush(); + + FSunPackLib::_DEBUG_EnableLogs=false; + } + + CString generic="generic"; + if(i==100) generic="gener"; + if(FSunPackLib::XCC_DoesFileExist((CString)generic+append, m_hExpand[i].hExpand)) + { + m_hExpand[i].hGeneric=FSunPackLib::XCC_OpenMix((CString)generic+append, m_hExpand[i].hExpand); + errstream << "generic.mix, "; + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"urbann"+nappend, m_hExpand[i].hExpand)) + { + m_hExpand[i].hUrbanN=FSunPackLib::XCC_OpenMix((CString)"urbann"+nappend, m_hExpand[i].hExpand); + errstream << "urbann.mix, "; + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"lunar"+nappend, m_hExpand[i].hExpand)) + { + m_hExpand[i].hLunar=FSunPackLib::XCC_OpenMix((CString)"lunar"+nappend, m_hExpand[i].hExpand); + errstream << "lunar.mix, "; + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"desert"+nappend, m_hExpand[i].hExpand)) + { + m_hExpand[i].hDesert=FSunPackLib::XCC_OpenMix((CString)"desert"+nappend, m_hExpand[i].hExpand); + errstream << "desert.mix, "; + errstream.flush(); + } + CString isotemp="isotemp"; + if(i==100) isotemp="isotem"; + if(FSunPackLib::XCC_DoesFileExist(isotemp+append, m_hExpand[i].hExpand)) + { + m_hExpand[i].hIsoTemp=FSunPackLib::XCC_OpenMix((CString)isotemp+append, m_hExpand[i].hExpand); + errstream << "isotemp.mix, "; + errstream.flush(); + } + CString isosnow="isosnow"; + if(i==100) isosnow="isosno"; + if(FSunPackLib::XCC_DoesFileExist((CString)isosnow+append, m_hExpand[i].hExpand)) + { + m_hExpand[i].hIsoSnow=FSunPackLib::XCC_OpenMix((CString)isosnow+append, m_hExpand[i].hExpand); + errstream << "isosnow.mix, "; + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"isourb"+append, m_hExpand[i].hExpand)) + { + m_hExpand[i].hIsoUrb=FSunPackLib::XCC_OpenMix((CString)"isourb"+append, m_hExpand[i].hExpand); + errstream << "isourb.mix, "; + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"isoubn"+append, m_hExpand[i].hExpand)) + { + m_hExpand[i].hIsoUbnMd=FSunPackLib::XCC_OpenMix((CString)"isoubn"+append, m_hExpand[i].hExpand); + errstream << "isoubn.mix, "; + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"isolun"+append, m_hExpand[i].hExpand)) + { + m_hExpand[i].hIsoLunMd=FSunPackLib::XCC_OpenMix((CString)"isolun"+append, m_hExpand[i].hExpand); + errstream << "isolun.mix, "; + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"isodes"+append, m_hExpand[i].hExpand)) + { + m_hExpand[i].hIsoDesMd=FSunPackLib::XCC_OpenMix((CString)"isodes"+append, m_hExpand[i].hExpand); + errstream << "isodes.mix, "; + errstream.flush(); + } + + if(FSunPackLib::XCC_DoesFileExist((CString)"isoubn"+nappend, m_hExpand[i].hExpand)) + { + m_hExpand[i].hIsoUbn=FSunPackLib::XCC_OpenMix((CString)"isoubn"+nappend, m_hExpand[i].hExpand); + errstream << "isoubn.mix, "; + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"isolun"+nappend, m_hExpand[i].hExpand)) + { + m_hExpand[i].hIsoLun=FSunPackLib::XCC_OpenMix((CString)"isolun"+nappend, m_hExpand[i].hExpand); + errstream << "isolun.mix, "; + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"isodes"+nappend, m_hExpand[i].hExpand)) + { + m_hExpand[i].hIsoDes=FSunPackLib::XCC_OpenMix((CString)"isodes"+nappend, m_hExpand[i].hExpand); + errstream << "isodes.mix, "; + errstream.flush(); + } + + if(FSunPackLib::XCC_DoesFileExist((CString)"isogen"+append, m_hExpand[i].hExpand)) + { + m_hExpand[i].hIsoGenMd=FSunPackLib::XCC_OpenMix((CString)"isogen"+append, m_hExpand[i].hExpand); + errstream << "isogen.mix, "; + errstream.flush(); + } + + if(FSunPackLib::XCC_DoesFileExist((CString)"isogen"+nappend, m_hExpand[i].hExpand)) + { + m_hExpand[i].hIsoGen=FSunPackLib::XCC_OpenMix((CString)"isogen"+nappend, m_hExpand[i].hExpand); + errstream << "isogen.mix, "; + errstream.flush(); + } + + CString cache="ecache01"; + if(i==100) cache="cache"; + if(FSunPackLib::XCC_DoesFileExist((CString)cache+append, m_hExpand[i].hExpand)) + { + m_hExpand[i].hECache=FSunPackLib::XCC_OpenMix((CString)cache+append, m_hExpand[i].hExpand); + errstream << LPCSTR("ecache01"+append+", "); + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"tem"+append, m_hExpand[i].hExpand)) + { + m_hExpand[i].hTem=FSunPackLib::XCC_OpenMix((CString)"tem"+append, m_hExpand[i].hExpand); + errstream << LPCSTR("tem"+append+", "); + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"sno"+append, m_hExpand[i].hExpand)) + { + m_hExpand[i].hSno=FSunPackLib::XCC_OpenMix((CString)"sno"+append, m_hExpand[i].hExpand); + errstream << LPCSTR("sno"+append+", "); + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"urb"+append, m_hExpand[i].hExpand)) + { + m_hExpand[i].hUrb=FSunPackLib::XCC_OpenMix((CString)"urb"+append, m_hExpand[i].hExpand); + errstream << LPCSTR("urb"+append+", "); + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"ubn"+nappend, m_hExpand[i].hExpand)) + { + m_hExpand[i].hUbn=FSunPackLib::XCC_OpenMix((CString)"ubn"+nappend, m_hExpand[i].hExpand); + errstream << LPCSTR("ubn"+nappend+", "); + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"lun"+nappend, m_hExpand[i].hExpand)) + { + m_hExpand[i].hLun=FSunPackLib::XCC_OpenMix((CString)"lun"+nappend, m_hExpand[i].hExpand); + errstream << LPCSTR("lun"+nappend+", "); + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"des"+nappend, m_hExpand[i].hExpand)) + { + m_hExpand[i].hDes=FSunPackLib::XCC_OpenMix((CString)"des"+nappend, m_hExpand[i].hExpand); + errstream << LPCSTR("des"+nappend+", "); + errstream.flush(); + } + if(FSunPackLib::XCC_DoesFileExist((CString)"marble"+append, m_hExpand[i].hExpand)) + { + theApp.m_Options.bSupportMarbleMadness=TRUE; + + m_hExpand[i].hMarble=FSunPackLib::XCC_OpenMix((CString)"marble"+append, m_hExpand[i].hExpand); + errstream << LPCSTR("marble"+append+", "); + errstream.flush(); + } + + errstream << endl; + errstream.flush(); + } + else + { + m_hExpand[i].hExpand=NULL; + } + } + + // load expansion ecache mix files + for(i=0;i<100;i++) + { + CString expand; + char n[50]; + + itoa(i, n, 10); + expand=TSPath; + if(!yuri_mode) expand+="\\ECache"; + else expand+="\\ecachemd"; + + if(i<10) expand+="0"; + expand+=n; + expand+=".mix"; + + + if(DoesFileExist(expand)) + { + m_hECache[i]=FSunPackLib::XCC_OpenMix(expand, NULL); + errstream << (LPCTSTR)expand << " found and loaded" << endl; + errstream.flush(); + } + else + { + m_hECache[i]=NULL; + } + } + + ms.dwLength=sizeof(MEMORYSTATUS); + GlobalMemoryStatus(&ms); + cs=ms.dwAvailPhys+ms.dwAvailPageFile; + + errstream << "InitMixFiles() finished. Available memory: " << cs << endl; + errstream.flush(); + + return TRUE; +} + +CLoading::~CLoading() +{ + Unload(); +} + +void CLoading::Unload() +{ + FSunPackLib::XCC_CloseMix(m_hCache); + FSunPackLib::XCC_CloseMix(m_hConquer); + FSunPackLib::XCC_CloseMix(m_hIsoSnow); + FSunPackLib::XCC_CloseMix(m_hIsoTemp); + FSunPackLib::XCC_CloseMix(m_hIsoUrb); + FSunPackLib::XCC_CloseMix(m_hIsoGen); + FSunPackLib::XCC_CloseMix(m_hLocal); + FSunPackLib::XCC_CloseMix(m_hTemperat); + FSunPackLib::XCC_CloseMix(m_hSnow); + FSunPackLib::XCC_CloseMix(m_hUrban); + FSunPackLib::XCC_CloseMix(m_hTibSun); + FSunPackLib::XCC_CloseMix(m_hSno); + FSunPackLib::XCC_CloseMix(m_hTem); + FSunPackLib::XCC_CloseMix(m_hUrb); + FSunPackLib::XCC_CloseMix(m_hBuildings); + + + m_hCache = NULL; + m_hConquer = NULL; + m_hIsoSnow = NULL; + m_hIsoTemp = NULL; + m_hIsoUrb = NULL; + m_hLocal = NULL; + m_hTemperat = NULL; + m_hSnow = NULL; + m_hUrban = NULL; + m_hTibSun = NULL; + m_hBuildings = NULL; + m_hIsoGen = NULL; + + + int i = 0; + for (i = 0;i < 100; i++) + { + FSunPackLib::XCC_CloseMix(m_hExpand[i].hExpand); + FSunPackLib::XCC_CloseMix(m_hExpand[i].hConquer); + FSunPackLib::XCC_CloseMix(m_hExpand[i].hECache); + FSunPackLib::XCC_CloseMix(m_hExpand[i].hIsoSnow); + FSunPackLib::XCC_CloseMix(m_hExpand[i].hIsoTemp); + FSunPackLib::XCC_CloseMix(m_hExpand[i].hIsoUrb); + FSunPackLib::XCC_CloseMix(m_hExpand[i].hIsoGen); + FSunPackLib::XCC_CloseMix(m_hExpand[i].hTemperat); + FSunPackLib::XCC_CloseMix(m_hExpand[i].hSnow); + FSunPackLib::XCC_CloseMix(m_hExpand[i].hUrban); + FSunPackLib::XCC_CloseMix(m_hExpand[i].hSno); + FSunPackLib::XCC_CloseMix(m_hExpand[i].hTem); + FSunPackLib::XCC_CloseMix(m_hExpand[i].hUrb); + FSunPackLib::XCC_CloseMix(m_hExpand[i].hBuildings); + m_hExpand[i].hExpand = NULL; + } + + for (i = 0;i < 100; i++) + { + FSunPackLib::XCC_CloseMix(m_hECache[i]); + } + + MEMORYSTATUS ms; + ms.dwLength = sizeof(MEMORYSTATUS); + GlobalMemoryStatus(&ms); + int cs = ms.dwAvailPhys + ms.dwAvailPageFile; + + errstream << "CLoading::Unload finished. Available memory: " << cs << endl; + errstream.flush(); +} + + +HMIXFILE CLoading::FindFileInMix(LPCTSTR lpFilename, TheaterChar* pTheaterChar) +{ + if(pTheaterChar) + *pTheaterChar = TheaterChar::None; + + int i; + // MW: added ecache support + for(i=100;i>=0; i--) + { + HMIXFILE cuExp=m_hECache[i]; + + if(cuExp!=NULL) + { + if(FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp)) + return cuExp; + } + } + + for(i=100;i>=0; i--) + { + EXPANDMIX cuExp=m_hExpand[i]; + + if(cuExp.hExpand!=NULL) + { + if(FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hExpand)) + return cuExp.hExpand; + if(cuExp.hECache!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hECache)) + return cuExp.hECache; + if(cuExp.hConquer!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hConquer)) + return cuExp.hConquer; + if(cuExp.hLocal!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hLocal)) + return cuExp.hLocal; + if(cuExp.hTemperat!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hTemperat)) + return cuExp.hTemperat; + if(strcmp(lpFilename,"yayard.shp")==NULL) + FSunPackLib::_DEBUG_EnableLogs=true; + if(cuExp.hSnow!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hSnow)) + return cuExp.hSnow; + FSunPackLib::_DEBUG_EnableLogs=false; + if(cuExp.hGeneric!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hGeneric)) + return cuExp.hGeneric; + if(cuExp.hUrban!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hUrban)) + return cuExp.hUrban; + if(cuExp.hUrbanN!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hUrbanN)) + return cuExp.hUrbanN; + if(cuExp.hLunar!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hLunar)) + return cuExp.hLunar; + if(cuExp.hDesert!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hDesert)) + return cuExp.hDesert; + if(cuExp.hBuildings!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hBuildings)) + return cuExp.hBuildings; + if(cuExp.hIsoGen!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hIsoGen)) + return cuExp.hIsoGen; + if(cuExp.hIsoGenMd!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hIsoGenMd)) + return cuExp.hIsoGenMd; + if(cuExp.hIsoTemp!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hIsoTemp)) + { + if(pTheaterChar) *pTheaterChar=TheaterChar::T; + return cuExp.hIsoTemp; + } + if(cuExp.hIsoSnow!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hIsoSnow)) + { + if(pTheaterChar) *pTheaterChar = TheaterChar::A; + return cuExp.hIsoSnow; + } + if(cuExp.hIsoUrb!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hIsoUrb)) + { + if(pTheaterChar) *pTheaterChar = TheaterChar::U; + return cuExp.hIsoUrb; + } + if(cuExp.hIsoUbn!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hIsoUbn)) + { + if(pTheaterChar) *pTheaterChar = TheaterChar::N; + return cuExp.hIsoUbn; + } + if(cuExp.hIsoDes!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hIsoDes)) + { + if(pTheaterChar) *pTheaterChar = TheaterChar::D; + return cuExp.hIsoDes; + } + if(cuExp.hIsoLun!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hIsoLun)) + { + if(pTheaterChar) *pTheaterChar = TheaterChar::L; + return cuExp.hIsoLun; + } + if(cuExp.hIsoUbnMd!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hIsoUbnMd)) + { + if(pTheaterChar) *pTheaterChar = TheaterChar::N; + return cuExp.hIsoUbnMd; + } + if(cuExp.hIsoDesMd!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hIsoDesMd)) + { + if(pTheaterChar) *pTheaterChar = TheaterChar::D; + return cuExp.hIsoDesMd; + } + if(cuExp.hIsoLunMd!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hIsoLunMd)) + { + if(pTheaterChar) *pTheaterChar = TheaterChar::L; + return cuExp.hIsoLunMd; + } + if(cuExp.hSno!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hSno)) + return cuExp.hSno; + if(cuExp.hTem!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hTem)) + return cuExp.hTem; + if(cuExp.hUrb!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hUrb)) + return cuExp.hUrb; + if(cuExp.hUbn!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hUbn)) + return cuExp.hUbn; + if(cuExp.hLun!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hLun)) + return cuExp.hLun; + if(cuExp.hDes!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hDes)) + return cuExp.hDes; + if(cuExp.hMarble!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, cuExp.hMarble)) + return cuExp.hMarble; + } + } + + if(m_hTibSun!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hTibSun)) + return m_hTibSun; + if(m_hLanguage!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hLanguage)) + return m_hLanguage; + if(m_hLangMD!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hLangMD)) + return m_hLangMD; + if(m_hLocal!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hLocal)) + return m_hLocal; + if(m_hBuildings!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hBuildings)) + return m_hBuildings; + if(m_hCache!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hCache)) + return m_hCache; + if(m_hConquer!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hConquer)) + return m_hConquer; + if(m_hTemperat!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hTemperat)) + return m_hTemperat; + if(m_hSnow!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hSnow)) + return m_hSnow; + if(m_hUrban!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hUrban)) + return m_hUrban; + if(m_hUrbanN!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hUrbanN)) + return m_hUrbanN; + if(m_hLunar!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hLunar)) + return m_hLunar; + if(m_hDesert!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hDesert)) + return m_hDesert; + if(m_hIsoGen!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hIsoGen)) + { + return m_hIsoGen; + } + if(m_hIsoTemp!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hIsoTemp)) + { + if(pTheaterChar) *pTheaterChar = TheaterChar::T; + return m_hIsoTemp; + } + if(m_hIsoSnow!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hIsoSnow)) + { + if(pTheaterChar) *pTheaterChar = TheaterChar::A; + return m_hIsoSnow; + } + if(m_hIsoUrb!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hIsoUrb)) + { + if(pTheaterChar) *pTheaterChar = TheaterChar::U; + return m_hIsoUrb; + } + if(m_hIsoUbn!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hIsoUbn)) + { + if(pTheaterChar) *pTheaterChar = TheaterChar::N; + return m_hIsoUbn; + } + if(m_hIsoLun!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hIsoLun)) + { + if(pTheaterChar) *pTheaterChar = TheaterChar::L; + return m_hIsoLun; + } + if(m_hIsoDes!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hIsoDes)) + { + if(pTheaterChar) *pTheaterChar = TheaterChar::D; + return m_hIsoDes; + } + if(m_hTem!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hTem)) + return m_hTem; + if(m_hSno!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hSno)) + return m_hSno; + if(m_hUrb!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hUrb)) + return m_hUrb; + if(m_hUbn!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hUbn)) + return m_hUbn; + if(m_hLun!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hLun)) + return m_hLun; + if(m_hDes!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hDes)) + return m_hDes; + + if(m_hMarble!=NULL && FSunPackLib::XCC_DoesFileExist(lpFilename, m_hMarble)) + return m_hMarble; + + + + return NULL; +} + + + +void CLoading::InitPalettes() +{ + errstream << "InitPalettes() called\n"; + if(!FSunPackLib::XCC_ExtractFile("isotem.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache)) + errstream << "IsoTem.pal failed\n"; + m_hPalIsoTemp=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + if(!FSunPackLib::XCC_ExtractFile("isosno.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache)) + errstream << "IsoSno.pal failed\n"; + m_hPalIsoSnow=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + if(!FSunPackLib::XCC_ExtractFile("isourb.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache)) + errstream << "IsoUrb.pal failed\n"; + m_hPalIsoUrb=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + HMIXFILE m_hCache2=m_hExpand[100].hECache; + if(!FSunPackLib::XCC_ExtractFile("isolun.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache2)) + errstream << "IsoLun.pal failed\n"; + m_hPalIsoLun=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + if(!FSunPackLib::XCC_ExtractFile("isodes.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache2)) + errstream << "IsoDes.pal failed\n"; + m_hPalIsoDes=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + if(!FSunPackLib::XCC_ExtractFile("isoubn.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache2)) + errstream << "IsoUbn.pal failed\n"; + m_hPalIsoUbn=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + + if(!FSunPackLib::XCC_ExtractFile("unittem.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache)) + errstream << "UnitTem.pal failed"; + m_hPalUnitTemp=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + if(!FSunPackLib::XCC_ExtractFile("unitsno.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache)) + errstream << "UnitSno.pal failed\n"; + m_hPalUnitSnow=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + if(!FSunPackLib::XCC_ExtractFile("uniturb.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache)) + errstream << "UnitUrb.pal failed\n"; + m_hPalUnitUrb=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + + if(!FSunPackLib::XCC_ExtractFile("unitlun.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache2)) + errstream << "UnitLun.pal failed\n"; + m_hPalUnitLun=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + if(!FSunPackLib::XCC_ExtractFile("unitdes.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache2)) + errstream << "UnitDes.pal failed\n"; + m_hPalUnitDes=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + if(!FSunPackLib::XCC_ExtractFile("unitubn.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache2)) + errstream << "UnitUbn.pal failed\n"; + m_hPalUnitUbn=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + + if(!FSunPackLib::XCC_ExtractFile("snow.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache)) + errstream << "Snow.pal failed\n"; + m_hPalSnow=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + if(!FSunPackLib::XCC_ExtractFile("temperat.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache)) + errstream << "Temperat.pal failed\n"; + m_hPalTemp=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + if(!FSunPackLib::XCC_ExtractFile("urban.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache)) + errstream << "Urban.pal failed\n"; + m_hPalUrb=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + + if(!FSunPackLib::XCC_ExtractFile("lunar.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache2)) + errstream << "lunar.pal failed\n"; + m_hPalLun=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + if(!FSunPackLib::XCC_ExtractFile("desert.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache2)) + errstream << "desert.pal failed\n"; + m_hPalDes=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + if(!FSunPackLib::XCC_ExtractFile("urbann.pal", u8AppDataPath+"\\TmpPalette.pal", m_hCache2)) + errstream << "urbann.pal failed\n"; + m_hPalUbn=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + + if(!FSunPackLib::XCC_ExtractFile("_ID2124019542", u8AppDataPath+"\\TmpPalette.pal", m_hCache)) + errstream << "lib.pal failed\n"; + m_hPalLib=FSunPackLib::LoadTSPalette(u8AppDataPath+"\\TmpPalette.pal", NULL); + deleteFile(u8AppDataPath +"\\TmpPalette.pal"); + + + errstream << "\n"; + errstream.flush(); + + +} + +void CLoading::InitTMPs(CProgressCtrl* prog) +{ + FetchPalettes(); + + + MEMORYSTATUS ms; + ms.dwLength=sizeof(MEMORYSTATUS); + GlobalMemoryStatus(&ms); + int cs=ms.dwAvailPhys+ms.dwAvailPageFile; + + errstream << "InitTMPs() called. Available memory: " << cs << endl; + errstream.flush(); + + // we need to have that here, CMapData::UpdateIniFile() is too late for the shore hack + shoreset=atoi((*tiles).sections["General"].values["ShorePieces"]); + waterset=atoi((*tiles).sections["General"].values["WaterSet"]); + + + + + + + int i, tcount=0; + + for(i=0;i<10000;i++) + { + CString tset; + char c[50]; + itoa(i, c, 10); + int e; + for(e=0;e<4-strlen(c);e++) + tset+="0"; + tset+=c; + CString sec="TileSet"; + sec+=tset; + + if(tiles->sections.find(sec)==tiles->sections.end()) break; + + for(e=0;esections[sec].values["TilesInSet"]);e++) + { + tcount++; + } + + + } + + if(prog) prog->SetRange(0, tcount); + if(prog) prog->SetPos(0); + + if(*tiledata!=NULL) delete[] *tiledata; + *tiledata=new(TILEDATA[tcount]); + *tiledata_count=tcount; + + DWORD tilecount=0; + for(i=0;i<10000;i++) + { + CString tset; + char c[50]; + itoa(i, c, 10); + int e; + for(e=0;e<4-strlen(c);e++) + tset+="0"; + tset+=c; + CString sec="TileSet"; + sec+=tset; + + if(tiles->sections.find(sec)==tiles->sections.end()) break; + + BOOL bTib, bMorph, bPlace, bMadness; + bPlace=TRUE; + bTib=FALSE; + bMorph=FALSE; + bMadness=FALSE; + tiles->sections[sec].values["AllowTiberium"].MakeLower(); + if(tiles->sections[sec].values["AllowTiberium"]=="true") + bTib=TRUE; + tiles->sections[sec].values["Morphable"].MakeLower(); + if(tiles->sections[sec].values["Morphable"]=="true") + bMorph=TRUE; + tiles->sections[sec].values["AllowToPlace"].MakeLower(); + if(tiles->sections[sec].values["AllowToPlace"]=="no") + bPlace=FALSE; + tiles->sections[sec].values["NonMarbleMadness"].MakeLower(); + if(tiles->sections[sec].values["NonMarbleMadness"].GetLength()>0) + bMadness=TRUE; + auto tilesetAnimSection = tiles->GetSection(tiles->sections[sec].GetValueByName("SetName")); + + tilesets_start[i]=tilecount; + + + for(e=0;esections[sec].values["TilesInSet"]);e++) + { + std::string sId = std::format("{:02}", e + 1); + CString filename=tiles->sections[sec].values["FileName"]; + filename+=sId.c_str(); + + CString bas_f=filename; + + CString suffix; + + if(tiles==&tiles_t) suffix =".tem"; + if(tiles==&tiles_s) suffix =".sno"; + if(tiles==&tiles_u) suffix =".urb"; + if(tiles==&tiles_un) suffix =".ubn"; + if(tiles==&tiles_l) suffix =".lun"; + if(tiles==&tiles_d) suffix =".des"; + + filename += suffix; + HTSPALETTE hPalette=m_hPalIsoTemp; + if(tiles==&tiles_s) hPalette=m_hPalIsoSnow; + if(tiles==&tiles_u) hPalette=m_hPalIsoUrb; + if(tiles==&tiles_t) hPalette=m_hPalIsoTemp; + if(tiles==&tiles_un) hPalette=m_hPalIsoUbn; + if(tiles==&tiles_d) hPalette=m_hPalIsoDes; + if(tiles==&tiles_l) hPalette=m_hPalIsoLun; + + // MW add: use other... + if(FindFileInMix(filename)==NULL && tiles==&tiles_un) { filename=bas_f+".urb"; hPalette=m_hPalIsoUrb; } + if(FindFileInMix(filename)==NULL) { filename=bas_f+".tem"; hPalette=m_hPalIsoTemp; } + + (*tiledata)[tilecount].bAllowTiberium=bTib; + (*tiledata)[tilecount].bAllowToPlace=bPlace; + (*tiledata)[tilecount].bMorphable=bMorph; + (*tiledata)[tilecount].bMarbleMadness=bMadness; + (*tiledata)[tilecount].wTileSet=i; + + int reps; + for(reps=0;reps<5;reps++) + { + CString r_filename=filename; + + if(reps>0) + { + char c[3]; + c[0]='a'+reps-1; + c[1]='.'; + c[2]=0; + + r_filename.Replace(".", c); + + if(!LoadTile(r_filename, FindFileInMix(filename), hPalette, tilecount, TRUE)) + break; + } + else + { + LoadTile(filename, FindFileInMix(filename), hPalette, tilecount, FALSE); + } + } + + if (tilesetAnimSection) + { + auto anim = tilesetAnimSection->GetValueByName(std::format("Tile{}Anim", sId).c_str()); + auto offsetX = std::atoi(tilesetAnimSection->GetValueByName(std::format("Tile{}XOffset", sId).c_str())); + auto offsetY = std::atoi(tilesetAnimSection->GetValueByName(std::format("Tile{}YOffset", sId).c_str())); + auto attachesTo = std::atoi(tilesetAnimSection->GetValueByName(std::format("Tile{}AttachesTo", sId).c_str())); + auto animFileName = anim + suffix; + HMIXFILE hAnimMix = FindFileInMix(animFileName); + if (hAnimMix) + { + auto& tile = (*tiledata)[tilecount]; + if (tile.wTileCount <= attachesTo) + { + ASSERT(tile.wTileCount > attachesTo); + } + else + { + auto& subtile = tile.tiles[attachesTo]; + SHPHEADER shp_h; + SHPIMAGEHEADER shpi_h; + auto animPic = std::make_shared(); + auto rawPic = std::make_shared>(); + animPic->rawPic = rawPic; + FSunPackLib::SetCurrentSHP(animFileName, hAnimMix); + FSunPackLib::XCC_GetSHPHeader(&shp_h); + int imageNum = 1; + FSunPackLib::XCC_GetSHPImageHeader(1, &shpi_h); + if (shpi_h.unknown == 0) + { + // shadow + imageNum = 0; + } + FSunPackLib::XCC_GetSHPImageHeader(imageNum, &shpi_h); + if (FSunPackLib::LoadSHPImage(imageNum, *rawPic)) + { + subtile.anim = animPic; + animPic->pic = animPic->rawPic->data(); + animPic->bType = PICDATA_TYPE_SHP; + animPic->pal = iPalIso; + animPic->wWidth = animPic->wMaxWidth = shp_h.cx; + animPic->wHeight = animPic->wMaxHeight = shp_h.cy; + animPic->x = offsetX; + animPic->y = offsetY; + animPic->createVBorder(); + } + } + } + } + + tilecount++; + if(prog!=NULL /*&& tilecount%15==0*/) + { + prog->SetPos(tilecount); + prog->UpdateWindow(); + } + } + + + } + + tilecount=0; + for(i=0;i<10000;i++) + { + CString tset; + char c[50]; + itoa(i, c, 10); + int e; + for(e=0;e<4-strlen(c);e++) + tset+="0"; + tset+=c; + CString sec="TileSet"; + sec+=tset; + + if(tiles->sections.find(sec)==tiles->sections.end()) break; + + + int madnessid=atoi(tiles->sections[sec].values["MarbleMadness"]); + + for(e=0;esections[sec].values["TilesInSet"]);e++) + { + if(madnessid) + { + (*tiledata)[tilecount].wMarbleGround=tilesets_start[madnessid]+(tilecount-tilesets_start[i]); + } + else + (*tiledata)[tilecount].wMarbleGround=0xFFFF; + + tilecount++; + + } + + + } + +} + +#ifdef NOSURFACES // first version, using palettized (or extracted) data +BOOL CLoading::LoadTile(LPCSTR lpFilename, HMIXFILE hOwner, HTSPALETTE hPalette, DWORD dwID, BOOL bReplacement) +{ + last_succeeded_operation=12; + + + int tileCount; + + if(FSunPackLib::XCC_DoesFileExist(lpFilename, hOwner)) + { + FSunPackLib::SetCurrentTMP(lpFilename, hOwner); + { + + //FSunPackLib::SetCurrentTMP((CString)AppPath+"\\TmpTmp.tmp"/* lpFilename*/, NULL/*hOwner*/); + int tileWidth, tileHeight; + RECT rect; + FSunPackLib::XCC_GetTMPInfo(&rect, &tileCount, &tileWidth, &tileHeight); + + + BYTE** pics=new(BYTE*[tileCount]); + + if(FSunPackLib::LoadTMPImage(0, tileCount, pics)) // be aware this allocates memory! + //if(FSunPackLib::LoadTMPImageInSurface(v.dd,lpFilename, 0, tileCount, pics, hPalette, hOwner)) + { + TILEDATA* td; + if(!bReplacement) td=&(*tiledata)[dwID]; + else + { + + TILEDATA* lpTmp=NULL; + if((*tiledata)[dwID].bReplacementCount) + { + lpTmp=new(TILEDATA[(*tiledata)[dwID].bReplacementCount]); + memcpy(lpTmp, (*tiledata)[dwID].lpReplacements, sizeof(TILEDATA)* (*tiledata)[dwID].bReplacementCount); + } + + (*tiledata)[dwID].lpReplacements=new(TILEDATA[(*tiledata)[dwID].bReplacementCount+1]); + + if((*tiledata)[dwID].bReplacementCount) + { + memcpy((*tiledata)[dwID].lpReplacements, lpTmp, sizeof(TILEDATA)*(*tiledata)[dwID].bReplacementCount); + delete[] lpTmp; + } + + td=&(*tiledata)[dwID].lpReplacements[(*tiledata)[dwID].bReplacementCount]; + (*tiledata)[dwID].bReplacementCount++; + } + + + td->tiles=new(SUBTILE[tileCount]); + td->wTileCount=tileCount; + td->cx=tileWidth; + td->cy=tileHeight; + td->rect=rect; + + int i; + for(i=0;itiles[i].rgbLeft, &td->tiles[i].rgbRight); + + td->tiles[i].pic=pics[i]; + td->tiles[i].sX=p.x; + td->tiles[i].sY=p.y; + td->tiles[i].wWidth=cx; + td->tiles[i].wHeight=cy; + td->tiles[i].bZHeight=height; + td->tiles[i].bTerrainType=terraintype; + td->tiles[i].bHackedTerrainType=terraintype; + td->tiles[i].bDirection=direction; + + td->tiles[i].vborder=new(VBORDER[cy]); + + int k; + int size=0; + BOOL TranspInside=FALSE; + for(k=0;ktiles[i].vborder[k].left=l; + td->tiles[i].vborder[k].right=r; + + if(r>=l) + size+=r-l+1; + } + +#ifdef NOSURFACES_EXTRACT + + if(!TranspInside) + { + // extract the palette data! + td->tiles[i].bNotExtracted=FALSE; + td->tiles[i].pic=new(BYTE[size*bpp]); + int l; + int pos=0; + for(k=0;ktiles[i].vborder[k].left; + right=td->tiles[i].vborder[k].right; + for(l=left;l<=right;l++) + { + memcpy(&td->tiles[i].pic[pos], &iPalIso[pics[i][l+k*cx]], bpp); + pos+=bpp; + } + } + delete[] pics[i]; + } + else + td->tiles[i].bNotExtracted=TRUE; +#endif + + + if(terraintype==0xa) + { +#ifdef RA2_MODE + td->tiles[i].bHackedTerrainType=TERRAINTYPE_WATER; +#else + td->tiles[i].bHackedTerrainType=TERRAINTYPE_WATER; +#endif + } + if(terraintype==TERRAINTYPE_ROUGH) td->tiles[i].bHackedTerrainType=TERRAINTYPE_GROUND; + + //if((*tiledata)[dwID].wTileSet==waterset) (*tiledata)[dwID].tiles[i].bHackedTerrainType=TERRAINTYPE_WATER; + + // shore hack: check fsdata.ini for new shore terrain + if(td->wTileSet==shoreset) + { + int h; + for(h=0;h<(*tiledata_count);h++) + { + if((*tiledata)[h].wTileSet==shoreset) break; + } + + int pos=dwID-h; + char c[50]; + itoa(pos,c,10); + CString hack=c; + hack+="_"; + itoa(i, c, 10); + hack+=c;/* + hack+="_"; + itoa(i/tileWidth, c, 10); + hack+=c;*/ + + CString section="ShoreTerrainTS"; +#ifdef RA2_MODE + section="ShoreTerrainRA2"; +#endif + + if(g_data.sections[section].FindName(hack)>=0) + { + int t=atoi(g_data.sections[section].values[hack]); + if(t) td->tiles[i].bHackedTerrainType=TERRAINTYPE_WATER; + else + td->tiles[i].bHackedTerrainType=0xe; + } + } + if((*tiledata)[dwID].wTileSet==waterset) (*tiledata)[dwID].tiles[i].bHackedTerrainType=TERRAINTYPE_WATER; + } + else + { + td->tiles[i].pic=NULL; + td->tiles[i].sX=0; + td->tiles[i].sY=0; + td->tiles[i].wWidth=0; + td->tiles[i].wHeight=0; + td->tiles[i].bZHeight=0; + td->tiles[i].bTerrainType=0; + td->tiles[i].bDirection=0; + td->tiles[i].vborder=NULL; + + } + } + } + + if(tileCount>0) delete[] pics; + } + } + else + { + errstream << lpFilename << " not found" << endl; + return FALSE; + } + + + + + + return TRUE; + + +} +#else // now standard version, with surfaces +BOOL CLoading::LoadTile(LPCSTR lpFilename, HMIXFILE hOwner, HTSPALETTE hPalette, DWORD dwID, BOOL bReplacement) +{ + last_succeeded_operation=12; + + //errstream << "Loading " << lpFilename << " owned by " << hOwner << ", palette " << hPalette ; + //errstream << lpFilename << endl; + //errstream.flush(); + + CIsoView& v=*((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; + + + //DeleteFile((CString)AppPath+(CString)"\\TmpTmp.tmp"); + //FSunPackLib::XCC_ExtractFile(lpFilename, (CString)AppPath+(CString)"\\TmpTmp.tmp" /*lpFilename*//*, hOwner); + + int tileCount; + try{ + if(FSunPackLib::XCC_DoesFileExist(lpFilename, hOwner)) + //if(DoesFileExist((CString)AppPath+(CString)"\\TmpTmp.tmp")) + { + //if( + FSunPackLib::SetCurrentTMP(lpFilename, hOwner); + //) + { + + //FSunPackLib::SetCurrentTMP((CString)AppPath+"\\TmpTmp.tmp"/* lpFilename*//*, NULL/*hOwner*//*); + int tileWidth, tileHeight; + RECT rect; + FSunPackLib::XCC_GetTMPInfo(&rect, &tileCount, &tileWidth, &tileHeight); + + + LPDIRECTDRAWSURFACE4* pics=new(LPDIRECTDRAWSURFACE4[tileCount]); + if(FSunPackLib::LoadTMPImageInSurface(v.dd,0, tileCount, pics, hPalette)) + //if(FSunPackLib::LoadTMPImageInSurface(v.dd,lpFilename, 0, tileCount, pics, hPalette, hOwner)) + { + TILEDATA* td; + if(!bReplacement) td=&(*tiledata)[dwID]; + else + { + + TILEDATA* lpTmp=NULL; + if((*tiledata)[dwID].bReplacementCount) + { + lpTmp=new(TILEDATA[(*tiledata)[dwID].bReplacementCount]); + memcpy(lpTmp, (*tiledata)[dwID].lpReplacements, sizeof(TILEDATA)* (*tiledata)[dwID].bReplacementCount); + } + + (*tiledata)[dwID].lpReplacements=new(TILEDATA[(*tiledata)[dwID].bReplacementCount+1]); + + if((*tiledata)[dwID].bReplacementCount) + { + memcpy((*tiledata)[dwID].lpReplacements, lpTmp, sizeof(TILEDATA)*(*tiledata)[dwID].bReplacementCount); + delete[] lpTmp; + } + + td=&(*tiledata)[dwID].lpReplacements[(*tiledata)[dwID].bReplacementCount]; + (*tiledata)[dwID].bReplacementCount++; + } + + + td->tiles=new(SUBTILE[tileCount]); + td->wTileCount=tileCount; + td->cx=tileWidth; + td->cy=tileHeight; + td->rect=rect; + + int i; + for(i=0;itiles[i].rgbLeft, &td->tiles[i].rgbRight); + td->tiles[i].pic=pics[i]; + td->tiles[i].sX=p.x; + td->tiles[i].sY=p.y; + td->tiles[i].wWidth=cx; + td->tiles[i].wHeight=cy; + td->tiles[i].bZHeight=height; + td->tiles[i].bTerrainType=terraintype; + td->tiles[i].bHackedTerrainType=terraintype; + td->tiles[i].bDirection=direction; + + if(terraintype==0xa) + { +#ifdef RA2_MODE + td->tiles[i].bHackedTerrainType=TERRAINTYPE_WATER; +#else + td->tiles[i].bHackedTerrainType=TERRAINTYPE_WATER; +#endif + } + if(terraintype==TERRAINTYPE_ROUGH) td->tiles[i].bHackedTerrainType=TERRAINTYPE_GROUND; + + //if((*tiledata)[dwID].wTileSet==waterset) (*tiledata)[dwID].tiles[i].bHackedTerrainType=TERRAINTYPE_WATER; + + // shore hack: check fsdata.ini for new shore terrain + if(td->wTileSet==shoreset) + { + int h; + for(h=0;h<(*tiledata_count);h++) + { + if((*tiledata)[h].wTileSet==shoreset) break; + } + + int pos=dwID-h; + char c[50]; + itoa(pos,c,10); + CString hack=c; + hack+="_"; + itoa(i, c, 10); + hack+=c;/* + hack+="_"; + itoa(i/tileWidth, c, 10); + hack+=c;*/ + + CString section="ShoreTerrainTS"; +#ifdef RA2_MODE + section="ShoreTerrainRA2"; +#endif + + if(g_data.sections[section].FindName(hack)>=0) + { + int t=atoi(g_data.sections[section].values[hack]); + if(t) td->tiles[i].bHackedTerrainType=TERRAINTYPE_WATER; + else + td->tiles[i].bHackedTerrainType=0xe; + } + } + if((*tiledata)[dwID].wTileSet==waterset) (*tiledata)[dwID].tiles[i].bHackedTerrainType=TERRAINTYPE_WATER; + } + else + { + td->tiles[i].pic=NULL; + td->tiles[i].sX=0; + td->tiles[i].sY=0; + td->tiles[i].wWidth=0; + td->tiles[i].wHeight=0; + td->tiles[i].bZHeight=0; + td->tiles[i].bTerrainType=0; + td->tiles[i].bDirection=0; + } + } + } + + if(tileCount>0) delete[] pics; + } + } + else + { + //errstream << " not found" << endl; + return FALSE; + } + } + catch(...) + { + + } + + if((*tiledata)[dwID].wTileCount==0 || (*tiledata)[dwID].tiles[0].pic==NULL) + { + //errstream << " failed" << endl; + //errstream.flush(); + + return FALSE; + } + else + { + //errstream << " succeeded" << endl; + //errstream.flush(); + } + + return TRUE; + + +} +#endif + +#ifdef NOSURFACES_OBJECTS // palettized +void CLoading::LoadOverlayGraphic(LPCTSTR lpOvrlName_, int iOvrlNum) +{ + last_succeeded_operation=11; + + CString image; // the image used + CString filename; // filename of the image + SHPHEADER head; + char theat=cur_theat; + BYTE** lpT=NULL; + + char OvrlID[50]; + itoa(iOvrlNum, OvrlID, 10); + + HTSPALETTE hPalette = m_hPalIsoTemp; + if(cur_theat=='T') + { + hPalette=m_hPalIsoTemp; + #ifdef RA2_MODE + hPalette=m_hPalIsoTemp; + #endif + } + if(cur_theat=='A') + { + hPalette=m_hPalIsoSnow; + #ifdef RA2_MODE + hPalette=m_hPalIsoSnow; + #endif + } + if(cur_theat=='U' && m_hPalIsoUrb) + { + hPalette=m_hPalIsoUrb; + #ifdef RA2_MODE + hPalette=m_hPalIsoUrb; + #endif + } + if(cur_theat=='N' && m_hPalIsoUbn) + { + hPalette=m_hPalIsoUbn; + #ifdef RA2_MODE + hPalette=m_hPalIsoUbn; + #endif + } + if(cur_theat=='L' && m_hPalIsoLun) + { + hPalette=m_hPalIsoLun; + #ifdef RA2_MODE + hPalette=m_hPalIsoLun; + #endif + } + if(cur_theat=='D' && m_hPalIsoDes) + { + hPalette=m_hPalIsoDes; + #ifdef RA2_MODE + hPalette=m_hPalIsoDes; + #endif + } + + HTSPALETTE forcedPalette = 0; + const auto& isoPalettePrefixes = g_data.sections["ForceOvrlIsoPalettePrefix"]; + const auto& unitPalettePrefixes = g_data.sections["ForceOvrlUnitPalettePrefix"]; + const CString sOvrlName(lpOvrlName_); + if (unitPalettePrefixes.end() != std::find_if(unitPalettePrefixes.begin(), unitPalettePrefixes.end(), [&sOvrlName](const auto& pair) {return sOvrlName.Find(pair.second) == 0;})) + { + forcedPalette = GetUnitPalette(cur_theat); + } + if (isoPalettePrefixes.end() != std::find_if(isoPalettePrefixes.begin(), isoPalettePrefixes.end(), [&sOvrlName](const auto& pair) {return sOvrlName.Find(pair.second) == 0;})) + { + forcedPalette = GetIsoPalette(cur_theat); + } + + HMIXFILE hMix; + + CString lpOvrlName = lpOvrlName_; + if(lpOvrlName.Find(' ')>=0) lpOvrlName = lpOvrlName.Left(lpOvrlName.Find(' ')); + //if(strchr(lpOvrlName, ' ')!=NULL) strchr(lpOvrlName, ' ')[0]=0; + //if(lpOvrlName + + CString isveinhole_t=rules.sections[lpOvrlName].values["IsVeinholeMonster"]; + CString istiberium_t=rules.sections[lpOvrlName].values["Tiberium"]; + CString isveins_t=rules.sections[lpOvrlName].values["IsVeins"]; + isveinhole_t.MakeLower(); + istiberium_t.MakeLower(); + isveins_t.MakeLower(); + BOOL isveinhole=FALSE, istiberium=FALSE, isveins=FALSE; + if(isTrue(isveinhole_t)) isveinhole=TRUE; + if(isTrue(istiberium_t)) istiberium=TRUE; + if(isTrue(isveins_t)) isveins=TRUE; + + + + + + image=lpOvrlName; + if(rules.sections[lpOvrlName].values.find("Image")!=rules.sections[lpOvrlName].values.end()) + image=rules.sections[lpOvrlName].values["Image"]; + + TruncSpace(image); + + CString imagerules=image; + if(art.sections[image].values.find("Image")!=art.sections[image].values.end()) + image=art.sections[image].values["Image"]; + + TruncSpace(image); + + if(cur_theat=='T') filename=image+".tem"; + if(cur_theat=='A') filename=image+".sno"; + if(cur_theat=='U') filename=image+".urb"; + if(cur_theat=='N') filename=image+".ubn"; + if(cur_theat=='L') filename=image+".lun"; + if(cur_theat=='D') filename=image+".des"; + + + hMix=FindFileInMix(filename); + + const auto& artSection = art.sections[image]; + + if(hMix==NULL) + { + filename=image+".shp"; + if(isTrue(artSection.GetValueByName("NewTheater"))) + filename.SetAt(1, theat); + + if(cur_theat=='U' && m_hPalUnitUrb) hPalette=m_hPalUnitUrb; + if(cur_theat=='T') hPalette=m_hPalUnitTemp; + if(cur_theat=='A') hPalette=m_hPalUnitSnow; + if(cur_theat=='N') hPalette=m_hPalUnitUbn; + if(cur_theat=='L') hPalette=m_hPalUnitLun; + if(cur_theat=='D') hPalette=m_hPalUnitDes; + + hMix=FindFileInMix(filename); + + //errstream << (LPCSTR)filename << " " << endl; + //errstream.flush(); + + if(hMix==NULL) + { + filename.SetAt(1, 'T'); + hMix=FindFileInMix(filename); + } + if(hMix==NULL) + { + filename.SetAt(1, 'A'); + hMix=FindFileInMix(filename); + } + if(hMix==NULL) + { + filename.SetAt(1, 'U'); + hMix=FindFileInMix(filename); + } + if(hMix==NULL) + { + filename.SetAt(1, 'N'); + hMix=FindFileInMix(filename); + } + if(hMix==NULL) + { + filename.SetAt(1, 'L'); + hMix=FindFileInMix(filename); + } + if(hMix==NULL) + { + filename.SetAt(1, 'D'); + hMix=FindFileInMix(filename); + } + + if(cur_theat=='T' || cur_theat=='U') + { + hPalette=m_hPalUnitTemp; + } + else + hPalette=m_hPalUnitSnow; + + } + + if(hMix==NULL) + { + filename=image+".tem"; + hMix=FindFileInMix(filename); + if(hMix) hPalette=m_hPalIsoTemp; + } + if(hMix==NULL) + { + filename=image+".sno"; + hMix=FindFileInMix(filename); + if(hMix) hPalette=m_hPalIsoSnow; + } + if(hMix==NULL) + { + filename=image+".urb"; + hMix=FindFileInMix(filename); + if(hMix && m_hPalIsoUrb) hPalette=m_hPalIsoUrb; + } + if(hMix==NULL) + { + filename=image+".ubn"; + hMix=FindFileInMix(filename); + if(hMix && m_hPalIsoUbn) hPalette=m_hPalIsoUbn; + } + if(hMix==NULL) + { + filename=image+".lun"; + hMix=FindFileInMix(filename); + if(hMix && m_hPalIsoLun) hPalette=m_hPalIsoLun; + } + if(hMix==NULL) + { + filename=image+".des"; + hMix=FindFileInMix(filename); + if(hMix && m_hPalIsoDes) hPalette=m_hPalIsoDes; + } + + if(isveinhole==TRUE || isveins==TRUE || istiberium==TRUE) + { + hPalette=m_hPalTemp; +#ifndef RA2_MODE + hPalette=m_hPalUnitTemp; +#endif + } + + hPalette = forcedPalette ? forcedPalette : hPalette; + + + if(hMix!=NULL) + { + + errstream << "Overlay: " << (LPCSTR) filename << endl; + errstream.flush(); + + FSunPackLib::SetCurrentSHP(filename, hMix); + { + + FSunPackLib::XCC_GetSHPHeader(&head); + + int i; + int maxPics=head.c_images; + if(maxPics>max_ovrl_img) maxPics=max_ovrl_img; + + + // create an array of pointers to directdraw surfaces + lpT=new(BYTE*[maxPics]); + memset(lpT, 0, sizeof(BYTE)*maxPics); + + // if tiberium, change color + BOOL bIsBlueTib=FALSE; + BOOL bIsGreenTib=FALSE; + RGBTRIPLE rgbOld[16], rgbNew; + #ifndef RA2_MODE + if(istiberium) + { + if(lpOvrlName[4]=='_') // other than green! + bIsBlueTib=TRUE; + else + bIsGreenTib=TRUE; + + + + int i; + for(i=0;i<16;i++) + { + if(bIsGreenTib) + { + rgbNew.rgbtBlue=0; + if(i!=0) + rgbNew.rgbtGreen=255-i*16+1; + else + rgbNew.rgbtGreen=255; + rgbNew.rgbtRed=0; + } + else if(bIsBlueTib) + { + if(i!=0) + rgbNew.rgbtBlue=255-i*16+1; + else + rgbNew.rgbtBlue=255; + rgbNew.rgbtGreen=0; + rgbNew.rgbtRed=0; // change green/blue (not RGB but BGR) + } + + int rb=rgbNew.rgbtBlue; + int rr=rgbNew.rgbtRed; + + FSunPackLib::SetTSPaletteEntry(hPalette, 0x10+i, &rgbNew, &rgbOld[i]); + } + } + #endif + + FSunPackLib::LoadSHPImage(0, maxPics, lpT); + + #ifndef RA2_MODE + if(istiberium) + for(i=0;i<16;i++) + FSunPackLib::SetTSPaletteEntry(hPalette, 0x10+i, &rgbOld[i], NULL); + #endif + + for(i=0; im_view.m_isoview; + + CString lpOvrlName = lpOvrlName_; + if (lpOvrlName.Find(' ') >= 0) lpOvrlName = lpOvrlName.Left(lpOvrlName.Find(' ')); + + CString isveinhole_t=rules.sections[lpOvrlName].values["IsVeinholeMonster"]; + CString istiberium_t=rules.sections[lpOvrlName].values["Tiberium"]; + CString isveins_t=rules.sections[lpOvrlName].values["IsVeins"]; + isveinhole_t.MakeLower(); + istiberium_t.MakeLower(); + isveins_t.MakeLower(); + BOOL isveinhole=FALSE, istiberium=FALSE, isveins=FALSE; + if(isTrue(isveinhole_t)) isveinhole=TRUE; + if(isTrue(istiberium_t)) istiberium=TRUE; + if(isTrue(isveins_t)) isveins=TRUE; + + + + + + image=lpOvrlName; + if(rules.sections[lpOvrlName].values.find("Image")!=rules.sections[lpOvrlName].values.end()) + image=rules.sections[lpOvrlName].values["Image"]; + + TruncSpace(image); + + CString imagerules=image; + if(art.sections[image].values.find("Image")!=art.sections[image].values.end()) + image=art.sections[image].values["Image"]; + + TruncSpace(image); + + if(cur_theat=='T') filename=image+".tem"; + if(cur_theat=='A') filename=image+".sno"; + if(cur_theat=='U') filename=image+".urb"; + + + hMix=FindFileInMix(filename); + + + if(hMix==NULL) + { + filename=image+".shp"; + if(isTrue(art.sections[image].values["NewTheater"])) + filename.SetAt(1, theat); + + if(cur_theat=='U' && m_hPalUnitUrb) hPalette=m_hPalUnitUrb; + if(cur_theat=='T') hPalette=m_hPalUnitTemp; + if(cur_theat=='A') hPalette=m_hPalUnitSnow; + + hMix=FindFileInMix(filename); + + // errstream << (LPCSTR)filename << " " << hMix; + + if(hMix==NULL) + { + filename.SetAt(1, 'T'); + hMix=FindFileInMix(filename); + } + if(hMix==NULL) + { + filename.SetAt(1, 'A'); + hMix=FindFileInMix(filename); + } + if(hMix==NULL) + { + filename.SetAt(1, 'U'); + hMix=FindFileInMix(filename); + } + + if(cur_theat=='T' || cur_theat=='U') + { + hPalette=m_hPalUnitTemp; + } + else + hPalette=m_hPalUnitSnow; + + } + + if(hMix==NULL) + { + filename=image+".tem"; + hMix=FindFileInMix(filename); + if(hMix) hPalette=m_hPalIsoTemp; + } + if(hMix==NULL) + { + filename=image+".sno"; + hMix=FindFileInMix(filename); + if(hMix) hPalette=m_hPalIsoSnow; + } + if(hMix==NULL) + { + filename=image+".urb"; + hMix=FindFileInMix(filename); + if(hMix && m_hPalIsoUrb) hPalette=m_hPalIsoUrb; + } + + if(isveinhole==TRUE || isveins==TRUE || istiberium==TRUE) + { + hPalette=m_hPalTemp; +#ifndef RA2_MODE + hPalette=m_hPalUnitTemp; +#endif + } + + if(hMix!=NULL) + { + + FSunPackLib::SetCurrentSHP(filename, hMix); + { + + FSunPackLib::XCC_GetSHPHeader(&head); + + int i; + int maxPics=head.c_images; + if(maxPics>max_ovrl_img) maxPics=max_ovrl_img; // max may_ovrl_img pictures (memory usage!) + //errstream << ", loading " << maxPics << " of " << head.c_images << " pictures. "; + //errstream.flush(); + + + // create an array of pointers to directdraw surfaces + lpT=new(LPDIRECTDRAWSURFACE4[maxPics]); + memset(lpT, 0, sizeof(LPDIRECTDRAWSURFACE4)*maxPics); + + // if tiberium, change color + BOOL bIsBlueTib=FALSE; + BOOL bIsGreenTib=FALSE; + RGBTRIPLE rgbOld[16], rgbNew; + #ifndef RA2_MODE + if(istiberium) + { + if(lpOvrlName[4]=='_') // other than green! + bIsBlueTib=TRUE; + else + bIsGreenTib=TRUE; + + + + int i; + for(i=0;i<16;i++) + { + if(bIsGreenTib) + { + rgbNew.rgbtBlue=0; + if(i!=0) + rgbNew.rgbtGreen=255-i*16+1; + else + rgbNew.rgbtGreen=255; + rgbNew.rgbtRed=0; + } + else if(bIsBlueTib) + { + if(i!=0) + rgbNew.rgbtBlue=255-i*16+1; + else + rgbNew.rgbtBlue=255; + rgbNew.rgbtGreen=0; + rgbNew.rgbtRed=0; + } + + FSunPackLib::SetTSPaletteEntry(hPalette, 0x10+i, &rgbNew, &rgbOld[i]); + } + } + #endif + + FSunPackLib::LoadSHPImageInSurface(v.dd, hPalette, 0, maxPics, lpT); + + #ifndef RA2_MODE + if(istiberium) + for(i=0;i<16;i++) + FSunPackLib::SetTSPaletteEntry(hPalette, 0x10+i, &rgbOld[i], NULL); + #endif + + for(i=0; iRelease(); + + if(imghead.unknown && lpT[i]) + { + char ic[50]; + itoa(i, ic, 10); + + PICDATA p; + p.pic=lpT[i]; + p.x=imghead.x; + p.y=imghead.y; + + p.wHeight=imghead.cy; + p.wWidth=imghead.cx; + p.wMaxWidth=head.cx; + p.wMaxHeight=head.cy; + p.bType=PICDATA_TYPE_SHP; + + + + pics[(CString)"OVRL"+ OvrlID + "_" + ic]=p; + } + } + + + delete[] lpT; + + //errstream << " --> Finished" << endl; + //errstream.flush(); + } + /*else + { + errstream << " failed"; + errstream.flush(); + }*/ + } + + else + { + //errstream << "File not found: " << (LPCTSTR)filename << endl; + //errstream.flush(); + } + + int i; + for(i=0; i<0xFF; i++) + { + char ic[50]; + itoa(i, ic, 10); + + pics[(CString)"OVRL"+ OvrlID + "_" + ic].bTried=TRUE; + } + + +} +#endif + +void CLoading::OnDestroy() +{ + CDialog::OnDestroy(); +} + +void CLoading::InitVoxelNormalTables() +{ + try + { + std::ifstream f(std::string(AppPath) + "\\voxel_normal_tables.bin", std::ios::binary); + m_voxelNormalTables.reset(new VoxelNormalTables(f)); + } + catch (const std::runtime_error& e) + { + errstream << e.what() << std::endl; + m_voxelNormalTables.reset(new VoxelNormalTables()); + } +} + +void CLoading::CalcPicCount() +{ + m_pic_count=0; + + CString bmps=(CString)AppPath+"\\pics\\*.bmp"; + if(!theApp.m_Options.bDoNotLoadBMPs) + { + CFileFind ff; + if(ff.FindFile(bmps)) + { + // found bmp + m_pic_count++; + while(ff.FindNextFile()) m_pic_count++; + } + } + + m_bmp_count=m_pic_count; + + if(!theApp.m_Options.bDoNotLoadVehicleGraphics) m_pic_count+=rules.sections["VehicleTypes"].values.size(); + if(!theApp.m_Options.bDoNotLoadOverlayGraphics) m_pic_count+=rules.sections["OverlayTypes"].values.size(); + if(!theApp.m_Options.bDoNotLoadInfantryGraphics) m_pic_count+=rules.sections["InfantryTypes"].values.size(); + if(!theApp.m_Options.bDoNotLoadBuildingGraphics) m_pic_count+=rules.sections["BuildingTypes"].values.size(); + if(!theApp.m_Options.bDoNotLoadAircraftGraphics) m_pic_count+=rules.sections["AircraftTypes"].values.size(); + if(!theApp.m_Options.bDoNotLoadTreeGraphics) m_pic_count+=rules.sections["TerrainTypes"].values.size(); + + int i; +/* + if(!theApp.m_Options.bDoNotLoadSnowGraphics) + { + tiledata=&s_tiledata; + tiles=&tiles_s; + tiledata_count=&s_tiledata_count; + for(i=0;i<10000;i++) + { + CString tset; + char c[50]; + itoa(i, c, 10); + int e; + for(e=0;e<4-strlen(c);e++) + tset+="0"; + tset+=c; + CString sec="TileSet"; + sec+=tset; + + if(tiles->sections.find(sec)==tiles->sections.end()) break; + + for(e=0;esections[sec].values["TilesInSet"]);e++) + { + m_pic_count++; + } + + } + } + + if(!theApp.m_Options.bDoNotLoadTemperateGraphics) + { + tiledata=&t_tiledata; + tiles=&tiles_t; + tiledata_count=&t_tiledata_count; + for(i=0;i<10000;i++) + { + CString tset; + char c[50]; + itoa(i, c, 10); + int e; + for(e=0;e<4-strlen(c);e++) + tset+="0"; + tset+=c; + CString sec="TileSet"; + sec+=tset; + + if(tiles->sections.find(sec)==tiles->sections.end()) break; + + for(e=0;esections[sec].values["TilesInSet"]);e++) + { + m_pic_count++; + } + + } + }*/ +} + + +BOOL CLoading::InitDirectDraw() +{ + last_succeeded_operation=7; + + errstream << "\n\nDirectDrawCreate() will be called now\n"; + errstream.flush(); + + CIsoView& v=*((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; + if(DirectDrawCreate(NULL, &v.dd_1, NULL)!=DD_OK) + { + errstream << "DirectDrawCreate() failed\n"; + errstream.flush(); + ShowWindow(SW_HIDE); + MessageBox("DirectDraw could not be initialized! Quitting..."); + exit(-1); + + return FALSE; + } + + errstream << "DirectDrawCreate() successful\n\n"; + errstream.flush(); + + if(m_progress.m_hWnd) m_progress.SetPos(1); + if(m_hWnd) UpdateWindow(); + + errstream << "Now querying the DirectX 7 or 6 interface\n"; + errstream.flush(); + + if(v.dd_1->QueryInterface(IID_IDirectDraw7, (void**)&v.dd)!=DD_OK) + { + errstream << "QueryInterface() failed -> Using DirectX 6.0\n"; + errstream.flush(); + //ShowWindow(SW_HIDE); + //MessageBox("You don´t have DirectX 6.0 but an older version. Quitting..."); + //exit(-1); + + //return FALSE; + + if(v.dd_1->QueryInterface(IID_IDirectDraw4, (void**)&v.dd)!=DD_OK) + { + MessageBox("You need at least DirectX 6.0 to run this program", "Error"); + exit(-1); + return FALSE; + } + } + + errstream << "QueryInterface() successful\n\nNow setting cooperative level\n"; + errstream.flush(); + + if(v.dd->SetCooperativeLevel(v.m_hWnd, DDSCL_NORMAL | DDSCL_NOWINDOWCHANGES )!=DD_OK) + { + errstream << "SetCooperativeLevel() failed\n"; + errstream.flush(); + ShowWindow(SW_HIDE); + MessageBox("Cooperative Level could not be set! Quitting..."); + v.dd->Release(); + v.dd=NULL; + exit(-2); + + return FALSE; + } + + errstream << "SetCooperativeLevel() successful\n\nCreating primary surface\n"; + errstream.flush(); + + + if(m_progress.m_hWnd) m_progress.SetPos(2); + if(m_hWnd) UpdateWindow(); + + DDSURFACEDESC2 ddsd; + + + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize=sizeof(DDSURFACEDESC2); + ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE ; + ddsd.dwFlags=DDSD_CAPS ; + + + + int res=0; + int trycount=0; + do + { + res=v.dd->CreateSurface(&ddsd, &v.lpds, NULL); + errstream << "Return code: " << res << endl; + errstream.flush(); + + //if(res!=DD_OK && (res!=DDERR_PRIMARYSURFACEALREADYEXISTS || trycount>100)) + if(res!=DD_OK && trycount>=300) + { + + errstream << "CreateSurface() failed\n"; + + errstream.flush(); + ShowWindow(SW_HIDE); + MessageBox("Primary surface could not be initialized! Quitting..."); + v.dd->Release(); + v.dd=NULL; + exit(-3); + + return FALSE; + } + trycount++; + if(res!=DD_OK) + { + Sleep(50); + } + + + }while(res!=DD_OK); + +#ifdef NOSURFACES + DDPIXELFORMAT pf; + memset(&pf, 0, sizeof(DDPIXELFORMAT)); + pf.dwSize=sizeof(DDPIXELFORMAT); + + v.lpds->GetPixelFormat(&pf); + + if(!pf.dwBBitMask || !pf.dwRBitMask || !pf.dwGBitMask) + { + ShowWindow(SW_HIDE); + MessageBox("You must not use a palette color mode like 8 bit in order to run FinalSun/FinalAlert 2. Please check readme.txt","Error",MB_OK); + + v.lpds->Release(); + v.lpds=NULL; + v.dd->Release(); + v.dd=NULL; + exit(-3); + return FALSE; + } + bpp=(pf.dwRGBBitCount+7)/8; +#endif + + + errstream << "CreateSurface() successful\n\nCreating backbuffer surface\n"; + errstream.flush(); + + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize=sizeof(DDSURFACEDESC2); + ddsd.dwFlags=DDSD_WIDTH | DDSD_HEIGHT; + v.lpds->GetSurfaceDesc(&ddsd); + ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN; + + + ddsd.dwFlags=DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + + + if(v.dd->CreateSurface(&ddsd, &v.lpdsBack, NULL)!=DD_OK) + { + errstream << "CreateSurface() failed\n"; + errstream.flush(); + ShowWindow(SW_HIDE); + MessageBox("Backbuffer surface could not be initialized! Quitting..."); + v.lpds->Release(); + v.lpds=NULL; + v.dd->Release(); + v.dd=NULL; + exit(-4); + + return FALSE; + } + if (theApp.m_Options.bHighResUI && v.dd->CreateSurface(&ddsd, &v.lpdsBackHighRes, NULL) != DD_OK) + { + errstream << "CreateSurface() failed\n"; + errstream.flush(); + ShowWindow(SW_HIDE); + MessageBox("Highres Backbuffer surface could not be initialized! Quitting..."); + v.lpdsBack->Release(); + v.lpdsBack = NULL; + v.lpds->Release(); + v.lpds = NULL; + v.dd->Release(); + v.dd = NULL; + exit(-4); + + return FALSE; + } + if(v.dd->CreateSurface(&ddsd, &v.lpdsTemp, NULL)!=DD_OK) + { + errstream << "CreateSurface() failed\n"; + errstream.flush(); + ShowWindow(SW_HIDE); + MessageBox("Tempbuffer surface could not be initialized! Quitting..."); + v.lpdsBack->Release(); + v.lpdsBack=NULL; + if (v.lpdsBackHighRes) + v.lpdsBackHighRes->Release(); + v.lpdsBackHighRes = nullptr; + v.lpds->Release(); + v.lpds=NULL; + v.dd->Release(); + v.dd=NULL; + exit(-4); + + return FALSE; + } + + errstream << "CreateSurface() successful\n\nNow creating clipper\n"; + errstream.flush(); + + LPDIRECTDRAWCLIPPER ddc; + if(v.dd->CreateClipper(0, &ddc, NULL)!=DD_OK) + { + errstream << "CreateClipper() failed\n"; + errstream.flush(); + ShowWindow(SW_HIDE); + MessageBox("Clipper could not be created! Quitting..."); + v.lpdsTemp->Release(); + v.lpdsTemp=NULL; + v.lpdsBack->Release(); + v.lpdsBack=NULL; + if (v.lpdsBackHighRes) + v.lpdsBackHighRes->Release(); + v.lpdsBackHighRes = nullptr; + v.lpds->Release(); + v.lpds=NULL; + v.dd->Release(); + v.dd=NULL; + exit(-6); + } + + errstream << "CreateClipper() successful\n\n"; + errstream.flush(); + + v.lpds->SetClipper(ddc); + + ddc->SetHWnd(0, v.m_hWnd); + + return TRUE; +} + +void CLoading::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + CWnd* poswindow=GetDlgItem(IDC_SAVEOFTEN); + + if(!poswindow) return; + + RECT r1,r2; + poswindow->GetWindowRect(&r1); + GetWindowRect(&r2); + + dc.SetTextColor(RGB(255, 0, 0)); + dc.SetBkMode(TRANSPARENT); + + RECT dest; + dest.top=r1.bottom-r2.top-45; + dest.bottom=r1.bottom-r2.top+10; + dest.left=10; + dest.right=r1.right-r1.left+10; + + CFont f; + f.CreatePointFont(90, "Tahoma"); + dc.SelectObject(&f); + +} + +void CLoading::FreeTileSet() +{ + // free the current tileset + + int i; + for(i=0;i<(*tiledata_count);i++) + { + int e; + int z; + + // delete replacements. Replacements themself MUST NOT have replacements + for(z=0;z<(*tiledata)[i].bReplacementCount;z++) + { + TILEDATA& rept=(*tiledata)[i].lpReplacements[z]; + + for(e=0;eRelease(); +#endif + } + + delete[] rept.tiles; + rept.tiles=NULL; + rept.wTileCount=0; + rept.bReplacementCount=0; + + ASSERT(!rept.lpReplacements); // make sure we don´t have replacements for this replacement + } + + for(e=0;e<(*tiledata)[i].wTileCount;e++) + { +#ifdef NOSURFACES + BYTE* curSur=(*tiledata)[i].tiles[e].pic; + if(curSur) delete[] curSur; + if((*tiledata)[i].tiles[e].vborder) delete[] (*tiledata)[i].tiles[e].vborder; +#else + LPDIRECTDRAWSURFACE4 curSur=(*tiledata)[i].tiles[e].pic; + if(curSur) curSur->Release(); +#endif + } + + delete[] ((*tiledata)[i].tiles); + (*tiledata)[i].tiles=NULL; + (*tiledata)[i].wTileCount=0; + (*tiledata)[i].bReplacementCount=0; + if((*tiledata)[i].lpReplacements) delete[] (*tiledata)[i].lpReplacements; + (*tiledata)[i].lpReplacements=NULL; + } + if(*tiledata) delete[] (*tiledata); + (*tiledata)=NULL; + (*tiledata_count)=0; +} + +void CLoading::FreeAll() +{ + last_succeeded_operation=14; + + // MW fix: We need to set tiledata and tiledata_count to the old pointers again + int t=0; + if(tiledata==&t_tiledata) t=0; + if(tiledata==&s_tiledata) t=1; + if(tiledata==&u_tiledata) t=2; + if(tiledata==&un_tiledata) t=3; + if(tiledata==&l_tiledata) t=4; + if(tiledata==&d_tiledata) t=4; + + //try{ + tiledata=&t_tiledata; + tiledata_count=&t_tiledata_count; + FreeTileSet(); + tiledata=&s_tiledata; + tiledata_count=&s_tiledata_count; + FreeTileSet(); + tiledata=&u_tiledata; + tiledata_count=&u_tiledata_count; + FreeTileSet(); + + // MW New tilesets: + tiledata=&un_tiledata; + tiledata_count=&un_tiledata_count; + FreeTileSet(); + tiledata=&l_tiledata; + tiledata_count=&l_tiledata_count; + FreeTileSet(); + tiledata=&d_tiledata; + tiledata_count=&d_tiledata_count; + FreeTileSet(); + /* } + catch(...) + { + errstream << "Exception in FreeTileSet()" << endl; + }*/ + + // MW Reset tiledata & tiledata_count + if(t==0) { tiledata=&t_tiledata; tiledata_count=&t_tiledata_count; } + if(t==1) { tiledata=&s_tiledata; tiledata_count=&s_tiledata_count; } + if(t==2) { tiledata=&u_tiledata; tiledata_count=&u_tiledata_count; } + if(t==3) { tiledata=&un_tiledata; tiledata_count=&un_tiledata_count; } + if(t==4) { tiledata=&l_tiledata; tiledata_count=&l_tiledata_count; } + if(t==5) { tiledata=&d_tiledata; tiledata_count=&d_tiledata_count; } + + map::iterator i=pics.begin(); + for (int e=0;esecond.bType==PICDATA_TYPE_BMP) + { + if(i->second.pic!=NULL) + { + ((LPDIRECTDRAWSURFACE4)i->second.pic)->Release(); + } + } + else + { + if(i->second.pic!=NULL) + { + delete[] i->second.pic; + } + if(i->second.vborder) delete[] i->second.vborder; + } +#else + if(i->second.pic!=NULL) i->second.pic->Release(); +#endif + + i->second.pic=NULL; + } + catch(...) + { + CString err; + err="Access violation while trying to release surface "; + char c[6]; + itoa(e,c,10); + err+=c; + + err+="\n"; + OutputDebugString(err); + continue; + } + + i++; + } + + + + try{ + CFinalSunDlg* dlg=((CFinalSunDlg*)theApp.m_pMainWnd); + if(dlg->m_view.m_isoview->lpds!=NULL) dlg->m_view.m_isoview->lpds->Release(); + dlg->m_view.m_isoview->lpds=NULL; + if(dlg->m_view.m_isoview->lpdsBack!=NULL) dlg->m_view.m_isoview->lpdsBack->Release(); + dlg->m_view.m_isoview->lpdsBack=NULL; + if (dlg->m_view.m_isoview->lpdsBackHighRes != NULL) dlg->m_view.m_isoview->lpdsBackHighRes->Release(); + dlg->m_view.m_isoview->lpdsBackHighRes = NULL; + if(dlg->m_view.m_isoview->lpdsTemp!=NULL) dlg->m_view.m_isoview->lpdsTemp->Release(); + dlg->m_view.m_isoview->lpdsTemp=NULL; + if(dlg->m_view.m_isoview->dd!=NULL) dlg->m_view.m_isoview->dd->Release(); + dlg->m_view.m_isoview->dd=NULL; + if(dlg->m_view.m_isoview->dd_1!=NULL) dlg->m_view.m_isoview->dd_1->Release(); + dlg->m_view.m_isoview->dd_1=NULL; + } + catch(...) + { + errstream << "Exception while freeing DirectDraw" << endl; + } +} + +void CLoading::PostNcDestroy() +{ + +// delete this; // on stack! +// CDialog::PostNcDestroy(); +} + +void CLoading::PrepareHouses() +{ + int i; + int p=0 ; + for(i=0;i0) + { + sides[p].name=GetParam(*rules.sections["Sides"].GetValue(i), t); + sides[p].orig_n=rules.sections["Sides"].GetValueOrigPos(i); // mw fix instead of =i + t++; + p++; + } + } + + for(i=0;i AllStrings; +void CLoading::LoadStrings() +{ + last_succeeded_operation=9; + +#ifdef RA2_MODE + + // MW April 17th, 2002: + // ra2md.csf supported! + std::string file="RA2.CSF"; + if(yuri_mode) + file="RA2MD.CSF"; + + errstream << "LoadStrings() executing" << endl; + errstream.flush(); + + BYTE *lpData=NULL; + DWORD dwSize; + if(DoesFileExist((std::string(TSPath) + "\\" + file).c_str())) + { + std::ifstream f(std::string(TSPath) + "\\" + file, ios::binary); + if (f.good()) + { + f.seekg(0, std::ios::end); + auto size = f.tellg(); + if (size > 0) + { + lpData = new(BYTE[size]); + dwSize = size; + f.seekg(0, std::ios::beg); + f.read(reinterpret_cast(lpData), dwSize); + } + } + } + errstream << "LoadStrings() loading from mix" << endl; + errstream.flush(); + + if(!lpData) + { + HMIXFILE hMix=FindFileInMix(file.c_str()); + //HMIXFILE hMix=m_hLanguage; + if(hMix) + { + if (FSunPackLib::XCC_ExtractFile(file, u8AppDataPath + "\\RA2Tmp.csf", hMix)) + { + std::ifstream f(u8AppDataPath + "\\RA2Tmp.csf", ios::binary); + if (f.good()) + { + f.seekg(0, std::ios::end); + auto size = f.tellg(); + if (size > 0) + { + lpData = new(BYTE[size]); + dwSize = size; + f.seekg(0, std::ios::beg); + f.read(reinterpret_cast(lpData), dwSize); + } + } + } + + if (!lpData) + { + MessageBox("String file not found, using rules.ini names","Error"); + return; + } + } + else + { + MessageBox("String file not found, using rules.ini names","Error"); + return; + } + + } + + BYTE* orig=static_cast(lpData); + + if(!(lpData=Search(&lpData, (BYTE*)" FSC"))) return; + + RA2STRFILEHEAD head; + memcpy(&head, lpData, RA2STRFILEHEADSIZE); + + + lpData+=RA2STRFILEHEADSIZE; + + map strings; + + int i; + //try{ + for(i=0;ilpData); + + if(!(lpData=lpData+4))//Search(&lpData, (BYTE*)" LBL"))) + { + + return; + } + + RA2STRINGENTRY entry; + memcpy(&entry.dwFlag, lpData, 4); + lpData+=4; + + DWORD dwCharCount; + memcpy(&dwCharCount, lpData, 4); + lpData+=4; + + BYTE* lpID=new(BYTE[dwCharCount+1]); + memcpy(lpID, lpData, dwCharCount); + lpData+=dwCharCount; + lpID[dwCharCount]=0; + entry.id=(CHAR*)new(BYTE[dwCharCount+1]); + strcpy(entry.id, (LPCSTR)lpID); + entry.id[dwCharCount]=0; + entry.id_size=dwCharCount; + // enable this to show the string ID + delete[](lpID); + + + BOOL b2Strings=FALSE; + + if(lpData[0]=='W') + b2Strings=TRUE; + + if(!(lpData=lpData+4))//Search(&lpData, (BYTE*)" RTS"))) + { + return; + } + + memcpy(&dwCharCount, lpData, 4); + lpData+=4; + + WCHAR* lpwID=new(WCHAR[dwCharCount+1]); + int e; + for(e=0;eFindName("UIName")>=0) + { + int e; + + if(strings.find(rules.GetSection(i)->values["UIName"])!=strings.end()) + { + //MessageBox(strings[rules.GetSection(i)->values["UIName"]].cString); + if(!strings[rules.GetSection(i)->values["UIName"]].bUsedDefault) + { + //CCStrings[*rules.GetSectionName(i)].cString=strings[rules.GetSection(i)->values["UIName"]].cString; //.SetString(strings[rules.GetSection(i)->values["UIName"]].wString, strings[rules.GetSection(i)->values["UIName"]].len); + CCStrings[*rules.GetSectionName(i)].SetString(strings[rules.GetSection(i)->values["UIName"]].wString, strings[rules.GetSection(i)->values["UIName"]].len); + } + else + { + CCStrings[*rules.GetSectionName(i)].SetString(strings[rules.GetSection(i)->values["UIName"]].wString, strings[rules.GetSection(i)->values["UIName"]].len); + CCStrings[*rules.GetSectionName(i)].cString=rules.GetSection(i)->GetValueByName("Name"); + } + } + else + { + //MessageBox((LPSTR)(LPCSTR)rules.GetSection(i)->values["Name"], *rules.GetSectionName(i)); + CCStrings[*rules.GetSectionName(i)].SetString((LPSTR)(LPCSTR)rules.GetSection(i)->GetValueByName("Name")); + } + } + else CCStrings[*rules.GetSectionName(i)].SetString((LPSTR)(LPCSTR)rules.GetSection(i)->GetValueByName("Name")); + + } + + +#else + int i; + for(i=0;iFindName("Name")>=0) + { + //CCStrings[*rules.GetSectionName(i)].cString=rules.GetSection(i)->values["Name"]; + //CCStrings[*rules.GetSectionName(i)].SetString=rul + CCStrings[*rules.GetSectionName(i)].SetString((LPSTR)(LPCSTR)rules.GetSection(i)->values["Name"]); + } + } +#endif + + +} + +void CLoading::HackRules() +{ + if(editor_mode==ra2_mode) + { + int i; + int max_c=0; + for(i=0;imax_c) max_c=p; + } + + char c[50]; + itoa(max_c+1,c,10); + + rules.sections["BuildingTypes"].values[c]=rules.sections["General"].values["GDIGateOne"]; + +#ifdef RA2_MODE + // RULES(MD).INI has the incorrect colors set for the following houses, let's remap them to the expected values. + // Fixup YuriCountry colour + if (rules.sections["YuriCountry"].GetValueByName("Color") == "DarkRed") { + rules.sections["YuriCountry"].values["Color"] = "Purple"; + } + // Fixup Allied colors + std::list allied_houses; + allied_houses.push_back("British"); + allied_houses.push_back("French"); + allied_houses.push_back("Germans"); + allied_houses.push_back("Americans"); + allied_houses.push_back("Alliance"); + for (std::list::iterator it = allied_houses.begin(); it != allied_houses.end(); ++it) { + if (rules.sections[*it].GetValueByName("Color") == "Gold") { + rules.sections[*it].values["Color"] = "DarkBlue"; + } + } + // Fixup Nod color + if (rules.sections["Nod"].GetValueByName("Color") == "Gold") { + rules.sections["Nod"].values["Color"] = "DarkRed"; + } +#endif + + } + +} + +void CLoading::PrepareBuildingTheaters() +{ + // stub + +} + +/* +This actually just checks what palette the unit (only buildings make sense) +uses. Used for the ObjectBrowser (so it only shows those buildings that really exist +in the specific terrain) + +Added: MW March 20th 2001 +*/ +void CLoading::PrepareUnitGraphic(LPCSTR lpUnittype) +{ + CString _rules_image; // the image used + CString filename; // filename of the image + char theat=cur_theat; // standard theater char is t (Temperat). a is snow. + + BOOL bAlwaysSetChar; // second char is always theater, even if NewTheater not specified! + WORD wStep=1; // step is 1 for infantry, buildings, etc, and for shp vehicles it specifies the step rate between every direction + WORD wStartWalkFrame=0; // for examply cyborg reaper has another walk starting frame + int iTurretOffset=0; // used for centering y pos of turret (if existing) + BOOL bStructure=rules.sections["BuildingTypes"].FindValue(lpUnittype)>=0; // is this a structure? + + if(!bStructure) return; // make sure we only use it for buildings now + + BOOL bPowerUp=rules.sections[lpUnittype].values["PowersUpBuilding"]!=""; + + HTSPALETTE hPalette; + if(theat=='T') hPalette=m_hPalIsoTemp; + if(theat=='A') hPalette=m_hPalIsoSnow; + if(theat=='U') hPalette=m_hPalIsoUrb; + if(theat=='L') hPalette=m_hPalIsoLun; + if(theat=='D') hPalette=m_hPalIsoDes; + if(theat=='N') hPalette=m_hPalIsoUbn; + + CIsoView& v=*((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; + + _rules_image=lpUnittype; + if(rules.sections[lpUnittype].values.find("Image")!=rules.sections[lpUnittype].values.end()) + _rules_image=rules.sections[lpUnittype].values["Image"]; + + CString _art_image = _rules_image; + if(art.sections[_rules_image].values.find("Image")!=art.sections[_rules_image].values.end()) + { + if(!isTrue(g_data.sections["IgnoreArtImage"].values[_rules_image])) + _art_image=art.sections[_rules_image].values["Image"]; + } + + const CString& image = _art_image; + const auto& rulesSection = rules.sections[lpUnittype]; + const auto& artSection = art.sections[image]; + + if(!isTrue(art.sections[image].values["Voxel"])) // is it a shp graphic? + { + try + { + + /*filename = image + ".shp"; + + + BYTE bTerrain=0; + + + + BOOL isNewTerrain=FALSE; + if(isTrue(artSection.GetValueByName("NewTheater")))//&& isTrue(artSection.GetValueByName("TerrainPalette")))//(filename.GetAt(0)=='G' || filename.GetAt(0)=='N' || filename.GetAt(0)=='C') && filename.GetAt(1)=='A') + { + hPalette=m_hPalUnitTemp; + if(theat=='A') hPalette=m_hPalUnitSnow; + if(theat=='U') hPalette=m_hPalUnitUrb; + if(theat=='L') hPalette=m_hPalUnitLun; + if(theat=='D') hPalette=m_hPalUnitDes; + if(theat=='N') hPalette=m_hPalUnitUbn; + filename.SetAt(1, theat); + isNewTerrain=TRUE; + } + + + HMIXFILE hShpMix=FindFileInMix(filename, &bTerrain); + + BYTE bIgnoreTerrain=TRUE; + + if(hShpMix==NULL && isNewTerrain) + { + filename.SetAt(1, 'G'); + hShpMix=FindFileInMix(filename, &bTerrain); + if(hShpMix) theat='G'; + + } + + + if(hShpMix==NULL && isNewTerrain) + { + filename.SetAt(1, 'N'); + hShpMix=FindFileInMix(filename, &bTerrain); + if(hShpMix) theat='N'; + } + + if(hShpMix==NULL && isNewTerrain) + { + filename.SetAt(1, 'D'); + hShpMix=FindFileInMix(filename, &bTerrain); + if(hShpMix) theat='D'; + } + + if(hShpMix==NULL && isNewTerrain) + { + filename.SetAt(1, 'L'); + hShpMix=FindFileInMix(filename, &bTerrain); + if(hShpMix) theat='L'; + } + + if(hShpMix==NULL && isNewTerrain) + { + filename.SetAt(1, 'A'); + hShpMix=FindFileInMix(filename, &bTerrain); + if(hShpMix) theat='A'; + } + + if(hShpMix==NULL && isNewTerrain) + { + filename.SetAt(1, 'T'); + hShpMix=FindFileInMix(filename, &bTerrain); + if(hShpMix){ + theat='T'; + hPalette=m_hIsoTemp; + } + } + + + if(isTrue(artSection.GetValueByName("TerrainPalette"))) + { + bIgnoreTerrain=FALSE; + + if(cur_theat=='T') + hPalette=m_hPalIsoTemp; + else if(cur_theat=='A') + hPalette=m_hPalIsoSnow; + else if (cur_theat=='U') + hPalette=m_hPalIsoUrb; + else if(cur_theat=='L') + hPalette=m_hPalIsoLun; + else if(cur_theat=='D') + hPalette=m_hPalIsoDes; + else if(cur_theat=='N') + hPalette=m_hPalIsoUbn; + + + + } + + + + if(hShpMix==0) + { + filename=image; + filename+=".shp"; + hShpMix=FindFileInMix(filename, &bTerrain); + + + + if(hShpMix==NULL) + { + filename=image; + if(theat=='T') filename+=".tem"; + if(theat=='A') filename+=".sno"; + if(theat=='U') filename+=".urb"; + if(theat=='L') filename+=".lun"; + if(theat=='D') filename+=".des"; + if(theat=='N') filename+=".ubn"; + filename.MakeLower(); + hShpMix=FindFileInMix(filename, &bTerrain); + + if(hShpMix==NULL) + { + filename=image; + filename+=".tem"; + hShpMix=FindFileInMix(filename, &bTerrain); + if(hShpMix) + { + hPalette=m_hPalIsoTemp; + } + } + + if(hShpMix!=NULL) + { + + + + } + else + { + filename=image+".shp"; + + filename.SetAt(1, 'A'); + + hShpMix=FindFileInMix(filename); + + if(hShpMix!=NULL) + { + bAlwaysSetChar=TRUE; + } + else + { + filename.SetAt(1, 'A'); + hShpMix=FindFileInMix(filename); + + if(hShpMix!=NULL) + { + theat='A'; + bAlwaysSetChar=TRUE; + } + else + { + filename.SetAt(1, 'U'); + hShpMix=FindFileInMix(filename); + if(hShpMix) theat='U'; + else + { + filename.SetAt(1, 'L'); + hShpMix=FindFileInMix(filename); + if(hShpMix) theat='L'; + else + { + filename.SetAt(1, 'D'); + hShpMix=FindFileInMix(filename); + if(hShpMix) theat='D'; + else + { + filename.SetAt(1, 'N'); + hShpMix=FindFileInMix(filename); + if(hShpMix) theat='N'; + else + { + filename.SetAt(1, 'T'); + hShpMix=FindFileInMix(filename); + if(hShpMix) theat='T'; + } + } + } + } + } + } + } + } + else + { + theat='T'; + } + + } + else + { + + // now we need to find out the palette + + if(isTrue(artSection.GetValueByName("TerrainPalette"))) // it´s a file in isotemp.mix/isosno.mix + { + + } + else // it´s a file in temperat.mix/snow.mix + { + if(cur_theat=='T') hPalette=m_hPalUnitTemp; + if(cur_theat=='A') hPalette=m_hPalUnitSnow; + if(cur_theat=='U') hPalette=m_hPalUnitUrb; + if(cur_theat=='L') hPalette=m_hPalUnitLun; + if(cur_theat=='D') hPalette=m_hPalUnitDes; + if(cur_theat=='N') hPalette=m_hPalUnitUbn; + } + + }*/ + + auto shp = FindUnitShp(image, cur_theat, artSection); + if (!shp) + return; + + filename = shp->filename; + hPalette = shp->palette; + + auto limited_to_theater = isTrue(artSection.GetValueByName("TerrainPalette")) ? shp->mixfile_theater : TheaterChar::None; + + if(filename=="tibtre01.tem" || filename=="tibtre02.tem" || filename=="tibtre03.tem" || filename=="veinhole.tem") + { + hPalette=m_hPalUnitTemp; + } + + + if(shp->mixfile>0) + { + + BOOL bSuccess=FSunPackLib::SetCurrentSHP(filename, shp->mixfile); + if( + !bSuccess + ) + { + filename=image+".sno"; + if(cur_theat=='T' || cur_theat=='U') hPalette=m_hPalIsoTemp; + HMIXFILE hShpMix=FindFileInMix(filename); + bSuccess=FSunPackLib::SetCurrentSHP(filename, hShpMix); + + if(!bSuccess) + { + return; + } + } + + if(bSuccess) + { + + + char ic[50]; + int i=0; + itoa(i, ic, 10); + + // just fill in a stub entry - Final* will automatically retry loading once the graphic really must be loaded + PICDATA p; + p.pic=NULL; + p.x=0; + p.y=0; + p.wHeight=0; + p.wWidth=0; + p.wMaxWidth=0; + p.wMaxHeight=0; + p.bType=PICDATA_TYPE_SHP; + p.bTerrain=limited_to_theater; + + + pics[image+ic]=p; + + + } + + } + + } + catch(...) + { + errstream << " exception " << endl; + errstream.flush(); + } + + + } + +} + +/* +Helper function that fetches the palette data from FsunPackLib +FSunPackLib doesn´t provide any special function to retrieve a color table entry, +so we have to build it ourself +Also builds color_conv +*/ +void CLoading::FetchPalettes() +{ + // SetTSPaletteEntry(HTSPALETTE hPalette, BYTE bIndex, RGBTRIPLE* rgb, RGBTRIPLE* orig); + // SetTSPaletteEntry can retrieve the current color table entry without modifying it! + + + // iso palette + HTSPALETTE hCur=0; + if(Map->GetTheater()==THEATER0) hCur=m_hPalIsoTemp; + if(Map->GetTheater()==THEATER1) hCur=m_hPalIsoSnow; + if(Map->GetTheater()==THEATER2) hCur=m_hPalIsoUrb; + if(Map->GetTheater()==THEATER3) hCur=m_hPalIsoUbn; + if(Map->GetTheater()==THEATER4) hCur=m_hPalIsoLun; + if(Map->GetTheater()==THEATER5) hCur=m_hPalIsoDes; + + int i; + + for(i=0;i<256;i++) + { + FSunPackLib::SetTSPaletteEntry(hCur, i, NULL /* don´t modify it!*/, &palIso[i] /*but retrieve it!*/); + } + + + // unit palette + if(Map->GetTheater()==THEATER0) hCur=m_hPalUnitTemp; + if(Map->GetTheater()==THEATER1) hCur=m_hPalUnitSnow; + if(Map->GetTheater()==THEATER2) hCur=m_hPalUnitUrb; + if(Map->GetTheater()==THEATER3) hCur=m_hPalUnitUbn; + if(Map->GetTheater()==THEATER4) hCur=m_hPalUnitLun; + if(Map->GetTheater()==THEATER5) hCur=m_hPalUnitDes; + + + for(i=0;i<256;i++) + { + FSunPackLib::SetTSPaletteEntry(hCur, i, NULL /* don´t modify it!*/, &palUnit[i] /*but retrieve it!*/); + } + + + // theater palette + if(Map->GetTheater()==THEATER0) hCur=m_hPalTemp; + if(Map->GetTheater()==THEATER1) hCur=m_hPalSnow; + if(Map->GetTheater()==THEATER2) hCur=m_hPalUrb; + if(Map->GetTheater()==THEATER3) hCur=m_hPalUbn; + if(Map->GetTheater()==THEATER4) hCur=m_hPalLun; + if(Map->GetTheater()==THEATER5) hCur=m_hPalDes; + + + + for(i=0;i<256;i++) + { + FSunPackLib::SetTSPaletteEntry(hCur, i, NULL /* don´t modify it!*/, &palTheater[i] /*but retrieve it!*/); + } + + + // lib palette + hCur=m_hPalLib; + + + for(i=0;i<256;i++) + { + FSunPackLib::SetTSPaletteEntry(hCur, i, NULL /* don´t modify it!*/, &palLib[i] /*but retrieve it!*/); + } + + CreateConvTable(palIso, iPalIso); + CreateConvTable(palLib, iPalLib); + CreateConvTable(palUnit, iPalUnit); + CreateConvTable(palTheater, iPalTheater); + + CIsoView& v=*((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; + + DDPIXELFORMAT pf; + memset(&pf, 0, sizeof(DDPIXELFORMAT)); + pf.dwSize=sizeof(DDPIXELFORMAT); + + v.lpds->GetPixelFormat(&pf); + v.pf = pf; + v.m_color_converter.reset(new FSunPackLib::ColorConverter(v.pf)); + + FSunPackLib::ColorConverter conf(pf); + + const auto& rulesColors = rules.sections["Colors"]; + for(i=0;i< rulesColors.values.size();i++) + { + CString col=*rulesColors.GetValueName(i); + COLORREF cref=v.GetColor("", col); + + color_conv[col]=conf.GetColor(GetRValue(cref), GetGValue(cref), GetBValue(cref)); + colorref_conv[cref]=color_conv[col]; + } +} + +void CLoading::CreateConvTable(RGBTRIPLE *pal, int *iPal) +{ + CIsoView& v=*((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview; + + DDPIXELFORMAT pf; + memset(&pf, 0, sizeof(DDPIXELFORMAT)); + pf.dwSize=sizeof(DDPIXELFORMAT); + + v.lpds->GetPixelFormat(&pf); + + FSunPackLib::ColorConverter conf(pf); + + int i; + for(i=0;i<256;i++) + { + iPal[i]=conf.GetColor(pal[i].rgbtRed, pal[i].rgbtGreen, pal[i].rgbtBlue); + } +} diff --git a/MissionEditor/Loading.h b/MissionEditor/Loading.h new file mode 100644 index 0000000..eb07890 --- /dev/null +++ b/MissionEditor/Loading.h @@ -0,0 +1,221 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_LOADING_H__5D5C3284_8962_11D3_B63B_AAA51FD322E3__INCLUDED_) +#define AFX_LOADING_H__5D5C3284_8962_11D3_B63B_AAA51FD322E3__INCLUDED_ + +#include "FinalSunDlg.h" +#include "MissionEditorPackLib.h" +#include +#include + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Loading.h : header file +// + +class VoxelNormalTables; + +struct EXPANDMIX +{ + HMIXFILE hExpand; // NULL if expansion mix does not exist + HMIXFILE hECache; // NULL if no ECache + HMIXFILE hConquer; // NULL if no Conquer + HMIXFILE hLocal; + HMIXFILE hIsoSnow; // NULL if no IsoSnow + HMIXFILE hIsoTemp; // NULL if no IsoTemp + HMIXFILE hIsoUrb; + HMIXFILE hIsoGen; + HMIXFILE hIsoLun; + HMIXFILE hIsoDes; + HMIXFILE hIsoUbn; + HMIXFILE hIsoGenMd; + HMIXFILE hIsoLunMd; + HMIXFILE hIsoDesMd; + HMIXFILE hIsoUbnMd; + HMIXFILE hTemperat; // NULL if no Temperat + HMIXFILE hSnow; + HMIXFILE hUrban; + HMIXFILE hLunar; + HMIXFILE hUrbanN; + HMIXFILE hDesert; + HMIXFILE hGeneric; + HMIXFILE hTem; + HMIXFILE hSno; + HMIXFILE hUrb; + HMIXFILE hLun; + HMIXFILE hDes; + HMIXFILE hUbn; + HMIXFILE hBuildings; + HMIXFILE hMarble; + EXPANDMIX() {memset(this, 0, sizeof(EXPANDMIX));}; +}; + +class CFinalSunDlg; + + +///////////////////////////////////////////////////////////////////////////// +// dialog field CLoading + + +struct FindShpResult +{ + FindShpResult(HMIXFILE mixfile_, TheaterChar mixfile_theater_, CString filename_, TheaterChar theat_, HTSPALETTE palette_): mixfile(mixfile_), mixfile_theater(mixfile_theater_), filename(filename_), theat(theat_), palette(palette_) { } + HMIXFILE mixfile; + TheaterChar mixfile_theater; + CString filename; + TheaterChar theat; + HTSPALETTE palette; +}; + +class CLoading : public CDialog +{ +// Construction +public: + void CreateConvTable(RGBTRIPLE* pal, int* iPal); + void FetchPalettes(); + void PrepareUnitGraphic(LPCSTR lpUnittype); + void LoadStrings(); + void FreeAll(); + void FreeTileSet(); + BOOL InitDirectDraw(); + + void InitTMPs(CProgressCtrl* prog=NULL); + void InitPalettes(); + + ~CLoading(); + void Unload(); + BOOL InitMixFiles(); + void InitSHPs(CProgressCtrl* prog=NULL); + void LoadTSIni(LPCTSTR lpFilename, CIniFile* lpIniFile, BOOL bIsExpansion, BOOL bCheckEditorDir = FALSE); + void CreateINI(); + CLoading(CWnd* pParent = NULL); // Standardconstructor + void InitPics(CProgressCtrl* prog=NULL); + void Load(); + BOOL LoadUnitGraphic(LPCTSTR lpUnittype); + void LoadBuildingSubGraphic(const CString& subkey, const CIniFileSection& artSection, BOOL bAlwaysSetChar, char theat, HMIXFILE hShpMix, SHPHEADER& shp_h, BYTE*& shp); + void LoadOverlayGraphic(LPCTSTR lpOvrlName, int iOvrlNum); + void InitVoxelNormalTables(); + HTSPALETTE GetIsoPalette(char theat); + HTSPALETTE GetUnitPalette(char theat); + std::optional FindUnitShp(const CString& image, char preferred_theat, const CIniFileSection& artSection); + char cur_theat; + + +// Dialog data + //{{AFX_DATA(CLoading) + enum { IDD = IDD_LOADING }; + CStatic m_Version; + CStatic m_BuiltBy; + CStatic m_cap; + CProgressCtrl m_progress; + //}}AFX_DATA + + +// Overwriteables + // class wizard generated overwriteables + //{{AFX_VIRTUAL(CLoading) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-support + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// Implementation +protected: + void PrepareBuildingTheaters(); + + // generated message handlers + //{{AFX_MSG(CLoading) + virtual BOOL OnInitDialog(); + afx_msg void OnDestroy(); + afx_msg void OnPaint(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + void HackRules(); + void PrepareHouses(void); + void CalcPicCount(); + int m_pic_count; + int m_bmp_count; + BOOL LoadTile(LPCSTR lpFilename, HMIXFILE hOwner, HTSPALETTE hPalette, DWORD dwID, BOOL bReplacement); + HTSPALETTE m_hPalIsoTemp; + HTSPALETTE m_hPalIsoSnow; + HTSPALETTE m_hPalIsoUrb; + + HTSPALETTE m_hPalUnitTemp; + HTSPALETTE m_hPalUnitSnow; + HTSPALETTE m_hPalUnitUrb; + HTSPALETTE m_hPalTemp; + HTSPALETTE m_hPalSnow; + HTSPALETTE m_hPalUrb; + HTSPALETTE m_hPalLib; + // YR pals: + HTSPALETTE m_hPalLun; + HTSPALETTE m_hPalDes; + HTSPALETTE m_hPalUbn; + HTSPALETTE m_hPalIsoLun; + HTSPALETTE m_hPalIsoDes; + HTSPALETTE m_hPalIsoUbn; + HTSPALETTE m_hPalUnitLun; + HTSPALETTE m_hPalUnitDes; + HTSPALETTE m_hPalUnitUbn; + + HMIXFILE FindFileInMix(LPCTSTR lpFilename, TheaterChar* pTheaterChar=NULL); + HMIXFILE m_hLocal; + HMIXFILE m_hSno; + HMIXFILE m_hTem; + HMIXFILE m_hUrb; + HMIXFILE m_hLun; + HMIXFILE m_hDes; + HMIXFILE m_hUbn; + HMIXFILE m_hTibSun; + HMIXFILE m_hBuildings; + EXPANDMIX m_hExpand[101]; // 1 added for ra2md.mix + HMIXFILE m_hECache[100]; + HMIXFILE m_hIsoSnow; + HMIXFILE m_hIsoTemp; + HMIXFILE m_hIsoUrb; + HMIXFILE m_hIsoGen; + HMIXFILE m_hIsoLun; + HMIXFILE m_hIsoDes; + HMIXFILE m_hIsoUbn; + HMIXFILE m_hTemperat; + HMIXFILE m_hSnow; + HMIXFILE m_hUrban; + HMIXFILE m_hUrbanN; + HMIXFILE m_hLunar; + HMIXFILE m_hDesert; + HMIXFILE m_hCache; + HMIXFILE m_hConquer; + HMIXFILE m_hLanguage; + HMIXFILE m_hLangMD; + HMIXFILE m_hMarble; + BOOL loaded; + + std::unique_ptr m_voxelNormalTables; + + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_LOADING_H__5D5C3284_8962_11D3_B63B_AAA51FD322E3__INCLUDED_ diff --git a/MissionEditor/MMXSavingOptionsDlg.cpp b/MissionEditor/MMXSavingOptionsDlg.cpp new file mode 100644 index 0000000..80af27f --- /dev/null +++ b/MissionEditor/MMXSavingOptionsDlg.cpp @@ -0,0 +1,86 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// MMXSavingOptionsDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "MMXSavingOptionsDlg.h" +#include "variables.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CMMXSavingOptionsDlg + + +CMMXSavingOptionsDlg::CMMXSavingOptionsDlg(CWnd* pParent /*=NULL*/) + : CDialog(CMMXSavingOptionsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CMMXSavingOptionsDlg) + m_Description = _T(""); + m_AirWar = FALSE; + m_Cooperative = FALSE; + m_Duel = FALSE; + m_Maxplayers = 0; + m_Meatgrind = FALSE; + m_MegaWealth = FALSE; + m_MinPlayers = 0; + m_NavalWar = FALSE; + m_NukeWar = FALSE; + m_Standard = TRUE; + //}}AFX_DATA_INIT + + m_Description=Map->GetIniFile().sections["Basic"].values["Name"]; +} + + +void CMMXSavingOptionsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMMXSavingOptionsDlg) + DDX_Text(pDX, IDC_DESCRIPTION, m_Description); + DDX_Check(pDX, IDC_AIRWAR, m_AirWar); + DDX_Check(pDX, IDC_COOPERATIVE, m_Cooperative); + DDX_Check(pDX, IDC_DUEL, m_Duel); + DDX_CBIndex(pDX, IDC_MAXPLAYERS, m_Maxplayers); + DDX_Check(pDX, IDC_MEATGRIND, m_Meatgrind); + DDX_Check(pDX, IDC_MEGAWEALTH, m_MegaWealth); + DDX_CBIndex(pDX, IDC_MINPLAYERS, m_MinPlayers); + DDX_Check(pDX, IDC_NAVALWAR, m_NavalWar); + DDX_Check(pDX, IDC_NUKEWAR, m_NukeWar); + DDX_Check(pDX, IDC_STANDARD, m_Standard); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CMMXSavingOptionsDlg, CDialog) + //{{AFX_MSG_MAP(CMMXSavingOptionsDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Zuordnungsmakros fĂ¼r Nachrichten ein + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CMMXSavingOptionsDlg diff --git a/MissionEditor/MMXSavingOptionsDlg.h b/MissionEditor/MMXSavingOptionsDlg.h new file mode 100644 index 0000000..783b5a2 --- /dev/null +++ b/MissionEditor/MMXSavingOptionsDlg.h @@ -0,0 +1,76 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_MMXSAVINGOPTIONSDLG_H__1A62AFE1_E8CA_11D4_9C88_444553540000__INCLUDED_) +#define AFX_MMXSAVINGOPTIONSDLG_H__1A62AFE1_E8CA_11D4_9C88_444553540000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// MMXSavingOptionsDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CMMXSavingOptionsDlg + +class CMMXSavingOptionsDlg : public CDialog +{ +// Konstruktion +public: + CMMXSavingOptionsDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CMMXSavingOptionsDlg) + enum { IDD = IDD_MMXOPTIONS }; + CString m_Description; + BOOL m_AirWar; + BOOL m_Cooperative; + BOOL m_Duel; + int m_Maxplayers; + BOOL m_Meatgrind; + BOOL m_MegaWealth; + int m_MinPlayers; + BOOL m_NavalWar; + BOOL m_NukeWar; + BOOL m_Standard; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CMMXSavingOptionsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CMMXSavingOptionsDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Member-Funktionen ein + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_MMXSAVINGOPTIONSDLG_H__1A62AFE1_E8CA_11D4_9C88_444553540000__INCLUDED_ diff --git a/MissionEditor/Macros.h b/MissionEditor/Macros.h new file mode 100644 index 0000000..e1215e9 --- /dev/null +++ b/MissionEditor/Macros.h @@ -0,0 +1,38 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + macros.h + + FinalSun Macros (mainly constant variables) +*/ + +#ifndef FINALSUN_MACROS_INCLUDED +#define FINALSUN_MACROS_INCLUDED + +/* Overlay types */ +#define OVRL_VEINS 0x7e +#define OVRL_VEINHOLE 0xa7 +#define OVRL_VEINHOLEBORDER 0xb2 + +#define OVRL_TRACK_BEGIN 0x27 +#define OVRL_TRACK_END 0x36 // 0x32 was old end [changed on 2/13/2000] + +#endif \ No newline at end of file diff --git a/MissionEditor/MapCode.cpp b/MissionEditor/MapCode.cpp new file mode 100644 index 0000000..aad82c0 --- /dev/null +++ b/MissionEditor/MapCode.cpp @@ -0,0 +1,152 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// This code determines the cell values for +// StartX, StartY, Width & Height for the [Header] section + +#include "stdafx.h" +#include "MapCode.h" +#include "mapdata.h" +#include "defines.h" + + + + +int calcXPos(int x, int y) +{ + int x1=x*256+128; + + int y1 = y*256 + 128; + + int x2 = (x1 - y1) * 30; + + int y2 = (x1 + y1) * 15; + + int x3 = (x2/256 + 512*30) / 60; + + int y3 = (y2/256) / 30; + + return x3; +} + +int calcYPos(int x, int y) +{ + int x1=x*256+128; + + int y1 = y*256 + 128; + + int x2 = (x1 - y1) * 30; + + int y2 = (x1 + y1) * 15; + + int x3 = (x2/256 + 512*30) / 60; + + int y3 = (y2/256) / 30; + + return y3; +} + +struct MRECT +{ + int X; + int Y; + int Width; + int Height; +}; + + +void MC_GetHeaderRect(int& startx, int& starty, int& width, int& height) +{ + int leastx=10000; + int leasty=10000; + int mostx=0; + int mosty=0; + + MRECT LocalRect, PlayRect; + + RECT r; + Map->GetLocalSize(&r); + LocalRect.X=r.left; + LocalRect.Y=r.top; + LocalRect.Width=r.right; + LocalRect.Height=r.bottom; + + CIniFile& ini=Map->GetIniFile(); + PlayRect.X=0; + PlayRect.Y=0; + PlayRect.Width=Map->GetWidth(); + PlayRect.Height=Map->GetHeight(); + + char c[50]; + char d[50]; + itoa(LocalRect.Width, c, 10); + + int x,y; + int max=Map->GetIsoSize(); + for(x=0;xGetHeightAt(y+x*max); // remember: x/y switched here, WS coordinate system + + // fudge ramps at the top of the map so that they end up considered not in the local rect + //if (cell->ramp && x + y < PlayRect.Width + 2*LocalRect.Y + 4 + height) { + //height++; + //} + } + + + if ((x + y > PlayRect.Width + 2*LocalRect.Y + height) && + (x + y <= PlayRect.Width + 2*(LocalRect.Y + LocalRect.Height + 1) + height) && + (x - y < 2*(LocalRect.X + LocalRect.Width) - PlayRect.Width) && + (y - x < PlayRect.Width - 2*LocalRect.X)) + //if ((x + y > PlayRect.Width) && (x - y < PlayRect.Width) && (y - x < PlayRect.Width) && (x + y <= PlayRect.Width + 2 * PlayRect.Height)) + { + int rx=calcXPos(x,y); + int ry=calcYPos(x,y); + + if (rx < leastx) + leastx = rx; + + if (rx > mostx) + mostx = rx; + + if (ry < leasty) + leasty = ry; + + if (ry > mosty) + mosty = ry; + } + + } + } + + startx=leastx; + starty=leasty; + width=mostx-leastx; + height=mosty-leasty; +} + + + \ No newline at end of file diff --git a/MissionEditor/MapCode.h b/MissionEditor/MapCode.h new file mode 100644 index 0000000..ab017d4 --- /dev/null +++ b/MissionEditor/MapCode.h @@ -0,0 +1,28 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef MAPCODE_INCLUDED +#define MAPCODE_INCLUDED + +void MC_GetHeaderRect(int& startx, int& starty, int& width, int& height); +int calcXPos(int x, int y); +int calcYPos(int x, int y); + +#endif \ No newline at end of file diff --git a/MissionEditor/MapD.cpp b/MissionEditor/MapD.cpp new file mode 100644 index 0000000..238fa46 --- /dev/null +++ b/MissionEditor/MapD.cpp @@ -0,0 +1,169 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// MapD.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "MapD.h" +#include "resource.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" +#include "changesizedlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Eigenschaftenseite CMapD + +IMPLEMENT_DYNCREATE(CMapD, CDialog) + +CMapD::CMapD() : CDialog(CMapD::IDD) +{ + //{{AFX_DATA_INIT(CMapD) + m_Width = _T(""); + m_Height = _T(""); + //}}AFX_DATA_INIT +} + +CMapD::~CMapD() +{ +} + +void CMapD::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMapD) + DDX_Control(pDX, IDC_USESIZE, m_LocalSize); + DDX_Control(pDX, IDC_THEATER, m_Theater); + DDX_Text(pDX, IDC__SIZEX, m_Width); + DDX_Text(pDX, IDC__SIZEY, m_Height); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CMapD, CDialog) + //{{AFX_MSG_MAP(CMapD) + ON_EN_CHANGE(IDC_USESIZE, OnChangeUsesize) + ON_CBN_EDITCHANGE(IDC_THEATER, OnEditchangeTheater) + ON_BN_CLICKED(IDC_CHANGELOCAL, OnChangelocal) + ON_CBN_SELCHANGE(IDC_THEATER, OnEditchangeTheater) + ON_BN_CLICKED(IDC_CHANGE, OnChange) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CMapD + +void CMapD::UpdateDialog() +{ + CIniFile& ini=Map->GetIniFile(); + + m_LocalSize.SetWindowText( ini.sections["Map"].values["LocalSize"] ); + //m_Size.SetWindowText( ini.sections["Map"].values["Size"] ); + m_Theater.SetWindowText( ini.sections["Map"].values["Theater"] ); + + char c[50]; + itoa(Map->GetWidth(), c, 10); + m_Width=c; + itoa(Map->GetHeight(), c, 10); + m_Height=c; + + CDialog::UpdateData(FALSE); +} + +void CMapD::UpdateData() +{ + //MessageBox("This function ( UpdateData() ) should not be called, please contact the author."); +} + +void CMapD::OnChangeUsesize() +{ + +} + +void CMapD::OnEditchangeTheater() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Map"].values["Theater"]=GetText(&m_Theater); +} + +void CMapD::UpdateStrings() +{ + + GetDlgItem(IDC_DESC)->SetWindowText(GetLanguageStringACP("MapDesc")); + GetDlgItem(IDC_SIZEFRAME)->SetWindowText(GetLanguageStringACP("MapSizeFrame")); + GetDlgItem(IDC_LSIZE)->SetWindowText(GetLanguageStringACP("MapSize")); + GetDlgItem(IDC_USEABLEFRAME)->SetWindowText(GetLanguageStringACP("MapVisibleSizeFrame")); + GetDlgItem(IDC_LUSEABLE)->SetWindowText(GetLanguageStringACP("MapVisibleSize")); + GetDlgItem(IDC_LTHEATER)->SetWindowText(GetLanguageStringACP("MapTheater")); +} + +void CMapD::OnChangelocal() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Map"].values["LocalSize"]=GetText(&m_LocalSize); + + Map->CalcMapRect(); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); +} + +void CMapD::OnChange() +{ + /* + CDialog::UpdateData(TRUE); + + int width, height; + width=atoi(m_Width); + height=atoi(m_Height); + + Map->ResizeMap(width, height); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + */ + + CChangeSizeDlg dlg; + if(dlg.DoModal()==IDCANCEL) return; + + if(dlg.m_Width<16 || dlg.m_Width>400 || dlg.m_Height<16 || dlg.m_Height>400 || (dlg.m_Width + dlg.m_Height) > 512) + { + MessageBox("Width and Height must both be between 16 and 400 and both added must be less than 512.", "Error"); + return; + } + + Map->ResizeMap(dlg.m_Left, dlg.m_Top, dlg.m_Width, dlg.m_Height); + + + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_minimap.UpdateView(); + + char c[50]; + itoa(dlg.m_Width, c, 10); + + m_Width=c; + itoa(dlg.m_Height, c, 10); + m_Height=c; + CDialog::UpdateData(FALSE); +} diff --git a/MissionEditor/MapD.h b/MissionEditor/MapD.h new file mode 100644 index 0000000..334cb3d --- /dev/null +++ b/MissionEditor/MapD.h @@ -0,0 +1,78 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_MAPD_H__B5D522E9_69CE_11D3_99E1_C138647F2A00__INCLUDED_) +#define AFX_MAPD_H__B5D522E9_69CE_11D3_99E1_C138647F2A00__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// MapD.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CMapD + +class CMapD : public CDialog +{ + DECLARE_DYNCREATE(CMapD) + +// Konstruktion +public: + void UpdateStrings(); + void UpdateData(); + void UpdateDialog(); + CMapD(); + ~CMapD(); + +// Dialogfelddaten + //{{AFX_DATA(CMapD) + enum { IDD = IDD_MAP }; + CEdit m_LocalSize; + CComboBox m_Theater; + CString m_Width; + CString m_Height; + //}}AFX_DATA + + +// Ăœberschreibungen + // Der Klassen-Assistent generiert virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CMapD) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CMapD) + afx_msg void OnChangeUsesize(); + afx_msg void OnEditchangeTheater(); + afx_msg void OnChangelocal(); + afx_msg void OnChange(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_MAPD_H__B5D522E9_69CE_11D3_99E1_C138647F2A00__INCLUDED_ diff --git a/MissionEditor/MapData.cpp b/MissionEditor/MapData.cpp new file mode 100644 index 0000000..1faee3e --- /dev/null +++ b/MissionEditor/MapData.cpp @@ -0,0 +1,7461 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Map->cpp: Implementierung der Klasse CMap. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "MapData.h" +#include "DynamicGraphDlg.h" +#include "MissionEditorPackLib.h" +#include "inlines.h" +#include "variables.h" +#include "maploadingdlg.h" +#include "progressdlg.h" +#include "Structs.h" +#include "Tube.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#define new DEBUG_NEW +#endif + +typedef map OURMAP; + + + +void DoEvents() +{ + /*MSG msg; + while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + }*/ +} + + +void GetNodeName(CString& name, int n); + + +CString GetFree(const char* section) +{ + CIniFile& ini = Map->GetIniFile(); + + int i = 0; + char l[50]; + itoa(i, l, 10); + + while (ini.sections[section].values.find(l) != ini.sections[section].values.end()) + { + i++; + itoa(i, l, 10); + } + + return l; +} + + +/* +This function calculates a number for the specified building type. +Because this function is slow, you should only use it to fill the +buildingid map +*/ +inline int GetBuildingNumber(LPCTSTR name) +{ + CIniFile& ini = Map->GetIniFile(); + + int v = rules.sections["BuildingTypes"].FindValue(name); + + if (v > -1) + { + + return v; + } + + v = ini.sections["BuildingTypes"].FindValue(name); + if (v > -1) + { + return v + 0x0C00; + } + return -1; +} + +inline int GetTerrainNumber(LPCTSTR name) +{ + CIniFile& ini = Map->GetIniFile(); + + int v = rules.sections["TerrainTypes"].FindValue(name); + + if (v > -1) + { + + return v; + } + + v = ini.sections["TerrainTypes"].FindValue(name); + if (v > -1) + { + return v + 0x0C00; + } + return -1; +} + +#ifdef SMUDGE_SUPP +inline int GetSmudgeNumber(LPCTSTR name) +{ + CIniFile& ini = Map->GetIniFile(); + + int v = rules.sections["SmudgeTypes"].FindValue(name); + + if (v > -1) + { + + return v; + } + + v = ini.sections["SmudgeTypes"].FindValue(name); + if (v > -1) + { + return v + 0x0C00; + } + return -1; +} +#endif + +SNAPSHOTDATA::SNAPSHOTDATA() +{ + memset(this, 0, sizeof(SNAPSHOTDATA)); +} + + +NODEDATA::NODEDATA() +{ + type = -1; + house = ""; + index = -1; +} + +FIELDDATA::FIELDDATA() +{ +#ifdef SMUDGE_SUPP + smudge = -1; + smudgetype = -1; +#endif + unit = -1; + int i; + for (i = 0;i < SUBPOS_COUNT;i++) + infantry[i] = -1; + aircraft = -1; + structure = -1; + structuretype = -1; + terrain = -1; + waypoint = -1; + overlay = 0xFF; + overlaydata = 0x0; + bMapData = 0x0; + bSubTile = 0; + bMapData2 = 0x0; + wGround = 0xFFFF; + bHeight = 0; + celltag = -1; + bReserved = 0; + bCliffHack = 0; + bRedrawTerrain = 0; + terraintype = -1; + bHide = FALSE; + //sTube = 0xFFFF; + //cTubePart = -1; + + if (tiledata_count && (*tiledata_count)) // only if initialized + { + // algorithm taken from UpdateMapFieldData + int replacement = 0; + int ground = wGround; + if (ground == 0xFFFF) ground = 0; + ASSERT(ground == 0); + + // we assume ground 0 will never be a bridge set, so don't do this check here in contrast to UpdateMapFieldData + if ((*tiledata)[ground].bReplacementCount) //&& atoi((*tiles).sections["General"].values["BridgeSet"]) != (*tiledata)[ground].wTileSet) + { + replacement = rand() * (1 + (*tiledata)[ground].bReplacementCount) / RAND_MAX; + } + + bRNDImage = replacement; + } + +}; + +CMapData::CMapData() +{ + m_noAutoObjectUpdate = FALSE; + m_money = 0; + m_cursnapshot = -1; + fielddata = NULL; + fielddata_size = 0; + m_IsoSize = 0; + isInitialized = FALSE; + tiledata = NULL; + m_mfd = NULL; + dwIsoMapSize = 0; + m_snapshots = NULL; + dwSnapShotCount = 0; + + memset(&m_mini_biinfo, 0, sizeof(BITMAPINFO)); + m_mini_biinfo.bmiHeader.biBitCount = 24; + m_mini_biinfo.bmiHeader.biWidth = 0; + m_mini_biinfo.bmiHeader.biHeight = 0; + m_mini_biinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + m_mini_biinfo.bmiHeader.biClrUsed = 0; + m_mini_biinfo.bmiHeader.biPlanes = 1; + m_mini_biinfo.bmiHeader.biCompression = BI_RGB; + m_mini_biinfo.bmiHeader.biClrImportant = 0; +} + +CMapData::~CMapData() +{ + errstream << "CMapData::~CMapData()\n"; + errstream.flush(); + + // MW : Do not delete tiledata here! + //if(*tiledata!=NULL) delete[] *tiledata; + tiledata = NULL; + if (m_mfd != NULL) delete[] m_mfd; + m_mfd = NULL; + if (fielddata != NULL) delete[] fielddata; + fielddata = NULL; + fielddata_size = 0; + + int i; + + for (i = 0;i < dwSnapShotCount;i++) + { + delete[] m_snapshots[i].bHeight; + delete[] m_snapshots[i].bMapData; + delete[] m_snapshots[i].bSubTile; + delete[] m_snapshots[i].bMapData2; + delete[] m_snapshots[i].wGround; + delete[] m_snapshots[i].bRedrawTerrain; + delete[] m_snapshots[i].overlay; + delete[] m_snapshots[i].overlaydata; + // m_snapshots[i].mapfile.Clear(); + } + if (m_snapshots) delete[] m_snapshots; + m_snapshots = NULL; + dwSnapShotCount = 0; +} + +void CMapData::CalcMapRect() +{ + CIniFileSection& sec = m_mapfile.sections["Map"]; + char msize[50]; + strcpy_s(msize, sec.values["Size"]); + + + int cupos = 0; + static const int custr_size = 20; + char custr[custr_size]; + char* cucomma; + + cucomma = strchr(&msize[cupos], ','); + if (cucomma == NULL) return; + memcpy_s(custr, custr_size, &msize[cupos], (cucomma - msize) - cupos + 1); + custr[(cucomma - msize) - cupos] = 0; + cupos = cucomma - msize + 1; + + m_maprect.left = atoi(custr); + + + cucomma = strchr(&msize[cupos], ','); + if (cucomma == NULL) return; + memcpy_s(custr, custr_size, &msize[cupos], (cucomma - msize) - cupos + 1); + custr[((cucomma - msize)) - cupos] = 0; + cupos = cucomma - msize + 1; + + m_maprect.top = atoi(custr); + + + cucomma = strchr(&msize[cupos], ','); + if (cucomma == NULL) return; + memcpy_s(custr, custr_size, &msize[cupos], (cucomma - msize) - cupos + 1); + custr[((cucomma - msize)) - cupos] = 0; + cupos = cucomma - msize + 1; + + m_maprect.right = atoi(custr); + + cucomma = strchr(&msize[cupos], ','); // we check again... could be there is a new ini format + if (cucomma == NULL) cucomma = (char*)((int)msize + strlen(msize)); + memcpy_s(custr, custr_size, &msize[cupos], (cucomma - msize) - cupos + 1); + custr[((cucomma - msize)) - cupos] = 0; + cupos = cucomma - msize + 1; + + m_maprect.bottom = atoi(custr); + + m_IsoSize = m_maprect.right + m_maprect.bottom; + + // local size + + strcpy_s(msize, sec.values["LocalSize"]); + cupos = 0; + + + cucomma = strchr(&msize[cupos], ','); + if (cucomma == NULL) return; + memcpy_s(custr, custr_size, &msize[cupos], (cucomma - msize) - cupos + 1); + custr[(cucomma - msize) - cupos] = 0; + cupos = cucomma - msize + 1; + + m_vismaprect.left = atoi(custr); + + + cucomma = strchr(&msize[cupos], ','); + if (cucomma == NULL) return; + memcpy_s(custr, custr_size, &msize[cupos], (cucomma - msize) - cupos + 1); + custr[((cucomma - msize)) - cupos] = 0; + cupos = cucomma - msize + 1; + + m_vismaprect.top = atoi(custr); + + + cucomma = strchr(&msize[cupos], ','); + if (cucomma == NULL) return; + memcpy_s(custr, custr_size, &msize[cupos], (cucomma - msize) - cupos + 1); + custr[((cucomma - msize)) - cupos] = 0; + cupos = cucomma - msize + 1; + + m_vismaprect.right = atoi(custr); + + + cucomma = strchr(&msize[cupos], ','); // we check again... could be there is a new ini format + if (cucomma == NULL) cucomma = (char*)((int)msize + strlen(msize)); + memcpy_s(custr, custr_size, &msize[cupos], (cucomma - msize) - cupos + 1); + custr[((cucomma - msize)) - cupos] = 0; + cupos = cucomma - msize + 1; + + m_vismaprect.bottom = atoi(custr); + + +} + + + + + +WORD CMapData::GetHousesCount(BOOL bCountries) +{ +#ifndef RA2_MODE + bCountries = FALSE; +#endif + + CString sSection = MAPHOUSES; + if (bCountries) sSection = HOUSES; + + if (m_mapfile.sections.find(sSection) != m_mapfile.sections.end()) + if (m_mapfile.sections[sSection].values.size() > 0) return m_mapfile.sections[sSection].values.size(); + + return(rules.sections[HOUSES].values.size()); +} + +CString CMapData::GetHouseID(WORD wHouse, BOOL bCountry) +{ + if (wHouse >= GetHousesCount()) + return CString(""); + +#ifndef RA2_MODE + bCountry = FALSE; +#endif + + CString sSection = MAPHOUSES; + if (bCountry) sSection = HOUSES; + + + if (m_mapfile.sections.find(sSection) != m_mapfile.sections.end()) + if (m_mapfile.sections[sSection].values.size() > 0) return *m_mapfile.sections[sSection].GetValue(wHouse); + + return(*rules.sections[HOUSES].GetValue(wHouse)); +} + +DWORD CMapData::GetAITriggerTypeCount() +{ + if (m_mapfile.sections.find("AITriggerTypes") != m_mapfile.sections.end()) + return(m_mapfile.sections["AITriggerTypes"].values.size()); + + return 0; +} + +void CMapData::GetAITriggerType(DWORD dwAITriggerType, AITRIGGERTYPE* pAITrg) +{ + CString data; + + if (dwAITriggerType >= GetAITriggerTypeCount()) + return; + + data = *m_mapfile.sections["AITriggerTypes"].GetValue(dwAITriggerType); + + pAITrg->ID = *m_mapfile.sections["AITriggerTypes"].GetValueName(dwAITriggerType); + pAITrg->name = GetParam(data, 0); + pAITrg->teamtype1 = GetParam(data, 1); + pAITrg->owner = GetParam(data, 2); + pAITrg->techlevel = GetParam(data, 3); + pAITrg->type = GetParam(data, 4); + pAITrg->unittype = GetParam(data, 5); + pAITrg->data = GetParam(data, 6); + pAITrg->float1 = GetParam(data, 7); + pAITrg->float2 = GetParam(data, 8); + pAITrg->float3 = GetParam(data, 9); + pAITrg->skirmish = GetParam(data, 10); + pAITrg->flag4 = GetParam(data, 11); + pAITrg->multihouse = GetParam(data, 12); + pAITrg->basedefense = GetParam(data, 13); + pAITrg->teamtype2 = GetParam(data, 14); + pAITrg->easy = GetParam(data, 15); + pAITrg->medium = GetParam(data, 16); + pAITrg->hard = GetParam(data, 17); + + +} + +WORD CMapData::GetHouseIndex(LPCTSTR lpHouse) +{ + if (m_mapfile.sections.find(HOUSES) != m_mapfile.sections.end()) + if (m_mapfile.sections[HOUSES].values.size() > 0) + return m_mapfile.sections[HOUSES].FindValue(lpHouse); + + + return rules.sections[HOUSES].FindValue(lpHouse); +} + +DWORD CMapData::GetAITriggerTypeIndex(LPCTSTR lpID) +{ + if (GetAITriggerTypeCount() == 0) return 0; + + return m_mapfile.sections["AITriggerTypes"].FindName(lpID); +} + +CString CMapData::GetAITriggerTypeID(DWORD dwAITriggerType) +{ + if (dwAITriggerType >= GetAITriggerTypeCount()) return CString(""); + + return *m_mapfile.sections["AITriggerTypes"].GetValueName(dwAITriggerType); +} + +CIniFile& CMapData::GetIniFile() +{ + UpdateIniFile(); + return m_mapfile; +} + +/* +UpdateIniFile(); + +This will update the mapfile member if bSave==TRUE, +else the other data will be updated according to the info in mapfile. + +This sections will NOT be updated during loading from ini, +because of perfomance issues. They will not be updated not +during saving to ini if MAPDATA_UPDATE_TO_INI_ALL is not specified: + - IsoMapPack5 + - OverlayPack + - OverlayDataPack +If you want to load these sections, the caller needs to call Unpack(); +in order to do this. +*/ +void CMapData::UpdateIniFile(DWORD dwFlags) +{ + BOOL bSave = TRUE; + if (dwFlags == MAPDATA_UPDATE_FROM_INI) + bSave = FALSE; + + if (dwFlags == MAPDATA_UPDATE_FROM_INI) + { + CalcMapRect(); + InitMinimap(); + + slopesetpiecesset = atoi((*tiles).sections["General"].values["SlopeSetPieces"]); + rampset = atoi((*tiles).sections["General"].values["RampBase"]); + rampsmoothset = atoi((*tiles).sections["General"].values["RampSmooth"]); + cliffset = atoi((*tiles).sections["General"].values["CliffSet"]); + cliffset_start = GetTileID(cliffset, 0); + waterset = atoi((*tiles).sections["General"].values["WaterSet"]); + shoreset = atoi((*tiles).sections["General"].values["ShorePieces"]); + rampset_start = GetTileID(atoi((*tiles).sections["General"].values["RampBase"]), 0); + ramp2set = atoi(g_data.sections["NewUrbanInfo"].values["Ramps2"]); + ramp2set_start = GetTileID(ramp2set, 0); + pave2set = atoi(g_data.sections["NewUrbanInfo"].values["Morphable2"]); + pave2set_start = GetTileID(pave2set, 0); + cliff2set = atoi(g_data.sections["NewUrbanInfo"].values["Cliffs2"]); + cliff2set_start = GetTileID(cliff2set, 0); + cliffwater2set = atoi(g_data.sections["NewUrbanInfo"].values["CliffsWater2"]); + + InitializeUnitTypes(); + UpdateBuildingInfo(); + UpdateTreeInfo(); +#ifdef SMUDGE_SUPP + UpdateSmudgeInfo(); +#endif + UpdateMapFieldData(bSave); + + + } + else if (dwFlags & MAPDATA_UPDATE_TO_INI_ALL) + { + UpdateAircraft(bSave); + UpdateCelltags(bSave); + UpdateInfantry(bSave); + UpdateNodes(bSave); + UpdateOverlay(bSave); + UpdateStructures(bSave); + UpdateTerrain(bSave); +#ifdef SMUDGE_SUPP + UpdateSmudges(bSave); +#endif + UpdateUnits(bSave); + UpdateWaypoints(bSave); + UpdateTubes(bSave); + errstream << "UpdateMapFieldData() called" << endl; + errstream.flush(); + UpdateMapFieldData(bSave); + errstream << "About to call Pack()" << endl; + errstream.flush(); + Pack(dwFlags & MAPDATA_UPDATE_TO_INI_ALL_PREVIEW, dwFlags & MAPDATA_UPDATE_TO_INI_ALL_COMPRESSED); + return; + } + + if (!bSave) UpdateAircraft(bSave); + UpdateCelltags(bSave); + if (!bSave) UpdateInfantry(bSave); + UpdateNodes(bSave); + if (!bSave) UpdateOverlay(bSave); + if (!bSave) UpdateStructures(bSave); + if (!bSave) UpdateTerrain(bSave); +#ifdef SMUDGE_SUPP + if (!bSave) UpdateSmudges(bSave); +#endif + if (!bSave) UpdateUnits(bSave); + UpdateWaypoints(bSave); + UpdateTubes(bSave); + +} + +void CMapData::LoadMap(const std::string& file) +{ + errstream << "LoadMap() frees memory\n"; + errstream.flush(); + + if (fielddata != NULL) delete[] fielddata; + int i; + for (i = 0;i < dwSnapShotCount;i++) + { + delete[] m_snapshots[i].bHeight; + delete[] m_snapshots[i].bMapData; + delete[] m_snapshots[i].bSubTile; + delete[] m_snapshots[i].bMapData2; + delete[] m_snapshots[i].wGround; + delete[] m_snapshots[i].bRedrawTerrain; + delete[] m_snapshots[i].overlay; + delete[] m_snapshots[i].overlaydata; + // m_snapshots[i].mapfile.Clear(); + } + if (m_snapshots != NULL) delete[] m_snapshots; + + + + fielddata = NULL; + fielddata_size = 0; + m_snapshots = NULL; + dwSnapShotCount = 0; + m_cursnapshot = -1; + + m_tubes.clear(); + m_tubes.reserve(32); + + m_infantry.clear(); + m_terrain.clear(); + m_units.clear(); + m_structures.clear(); +#ifdef SMUDGE_SUPP + m_smudges.clear(); +#endif + + errstream << "LoadMap() loads map file\n"; + errstream.flush(); + + m_mapfile.Clear(); + m_mapfile.LoadFile(file, TRUE); + + // any .mpr is a multi map. Previous FinalAlert/FinalSun versions did not set this value correctly-> + char lowc[MAX_PATH] = { 0 }; + strcpy_s(lowc, file.c_str()); + _strlwr(lowc); + if (strstr(lowc, ".mpr")) + { + m_mapfile.sections["Basic"].values["MultiplayerOnly"] = "1"; + if (m_mapfile.sections["Basic"].FindName("Player") >= 0) m_mapfile.sections["Basic"].values.erase("Player"); + } + + + + errstream << "LoadMap() repairs Taskforces (if needed)\n"; + errstream.flush(); + + // repair taskforces (bug in earlier 0.95 versions) + for (i = 0;i < m_mapfile.sections["TaskForces"].values.size();i++) + { + vector toDelete; + toDelete.reserve(5); + + CIniFileSection& sec = m_mapfile.sections[*m_mapfile.sections["TaskForces"].GetValue(i)]; + int e; + for (e = 0;e < sec.values.size();e++) + { + if (sec.GetValue(e)->GetLength() == 0) + { + toDelete.push_back(*sec.GetValueName(e)); + } + + + } + for (e = 0;e < toDelete.size();e++) + { + sec.values.erase(toDelete[e]); + } + } + + errstream << "LoadMap() loads graphics\n"; + errstream.flush(); + + CDynamicGraphDlg dlg(theApp.m_pMainWnd); + dlg.ShowWindow(SW_SHOW); + dlg.UpdateWindow(); + + theApp.m_loading->Unload(); + theApp.m_loading->InitMixFiles(); + + map::iterator it = pics.begin(); + for (int e = 0;e < pics.size();e++) + { + try + { +#ifdef NOSURFACES_OBJECTS + if (it->second.bType == PICDATA_TYPE_BMP) + { + if (it->second.pic != NULL) + { + ((LPDIRECTDRAWSURFACE4)it->second.pic)->Release(); + } + } + else + { + if (it->second.pic != NULL) + { + delete[] it->second.pic; + } + if (it->second.vborder) delete[] it->second.vborder; + } +#else + if (it->second.pic != NULL) it->second.pic->Release(); +#endif + + it->second.pic = NULL; + } + catch (...) + { + CString err; + err = "Access violation while trying to release surface "; + char c[6]; + itoa(e, c, 10); + err += c; + + err += "\n"; + OutputDebugString(err); + continue; + } + + it++; + } + + pics.clear(); + missingimages.clear(); + + theApp.m_loading->InitPics(); + + UpdateBuildingInfo(); + UpdateTreeInfo(); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->UpdateOverlayPictures(); + + + if (m_mapfile.sections["Map"].values["Theater"] == THEATER0) + { + tiledata = &s_tiledata; + tiledata_count = &s_tiledata_count; + tiles = &tiles_s; + theApp.m_loading->FreeTileSet(); + tiledata = &u_tiledata; + tiledata_count = &u_tiledata_count; + tiles = &tiles_u; + theApp.m_loading->FreeTileSet(); + + // MW new tilesets + tiledata = &un_tiledata; + tiledata_count = &un_tiledata_count; + tiles = &tiles_un; + theApp.m_loading->FreeTileSet(); + tiledata = &d_tiledata; + tiledata_count = &d_tiledata_count; + tiles = &tiles_d; + theApp.m_loading->FreeTileSet(); + tiledata = &l_tiledata; + tiledata_count = &l_tiledata_count; + tiles = &tiles_l; + theApp.m_loading->FreeTileSet(); + + tiledata = &t_tiledata; + tiledata_count = &t_tiledata_count; + tiles = &tiles_t; + theApp.m_loading->FreeTileSet(); + theApp.m_loading->InitTMPs(&dlg.m_Progress); + theApp.m_loading->cur_theat = 'T'; + + } + else if (m_mapfile.sections["Map"].values["Theater"] == THEATER1) + { + tiledata = &t_tiledata; + tiledata_count = &t_tiledata_count; + tiles = &tiles_t; + theApp.m_loading->FreeTileSet(); + tiledata = &u_tiledata; + tiledata_count = &u_tiledata_count; + tiles = &tiles_u; + theApp.m_loading->FreeTileSet(); + + // MW new tilesets + tiledata = &un_tiledata; + tiledata_count = &un_tiledata_count; + tiles = &tiles_un; + theApp.m_loading->FreeTileSet(); + tiledata = &d_tiledata; + tiledata_count = &d_tiledata_count; + tiles = &tiles_d; + theApp.m_loading->FreeTileSet(); + tiledata = &l_tiledata; + tiledata_count = &l_tiledata_count; + tiles = &tiles_l; + theApp.m_loading->FreeTileSet(); + + tiledata = &s_tiledata; + tiledata_count = &s_tiledata_count; + tiles = &tiles_s; + theApp.m_loading->FreeTileSet(); + theApp.m_loading->InitTMPs(&dlg.m_Progress); + theApp.m_loading->cur_theat = 'A'; + } + else if (m_mapfile.sections["Map"].values["Theater"] == THEATER2) + { + tiledata = &t_tiledata; + tiledata_count = &t_tiledata_count; + tiles = &tiles_t; + theApp.m_loading->FreeTileSet(); + tiledata = &s_tiledata; + tiledata_count = &s_tiledata_count; + tiles = &tiles_s; + theApp.m_loading->FreeTileSet(); + + // MW new tilesets + tiledata = &un_tiledata; + tiledata_count = &un_tiledata_count; + tiles = &tiles_un; + theApp.m_loading->FreeTileSet(); + tiledata = &d_tiledata; + tiledata_count = &d_tiledata_count; + tiles = &tiles_d; + theApp.m_loading->FreeTileSet(); + tiledata = &l_tiledata; + tiledata_count = &l_tiledata_count; + tiles = &tiles_l; + theApp.m_loading->FreeTileSet(); + + tiledata = &u_tiledata; + tiledata_count = &u_tiledata_count; + tiles = &tiles_u; + theApp.m_loading->FreeTileSet(); + theApp.m_loading->InitTMPs(&dlg.m_Progress); + theApp.m_loading->cur_theat = 'U'; + } + else if (yuri_mode && m_mapfile.sections["Map"].values["Theater"] == THEATER3) + { + tiledata = &t_tiledata; + tiledata_count = &t_tiledata_count; + tiles = &tiles_t; + theApp.m_loading->FreeTileSet(); + tiledata = &s_tiledata; + tiledata_count = &s_tiledata_count; + tiles = &tiles_s; + theApp.m_loading->FreeTileSet(); + + // MW new tilesets + + tiledata = &d_tiledata; + tiledata_count = &d_tiledata_count; + tiles = &tiles_d; + theApp.m_loading->FreeTileSet(); + tiledata = &l_tiledata; + tiledata_count = &l_tiledata_count; + tiles = &tiles_l; + theApp.m_loading->FreeTileSet(); + + tiledata = &u_tiledata; + tiledata_count = &u_tiledata_count; + tiles = &tiles_u; + theApp.m_loading->FreeTileSet(); + + tiledata = &un_tiledata; + tiledata_count = &un_tiledata_count; + tiles = &tiles_un; + theApp.m_loading->FreeTileSet(); + + theApp.m_loading->InitTMPs(&dlg.m_Progress); + theApp.m_loading->cur_theat = 'N'; + } + else if (yuri_mode && m_mapfile.sections["Map"].values["Theater"] == THEATER4) + { + tiledata = &t_tiledata; + tiledata_count = &t_tiledata_count; + tiles = &tiles_t; + theApp.m_loading->FreeTileSet(); + tiledata = &s_tiledata; + tiledata_count = &s_tiledata_count; + tiles = &tiles_s; + theApp.m_loading->FreeTileSet(); + + // MW new tilesets + tiledata = &un_tiledata; + tiledata_count = &un_tiledata_count; + tiles = &tiles_un; + theApp.m_loading->FreeTileSet(); + tiledata = &d_tiledata; + tiledata_count = &d_tiledata_count; + tiles = &tiles_d; + theApp.m_loading->FreeTileSet(); + + + tiledata = &u_tiledata; + tiledata_count = &u_tiledata_count; + tiles = &tiles_u; + theApp.m_loading->FreeTileSet(); + + tiledata = &l_tiledata; + tiledata_count = &l_tiledata_count; + tiles = &tiles_l; + theApp.m_loading->FreeTileSet(); + + theApp.m_loading->InitTMPs(&dlg.m_Progress); + theApp.m_loading->cur_theat = 'L'; + } + else if (m_mapfile.sections["Map"].values["Theater"] == THEATER5) + { + tiledata = &t_tiledata; + tiledata_count = &t_tiledata_count; + tiles = &tiles_t; + theApp.m_loading->FreeTileSet(); + tiledata = &s_tiledata; + tiledata_count = &s_tiledata_count; + tiles = &tiles_s; + theApp.m_loading->FreeTileSet(); + + // MW new tilesets + tiledata = &un_tiledata; + tiledata_count = &un_tiledata_count; + tiles = &tiles_un; + theApp.m_loading->FreeTileSet(); + + tiledata = &l_tiledata; + tiledata_count = &l_tiledata_count; + tiles = &tiles_l; + theApp.m_loading->FreeTileSet(); + + + tiledata = &u_tiledata; + tiledata_count = &u_tiledata_count; + tiles = &tiles_u; + theApp.m_loading->FreeTileSet(); + + tiledata = &d_tiledata; + tiledata_count = &d_tiledata_count; + tiles = &tiles_d; + theApp.m_loading->FreeTileSet(); + + theApp.m_loading->InitTMPs(&dlg.m_Progress); + theApp.m_loading->cur_theat = 'D'; + } + else + { + theApp.m_loading->FreeAll(); + CString s = "Fatal error! %9 doesn´t support the theater of this map!"; + s = TranslateStringACP(s); + MessageBox(0, s, "Error", 0); + exit(0); + } + dlg.DestroyWindow(); + + + + CalcMapRect(); + + isInitialized = TRUE; + + errstream << "LoadMap() allocates fielddata\n"; + errstream.flush(); + + fielddata = new(FIELDDATA[(GetIsoSize() + 1) * (GetIsoSize() + 1)]); + fielddata_size = (GetIsoSize() + 1) * (GetIsoSize() + 1); + + errstream << "LoadMap() unpacks data\n"; + errstream.flush(); + + + + Unpack(); + + errstream << "LoadMap() updates from ini\n"; + errstream.flush(); + + + UpdateIniFile(MAPDATA_UPDATE_FROM_INI); + +} + + + + +void CMapData::Unpack() +{ + if (!isInitialized) return; + + CMapLoadingDlg d; + d.ShowWindow(SW_SHOW); + d.UpdateWindow(); + + CString ovrl; + int i; + + + ovrl = ""; + + for (i = 0;i < m_mapfile.sections["OverlayPack"].values.size();i++) + { + ovrl += *m_mapfile.sections["OverlayPack"].GetValue(i); + } + + //BYTE values[262144]; + const size_t VALUESIZE = 262144; + std::vector values(VALUESIZE, 0xFF); + int hexlen; + + + if (ovrl.GetLength() > 0) + { + std::vector hex; + hexlen = FSunPackLib::DecodeBase64(ovrl, hex); + FSunPackLib::DecodeF80(hex.data(), hexlen, values, VALUESIZE); + values.resize(VALUESIZE, 0xFF); // fill rest + } + + memcpy(m_Overlay, values.data(), std::min(VALUESIZE, values.size())); + + ovrl = ""; + + for (i = 0;i < m_mapfile.sections["OverlayDataPack"].values.size();i++) + { + ovrl += *m_mapfile.sections["OverlayDataPack"].GetValue(i); + } + + values.assign(VALUESIZE, 0); + if (ovrl.GetLength() > 0) + { + std::vector hex; + + hexlen = FSunPackLib::DecodeBase64(ovrl, hex); + FSunPackLib::DecodeF80(hex.data(), hexlen, values, VALUESIZE); + values.resize(VALUESIZE, 0xFF); // fill rest + } + + memcpy(m_OverlayData, values.data(), std::min(VALUESIZE, values.size())); + + + CString IsoMapPck; + int len_needed = 0; + + CIniFileSection& sec = m_mapfile.sections["IsoMapPack5"]; + int lines = sec.values.size(); + + /*char c[50]; + itoa(m_mapfile.sections["IsoMapPack5"].values.size(), c, 10); + MessageBox(0,c,"",0);*/ + + for (i = 0;i < lines;i++) + { + len_needed += sec.GetValue(i)->GetLength(); + } + + LPSTR lpMapPack = new(char[len_needed + 1]); + memset(lpMapPack, 0, len_needed + 1); + + int cur_pos = 0; + for (i = 0;i < lines;i++) + { + memcpy(lpMapPack + cur_pos, (LPCSTR)*sec.GetValue(i), sec.GetValue(i)->GetLength()); + cur_pos += sec.GetValue(i)->GetLength(); + DoEvents(); + + //IsoMapPck+=*sec.GetValue(i); + } + + IsoMapPck = lpMapPack; + + delete[] lpMapPack; + + + if (m_mfd != NULL) delete[] m_mfd; + m_mfd = NULL; + dwIsoMapSize = 0; + + if (IsoMapPck.GetLength() > 0) + { + std::vector hexC; + + //DoEvents(); + + hexlen = FSunPackLib::DecodeBase64(IsoMapPck, hexC); + + // first let´s find out the size of the mappack data + const auto hex = hexC.data(); + int SP = 0; + int MapSizeBytes = 0; + int sec = 0; + while (SP < hexlen) + { + WORD wSrcSize; + WORD wDestSize; + memcpy(&wSrcSize, hex + SP, 2); + SP += 2; + memcpy(&wDestSize, hex + SP, 2); + SP += 2; + + MapSizeBytes += wDestSize; + SP += wSrcSize; + + sec++; + } + + m_mfd = new(BYTE[MapSizeBytes]); + dwIsoMapSize = MapSizeBytes / MAPFIELDDATA_SIZE; + + FSunPackLib::DecodeIsoMapPack5(hex, hexlen, (BYTE*)m_mfd, d.m_Progress.m_hWnd, TRUE); + + int k; + /*fstream f; + f.open("C:\\isomappack5.txt",ios_base::in | ios_base::out | ios_base::trunc); + for(k=0;k<150;k++) + { + f << "Byte " << k << ": " << (int)m_mfd[k] << endl; + } + f.flush();*/ + } + + d.DestroyWindow(); + +} + + + + + + +void CMapData::Pack(BOOL bCreatePreview, BOOL bCompression) +{ + if (!isInitialized) return; + + errstream << "Erasing sections" << endl; + errstream.flush(); + + int i; + BYTE* base64 = NULL; // must be freed! + + m_mapfile.sections.erase("OverlayPack"); + m_mapfile.sections.erase("OverlayDataPack"); + m_mapfile.sections.erase("IsoMapPack5"); // only activate when packing isomappack is supported + + DWORD pos; + + errstream << "Creating Digest" << endl; + errstream.flush(); + + if (m_mapfile.sections["Digest"].values.size() == 0) + { + srand(GetTickCount()); + unsigned short vals[10]; + for (i = 0;i < 10;i++) + vals[i] = rand() * 65536 / RAND_MAX; + + base64 = FSunPackLib::EncodeBase64((BYTE*)vals, 20); + + i = 0; + pos = 0; + while (TRUE) + { + i++; + char cLine[50]; + itoa(i, cLine, 10); + char str[200]; + memset(str, 0, 200); + WORD cpysize = 70; + if (pos + cpysize > strlen((char*)base64)) cpysize = strlen((char*)base64) - pos; + memcpy(str, &base64[pos], cpysize); + if (strlen(str) > 0) + m_mapfile.sections["Digest"].values[cLine] = str; + if (cpysize < 70) break; + pos += 70; + } + + delete[] base64; + base64 = NULL; + } + + + BYTE* values = new(BYTE[262144]); + BYTE* hexpacked = NULL; // must be freed! + + + errstream << "Values allocated. Pointer: " << (int)values << endl; + errstream.flush(); + + + errstream << "Packing overlay" << endl; + errstream.flush(); + + for (i = 0;i < 262144;i++) + { + values[i] = m_Overlay[i]; + } + + int hexpackedLen = FSunPackLib::EncodeF80(values, 262144, 32, &hexpacked); + base64 = FSunPackLib::EncodeBase64(hexpacked, hexpackedLen); + + + errstream << "Saving overlay" << endl; + + i = 0; + pos = 0; + while (TRUE) + { + i++; + char cLine[50]; + itoa(i, cLine, 10); + char str[200]; + memset(str, 0, 200); + WORD cpysize = 70; + if (pos + cpysize > strlen((char*)base64)) cpysize = strlen((char*)base64) - pos; + memcpy(str, &base64[pos], cpysize); + if (strlen(str) > 0) + m_mapfile.sections["OverlayPack"].values[cLine] = str; + if (cpysize < 70) break; + pos += 70; + } + + + +#ifndef _DEBUG__ + delete[] hexpacked; + delete[] base64; +#endif + + errstream << "Pack overlaydata" << endl; + errstream.flush(); + + for (i = 0;i < 262144;i++) + { + values[i] = m_OverlayData[i]; + } + + hexpacked = NULL; + + errstream << "Format80" << endl; + errstream.flush(); + + hexpackedLen = FSunPackLib::EncodeF80(values, 262144, 32, &hexpacked); + + + errstream << "Base64" << endl; + errstream.flush(); + + base64 = FSunPackLib::EncodeBase64(hexpacked, hexpackedLen); + + + errstream << "Overlaydata done" << endl; + errstream.flush(); + + i = 0; + pos = 0; + while (TRUE) + { + i++; + char cLine[50]; + itoa(i, cLine, 10); + char str[200]; + memset(str, 0, 200); + WORD cpysize = 70; + if (pos + cpysize > strlen((char*)base64)) cpysize = strlen((char*)base64) - pos; + memcpy(str, &base64[pos], cpysize); + if (strlen(str) > 0) + m_mapfile.sections["OverlayDataPack"].values[cLine] = str; + if (cpysize < 70) break; + pos += 70; + } + + +#ifndef _DEBUG__ + delete[] hexpacked; + delete[] base64; +#endif + + hexpacked = NULL; + + errstream << "Pack isomappack" << endl; + errstream.flush(); + + + hexpackedLen = FSunPackLib::EncodeIsoMapPack5(m_mfd, dwIsoMapSize * MAPFIELDDATA_SIZE, &hexpacked); + + + errstream << "done" << endl; + errstream.flush(); + + errstream << "hexdata size: " << hexpackedLen; + errstream << endl << "Now converting to base64"; + errstream.flush(); + base64 = FSunPackLib::EncodeBase64(hexpacked, hexpackedLen); + errstream << "done" << endl; + errstream.flush(); + + i = 0; + pos = 0; + int base64len = strlen((char*)base64); + while (TRUE) + { + i++; + char cLine[50]; + itoa(i, cLine, 10); + char str[200]; + memset(str, 0, 200); + int cpysize = 70; + if (pos + cpysize > base64len) cpysize = base64len - pos; + memcpy(str, &base64[pos], cpysize); + if (cpysize) + m_mapfile.sections["IsoMapPack5"].values[cLine] = str; + + if (cpysize < 70) break; + pos += 70; + } + + errstream << "finished copying into inifile" << endl; + errstream.flush(); + + +#ifndef _DEBUG__ + delete[] hexpacked; + delete[] base64; +#endif + + + // create minimap + if (bCreatePreview) + { + BITMAPINFO biinfo; + BYTE* lpDibData; + int pitch; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_minimap.DrawMinimap(&lpDibData, biinfo, pitch); + + m_mapfile.sections.erase("PreviewPack"); + m_mapfile.sections["Preview"].values["Size"] = m_mapfile.sections["Map"].values["Size"]; + char c[50]; + itoa(biinfo.bmiHeader.biWidth, c, 10); + m_mapfile.sections["Preview"].values["Size"] = SetParam(m_mapfile.sections["Preview"].values["Size"], 2, c); + itoa(biinfo.bmiHeader.biHeight, c, 10); + m_mapfile.sections["Preview"].values["Size"] = SetParam(m_mapfile.sections["Preview"].values["Size"], 3, c); + + BYTE* lpRAW = new(BYTE[biinfo.bmiHeader.biWidth * biinfo.bmiHeader.biHeight * 3]); + + int mapwidth = GetWidth(); + int mapheight = GetHeight(); + int e; + for (i = 0;i < biinfo.bmiHeader.biWidth;i++) + { + for (e = 0;e < biinfo.bmiHeader.biHeight;e++) + { + int dest = i * 3 + e * biinfo.bmiHeader.biWidth * 3; + int src = i * 3 + (biinfo.bmiHeader.biHeight - e - 1) * pitch; + memcpy(&lpRAW[dest + 2], &lpDibData[src + 0], 1); + memcpy(&lpRAW[dest + 1], &lpDibData[src + 1], 1); + memcpy(&lpRAW[dest + 0], &lpDibData[src + 2], 1); + } + } + + + hexpacked = NULL; + hexpackedLen = FSunPackLib::EncodeIsoMapPack5(lpRAW, biinfo.bmiHeader.biWidth * biinfo.bmiHeader.biHeight * 3, &hexpacked); + + base64 = FSunPackLib::EncodeBase64(hexpacked, hexpackedLen); + + // uses IsoMapPack5 encoding routine + + + errstream << "Saving minimap" << endl; + + i = 0; + pos = 0; + while (TRUE) + { + i++; + char cLine[50]; + itoa(i, cLine, 10); + char str[200]; + memset(str, 0, 200); + WORD cpysize = 70; + if (pos + cpysize > strlen((char*)base64)) cpysize = strlen((char*)base64) - pos; + memcpy(str, &base64[pos], cpysize); + if (strlen(str) > 0) + m_mapfile.sections["PreviewPack"].values[cLine] = str; + if (cpysize < 70) break; + pos += 70; + } + + + + //#ifndef _DEBUG__ + delete[] base64; + delete[] hexpacked; + //#endif + + + delete[] lpRAW; + //delete[] lpDibData; + } + + delete[] values; +} + +void CMapData::ClearOverlayData() +{ + memset(m_OverlayData, 0x0, 262144); + // Pack(); +} + +void CMapData::ClearOverlay() +{ + memset(m_Overlay, 0xFF, 262144); + // Pack(); +} + +void CMapData::SetOverlayAt(DWORD dwPos, BYTE bValue) +{ + int y = dwPos / m_IsoSize; + int x = dwPos % m_IsoSize; + + if (y + x * 512 > 262144 || dwPos > m_IsoSize * m_IsoSize) return; + + BYTE& ovrl = m_Overlay[y + x * 512]; + BYTE& ovrld = m_OverlayData[y + x * 512]; + + + RemoveOvrlMoney(ovrl, ovrld); + + + m_Overlay[y + x * 512] = bValue; + m_OverlayData[y + x * 512] = 0; + fielddata[dwPos].overlay = bValue; + fielddata[dwPos].overlaydata = 0; + + BYTE& ovrl2 = m_Overlay[y + x * 512]; + BYTE& ovrld2 = m_OverlayData[y + x * 512]; + AddOvrlMoney(ovrl2, ovrld2); + + int i, e; + for (i = -1;i < 2;i++) + for (e = -1;e < 2;e++) + if (i + x > 0 && i + x < m_IsoSize && y + e >= 0 && y + e < m_IsoSize) + SmoothTiberium(dwPos + i + e * m_IsoSize); + + + + + + + + Mini_UpdatePos(x, y, IsMultiplayer()); + +} + +BYTE CMapData::GetOverlayAt(DWORD dwPos) +{ + if (dwPos > fielddata_size) return 0; + return fielddata[dwPos].overlay; +} + +void CMapData::SetOverlayDataAt(DWORD dwPos, BYTE bValue) +{ + + int y = dwPos / m_IsoSize; + int x = dwPos % m_IsoSize; + + if (y + x * 512 > 262144 || dwPos > m_IsoSize * m_IsoSize) return; + + BYTE& ovrl = m_Overlay[y + x * 512]; + BYTE& ovrld = m_OverlayData[y + x * 512]; + + if (ovrl >= RIPARIUS_BEGIN && ovrl <= RIPARIUS_END) + { + //m_money-=(ovrld+1)*(atoi(rules.sections["Riparius"].values["Value"])); + return; + } + + if (ovrl >= CRUENTUS_BEGIN && ovrl <= CRUENTUS_END) + { + //m_money-=(ovrld+1)*(atoi(rules.sections["Cruentus"].values["Value"])); + return; + } + + if (ovrl >= VINIFERA_BEGIN && ovrl <= VINIFERA_END) + { + //m_money-=(ovrld+1)*(atoi(rules.sections["Vinifera"].values["Value"])); + return; + } + + if (ovrl >= ABOREUS_BEGIN && ovrl <= ABOREUS_END) + { + //m_money-=(ovrld+1)*(atoi(rules.sections["Aboreus"].values["Value"])); + return; + } + + m_OverlayData[y + x * 512] = bValue; + fielddata[dwPos].overlaydata = bValue; + + BYTE& ovrl2 = m_Overlay[y + x * 512]; + BYTE& ovrld2 = m_OverlayData[y + x * 512]; + + + /*if(ovrl2>=RIPARIUS_BEGIN && ovrl2<=RIPARIUS_END) + { + m_money+=(ovrld2+1)*(atoi(rules.sections["Riparius"].values["Value"])); + } + + if(ovrl2>=CRUENTUS_BEGIN && ovrl2<=CRUENTUS_END) + { + m_money+=(ovrld2+1)*(atoi(rules.sections["Cruentus"].values["Value"])); + } + + if(ovrl2>=VINIFERA_BEGIN && ovrl2<=VINIFERA_END) + { + m_money+=(ovrld2+1)*(atoi(rules.sections["Vinifera"].values["Value"])); + } + + if(ovrl2>=ABOREUS_BEGIN && ovrl2<=ABOREUS_END) + { + m_money+=(ovrld2+1)*(atoi(rules.sections["Aboreus"].values["Value"])); + }*/ + + +} + +BYTE CMapData::GetOverlayDataAt(DWORD dwPos) +{ + return fielddata[dwPos].overlaydata; +} + +/* +UpdateInfantry(); + +Updates the tiledata if bSave==FALSE (standard) according to the mapfile. +If bSave==TRUE, nothing is done at the moment (would be for updating the mapfile, but not needed yet, + because the mapfile is modified directly) +*/ +void CMapData::UpdateInfantry(BOOL bSave) +{ + vector& iv = m_infantry; + + if (bSave == FALSE) + { + iv.clear(); + iv.reserve(100); + + int i; + for (i = 0;i < GetIsoSize() * GetIsoSize();i++) + { + int e; + for (e = 0;e < SUBPOS_COUNT;e++) + fielddata[i].infantry[e] = -1; + } + + + if (m_mapfile.sections.find("Infantry") != m_mapfile.sections.end()) + { + CIniFileSection& sec = m_mapfile.sections["Infantry"]; + + for (i = 0;i < sec.values.size();i++) + { + CString data = *sec.GetValue(i); + + int x = atoi(GetParam(data, 4)); + int y = atoi(GetParam(data, 3)); + int sp = atoi(GetParam(data, 5)); + int pos = x + y * GetIsoSize(); + + INFANTRY id; + id.deleted = 0; + id.house = GetParam(data, 0); + id.type = GetParam(data, 1); + id.strength = GetParam(data, 2); + id.y = GetParam(data, 3); + id.x = GetParam(data, 4); + id.pos = GetParam(data, 5); + id.action = GetParam(data, 6); + id.direction = GetParam(data, 7); + id.tag = GetParam(data, 8); + id.flag1 = GetParam(data, 9); + id.flag2 = GetParam(data, 10); + id.flag3 = GetParam(data, 11); + id.flag4 = GetParam(data, 12); + id.flag5 = GetParam(data, 13); + + iv.push_back(id); + + int spp = sp - 1; + if (spp < 0) spp = 0; + + if (spp < SUBPOS_COUNT) + if (pos < fielddata_size) + fielddata[pos].infantry[spp] = iv.size() - 1; + + Mini_UpdatePos(x, y, IsMultiplayer()); + + + + /*else + { + int e; + for(e=0;em_view.m_isoview->GetColor(GetParam(*sec.GetValue(i), 0)); + sp.strength = atoi(GetParam(*sec.GetValue(i), 2)); + sp.upgrade1 = GetParam(*sec.GetValue(i), 12); + sp.upgrade2 = GetParam(*sec.GetValue(i), 13); + sp.upgrade3 = GetParam(*sec.GetValue(i), 14); + sp.upradecount = atoi(GetParam(*sec.GetValue(i), 10)); + sp.x = atoi(GetParam(*sec.GetValue(i), 4)); + sp.y = atoi(GetParam(*sec.GetValue(i), 3)); + sp.direction = atoi(GetParam(*sec.GetValue(i), 5)); + sp.type = GetParam(*sec.GetValue(i), 1); + + TruncSpace(sp.upgrade1); + TruncSpace(sp.upgrade2); + TruncSpace(sp.upgrade3); + + m_structurepaint.push_back(sp); + + int x = atoi(GetParam(*sec.GetValue(i), 4)); + int y = atoi(GetParam(*sec.GetValue(i), 3)); + int d, e; + int bid = buildingid[GetParam(*sec.GetValue(i), 1)]; + for (d = 0;d < buildinginfo[bid].h;d++) + { + for (e = 0;e < buildinginfo[bid].w;e++) + { + int pos = (x + d) + (y + e) * GetIsoSize(); + if (pos < fielddata_size) + { + fielddata[pos].structure = i; + fielddata[pos].structuretype = bid; + } + + Mini_UpdatePos(x + d, y + e, IsMultiplayer()); + } + } + + + } + } + } +} + +void CMapData::UpdateTerrain(BOOL bSave, int num) +{ + vector& t = m_terrain; + + if (bSave == FALSE) + { + if (m_mapfile.sections.find("Terrain") == m_mapfile.sections.end() || m_mapfile.sections["Terrain"].values.size() <= 0) + return; + + if (num < 0) + { + t.clear(); + t.reserve(100); + + int i; + for (i = 0;i < GetIsoSize() * GetIsoSize();i++) + { + fielddata[i].terrain = -1; + } + + + + CIniFileSection& sec = m_mapfile.sections["Terrain"]; + + for (i = 0;i < sec.values.size();i++) + { + int x, y; + PosToXY(*sec.GetValueName(i), &x, &y); + + // check for valid coordinates ; MW May 17th 2001 + ASSERT(x >= 0 && x < GetIsoSize()); + ASSERT(y >= 0 && y < GetIsoSize()); + if (x < 0 || x >= GetIsoSize() || y < 0 || y >= GetIsoSize()) + { + // invalid coordinates - ignore in release + } + else + { + TERRAIN td; + td.deleted = 0; + td.type = *sec.GetValue(i); + td.x = x; + td.y = y; + + t.push_back(td); + + int pos = x + y * GetIsoSize(); + fielddata[pos].terrain = i; + fielddata[pos].terraintype = terrainid[td.type]; + } + } + + m_mapfile.sections.erase("Terrain"); + + } + + } + else + { + + //if(num<0) + { + //if(m_mapfile.sections.find("Terrain")!=m_mapfile.sections.end()) MessageBox(0,"Reupdate!","",0); + m_mapfile.sections.erase("Terrain"); + int i; + + for (i = 0;i < t.size();i++) + { + TERRAIN& td = t[i]; + if (!td.deleted) + { + char j1[15]; + char k1[15]; + + int x, y; + x = td.x; + y = td.y; + + itoa(y, j1, 10); + if (strlen(j1) < 3) + { + strcpy_safe(j1 + 1, j1); + j1[0] = '0'; + } + if (strlen(j1) < 3) + { + strcpy_safe(j1 + 1, j1); + j1[0] = '0'; + } + itoa(x, k1, 10); + strcat(k1, j1); + + + m_mapfile.sections["Terrain"].values[k1] = td.type; + } + } + } + + } +} + +void CMapData::UpdateUnits(BOOL bSave) +{ + if (bSave == FALSE) + { + int i; + for (i = 0;i < GetIsoSize() * GetIsoSize();i++) + { + fielddata[i].unit = -1; + } + + + if (m_mapfile.sections.find("Units") != m_mapfile.sections.end()) + { + CIniFileSection& sec = m_mapfile.sections["Units"]; + + for (i = 0;i < sec.values.size();i++) + { + int x = atoi(GetParam(*sec.GetValue(i), 4)); + int y = atoi(GetParam(*sec.GetValue(i), 3)); + int pos = x + y * GetIsoSize(); + if (pos < fielddata_size) fielddata[pos].unit = i; + + Mini_UpdatePos(x, y, IsMultiplayer()); + } + } + } + +} + +void CMapData::UpdateWaypoints(BOOL bSave) +{ + if (bSave == FALSE) + { + int i; + for (i = 0;i < GetIsoSize() * GetIsoSize();i++) + { + fielddata[i].waypoint = -1; + } + + + if (m_mapfile.sections.find("Waypoints") != m_mapfile.sections.end()) + { + CIniFileSection& sec = m_mapfile.sections["Waypoints"]; + + for (i = 0;i < sec.values.size();i++) + { + int x, y; + PosToXY(*sec.GetValue(i), &x, &y); + + int pos = x + y * GetIsoSize(); + if (pos < 0 || pos >= fielddata_size) continue; + fielddata[pos].waypoint = i; + + int k, l; + for (k = -1;k < 2;k++) + for (l = -1;l < 2;l++) + Mini_UpdatePos(x + k, y + l, IsMultiplayer()); + } + } + } + +} + +void CMapData::UpdateNodes(BOOL bSave) +{ + if (bSave == FALSE) + { + int i; + + for (i = 0;i < GetIsoSize() * GetIsoSize();i++) + { + fielddata[i].node.index = -1; + fielddata[i].node.type = -1; + fielddata[i].node.house = ""; + } + + if (m_mapfile.sections.find(MAPHOUSES) != m_mapfile.sections.end()) + { + + for (i = 0;i < m_mapfile.sections[MAPHOUSES].values.size();i++) + { + CIniFileSection& sec = m_mapfile.sections[*m_mapfile.sections[MAPHOUSES].GetValue(i)]; + int c = atoi(sec.values["NodeCount"]); + + int e; + for (e = 0;e < c;e++) + { + CString p; + GetNodeName(p, e); + + CString type, sx, sy; + type = GetParam(sec.values[p], 0); + sy = GetParam(sec.values[p], 1); + sx = GetParam(sec.values[p], 2); + + int x = atoi(sx); + int y = atoi(sy); + int bid = buildingid[type]; + int d, f; + for (d = 0;d < buildinginfo[bid].h;d++) + { + for (f = 0;f < buildinginfo[bid].w;f++) + { + int pos = x + d + (y + f) * GetIsoSize(); + fielddata[pos].node.type = buildingid[type]; + fielddata[pos].node.house = *m_mapfile.sections[MAPHOUSES].GetValue(i); + fielddata[pos].node.index = e; + } + } + } + } + } + } + +} + +void CMapData::UpdateOverlay(BOOL bSave) +{ + if (bSave == FALSE) + { + int u, v; + const bool mp = IsMultiplayer(); + for (u = 0;u < GetIsoSize();u++) + { + for (v = 0;v < GetIsoSize();v++) + { + fielddata[u + v * GetIsoSize()].overlay = m_Overlay[v + u * 512]; + fielddata[u + v * GetIsoSize()].overlaydata = m_OverlayData[v + u * 512]; + + Mini_UpdatePos(u, v, mp); + + } + } + } + else + { + int u, v; + for (u = 0;u < GetIsoSize();u++) + { + for (v = 0;v < GetIsoSize();v++) + { + m_Overlay[v + u * 512] = fielddata[u + v * GetIsoSize()].overlay; + m_OverlayData[v + u * 512] = fielddata[u + v * GetIsoSize()].overlaydata; + } + } + } + + m_money = CalcMoneyOnMap(); + +} + + +void CMapData::UpdateCelltags(BOOL bSave) +{ + if (bSave == FALSE) + { + int i; + for (i = 0;i < GetIsoSize() * GetIsoSize();i++) + { + fielddata[i].celltag = -1; + } + + + if (m_mapfile.sections.find("CellTags") != m_mapfile.sections.end()) + { + CIniFileSection& sec = m_mapfile.sections["CellTags"]; + + for (i = 0;i < sec.values.size();i++) + { + int x, y; + PosToXY(*sec.GetValueName(i), &x, &y); + + int pos = x + y * GetIsoSize(); + if (pos < fielddata_size) fielddata[pos].celltag = i; + } + } + } +} + + +INT CMapData::GetNodeAt(DWORD dwPos, CString& lpHouse) const +{ + lpHouse = fielddata[dwPos].node.house; + return fielddata[dwPos].node.index; +} + + + +void CMapData::DeleteInfantry(DWORD dwIndex) +{ + //if(dwIndex>=m_infantry.size()) MessageBox(0,"CMapData::DeleteInfantry(): Out of range error", "Error", 0); + + if (dwIndex >= m_infantry.size()) return; + + // BUG TRACING HERE, FOR THE COPY INSTEAD MOVE INFANTRY BUG! + // SOLUTION WAS IN ADDINFANTRY(); + if (m_infantry[dwIndex].deleted) + { + //MessageBox(0,"CMapData::DeleteInfantry() called for infantry that already got deleted!", "Error",0); + errstream << "CMapData::DeleteInfantry() called for infantry that already got deleted! Index: " << dwIndex << endl; + errstream.flush(); + } + + if (m_infantry[dwIndex].deleted) return; + + + + m_infantry[dwIndex].deleted = 1; + + int x = atoi(m_infantry[dwIndex].x); + int y = atoi(m_infantry[dwIndex].y); + int pos = atoi(m_infantry[dwIndex].pos); + + if (pos > 0) pos--; + + if (x + y * m_IsoSize < fielddata_size) fielddata[x + y * m_IsoSize].infantry[pos] = -1; + + Mini_UpdatePos(x, y, IsMultiplayer()); + + /*if(dwIndex>=m_mapfile.sections["Infantry"].values.size()) return; + + CIniFileSection& sec=m_mapfile.sections["Infantry"]; + int x=atoi(GetParam(*sec.GetValue(dwIndex),4)); + int y=atoi(GetParam(*sec.GetValue(dwIndex),3)); + + + m_mapfile.sections["Infantry"].values.erase(*m_mapfile.sections["Infantry"].GetValueName(dwIndex)); + UpdateInfantry(FALSE);*/ + + +} + +void CMapData::DeleteWaypoint(DWORD dwIndex) +{ + if (dwIndex >= GetWaypointCount()) return; + + CString id; + DWORD pos; + Map->GetWaypointData(dwIndex, &id, &pos); + + int x = pos % m_IsoSize; + int y = pos / m_IsoSize; + + + + m_mapfile.sections["Waypoints"].values.erase(*m_mapfile.sections["Waypoints"].GetValueName(dwIndex)); + if (!m_noAutoObjectUpdate) UpdateWaypoints(FALSE); + + int k, l; + for (k = -1;k < 2;k++) + for (l = -1;l < 2;l++) + Mini_UpdatePos(x + k, y + l, IsMultiplayer()); +} + +void CMapData::DeleteCelltag(DWORD dwIndex) +{ + if (dwIndex >= GetCelltagCount()) return; + + m_mapfile.sections["CellTags"].values.erase(*m_mapfile.sections["CellTags"].GetValueName(dwIndex)); + if (!m_noAutoObjectUpdate) UpdateCelltags(FALSE); +} + +void CMapData::DeleteUnit(DWORD dwIndex) +{ + if (dwIndex >= GetUnitCount()) return; + + CIniFileSection& sec = m_mapfile.sections["Units"]; + int x = atoi(GetParam(*sec.GetValue(dwIndex), 4)); + int y = atoi(GetParam(*sec.GetValue(dwIndex), 3)); + + + m_mapfile.sections["Units"].values.erase(*m_mapfile.sections["Units"].GetValueName(dwIndex)); + if (!m_noAutoObjectUpdate) UpdateUnits(FALSE); + + Mini_UpdatePos(x, y, IsMultiplayer()); +} + +void CMapData::DeleteStructure(DWORD dwIndex) +{ + if (dwIndex >= GetStructureCount()) return; + + CIniFileSection& sec = m_mapfile.sections["Structures"]; + int x = atoi(GetParam(*sec.GetValue(dwIndex), 4)); + int y = atoi(GetParam(*sec.GetValue(dwIndex), 3)); + CString type = GetParam(*sec.GetValue(dwIndex), 1); + + m_mapfile.sections["Structures"].values.erase(*m_mapfile.sections["Structures"].GetValueName(dwIndex)); + if (!m_noAutoObjectUpdate) UpdateStructures(FALSE); + + int d, e; + int bid = buildingid[type]; + for (d = 0;d < buildinginfo[bid].h;d++) + { + for (e = 0;e < buildinginfo[bid].w;e++) + { + int pos = (x + d) + (y + e) * GetIsoSize(); + + Mini_UpdatePos(x + d, y + e, IsMultiplayer()); + } + } +} + +void CMapData::DeleteAircraft(DWORD dwIndex) +{ + if (dwIndex >= GetAircraftCount()) return; + + CIniFileSection& sec = m_mapfile.sections["Aircraft"]; + int x = atoi(GetParam(*sec.GetValue(dwIndex), 4)); + int y = atoi(GetParam(*sec.GetValue(dwIndex), 3)); + + + m_mapfile.sections["Aircraft"].values.erase(*m_mapfile.sections["Aircraft"].GetValueName(dwIndex)); + if (!m_noAutoObjectUpdate) UpdateAircraft(FALSE); + + Mini_UpdatePos(x, y, IsMultiplayer()); +} + +void CMapData::DeleteTerrain(DWORD dwIndex) +{ + /* March 23th 2001: MW: Rewrote code, much faster */ + if (dwIndex >= GetTerrainCount()) return; + if (m_terrain[dwIndex].deleted) return; + + //UpdateTerrain(FALSE); + // replacement of slow UpdateTerrain(): + + //CString valuename=*m_mapfile.sections["Terrain"].GetValueName(dwIndex); + + int x, y; + //PosToXY(valuename, &x, &y); + //m_mapfile.sections["Terrain"].values.erase(valuename); + x = m_terrain[dwIndex].x; + y = m_terrain[dwIndex].y; + m_terrain[dwIndex].deleted = 1; + + int pos = x + y * GetIsoSize(); + if (x + y * m_IsoSize < fielddata_size) + { + fielddata[pos].terrain = -1; + fielddata[pos].terraintype = -1; + } + +} + +void CMapData::DeleteNode(LPCTSTR lpHouse, DWORD dwIndex) +{ + CString p; // p is last node + GetNodeName(p, atoi(m_mapfile.sections[lpHouse].values["NodeCount"]) - 1); + + char c[50]; + itoa(atoi(m_mapfile.sections[lpHouse].values["NodeCount"]) - 1, c, 10); + + int i; + for (i = dwIndex;i < atoi(m_mapfile.sections[lpHouse].values["NodeCount"]) - 1;i++) + { + CString d1, d2; + GetNodeName(d1, i); + GetNodeName(d2, i + 1); + m_mapfile.sections[lpHouse].values[d1] = m_mapfile.sections[lpHouse].values[d2]; + } + + m_mapfile.sections[lpHouse].values.erase(p); + m_mapfile.sections[lpHouse].values["NodeCount"] = c; + + UpdateNodes(FALSE); +} + +BOOL CMapData::AddWaypoint(CString lpID, DWORD dwPos) +{ + // create waypoint, auto number + CString id = lpID; + + + if (lpID.GetLength() == 0) id = GetFree("Waypoints"); + + + char j[15]; + char k[15]; + memset(j, 0, 15); + memset(k, 0, 15); + itoa(dwPos / GetIsoSize(), j, 10); + if (strlen(j) < 3) + { + strcpy_safe(j + 1, j); + j[0] = '0'; + } + if (strlen(j) < 3) + { + strcpy_safe(j + 1, j); + j[0] = '0'; + } + itoa(dwPos % GetIsoSize(), k, 10); + strcat(k, j); + + //MessageBox(0,k,"",0); + + + m_mapfile.sections["Waypoints"].values[id] = k; + if (!m_noAutoObjectUpdate) UpdateWaypoints(FALSE); + + return TRUE; +} + + + +void CMapData::GetStructureData(DWORD dwIndex, STRUCTURE* lpStructure) const +{ + const auto section = m_mapfile.GetSection("Structures"); + if (!section || dwIndex >= section->values.size()) + return; + + CString data = *section->GetValue(dwIndex); + + lpStructure->house = GetParam(data, 0); + lpStructure->type = GetParam(data, 1); + lpStructure->strength = GetParam(data, 2); + lpStructure->y = GetParam(data, 3); + lpStructure->x = GetParam(data, 4); + lpStructure->direction = GetParam(data, 5); + lpStructure->tag = GetParam(data, 6); + lpStructure->flag1 = GetParam(data, 7); + lpStructure->flag2 = GetParam(data, 8); + lpStructure->energy = GetParam(data, 9); + lpStructure->upgradecount = GetParam(data, 10); + lpStructure->spotlight = GetParam(data, 11); + lpStructure->upgrade1 = GetParam(data, 12); + lpStructure->upgrade2 = GetParam(data, 13); + lpStructure->upgrade3 = GetParam(data, 14); + lpStructure->flag3 = GetParam(data, 15); + lpStructure->flag4 = GetParam(data, 16); + +} + +void CMapData::GetStdStructureData(DWORD dwIndex, STDOBJECTDATA* lpStdStructure) const +{ + const auto section = m_mapfile.GetSection("Structures"); + if (!section || dwIndex >= section->values.size()) + return; + + CString data = *section->GetValue(dwIndex); + + lpStdStructure->house = GetParam(data, 0); + lpStdStructure->type = GetParam(data, 1); + lpStdStructure->strength = GetParam(data, 2); + lpStdStructure->y = GetParam(data, 3); + lpStdStructure->x = GetParam(data, 4); +} + +BOOL CMapData::AddNode(NODE* lpNode, WORD dwPos) +{ + NODE node; + if (lpNode != NULL) + { + node = *lpNode; + } + else + { + node.x.Format("%d", dwPos % Map->GetIsoSize()); + node.y.Format("%d", dwPos / Map->GetIsoSize()); + node.house = GetHouseID(0); + node.type = *rules.sections["BuildingTypes"].GetValue(0); + } + + if (m_mapfile.sections.find(HOUSES) == m_mapfile.sections.end() || m_mapfile.sections[HOUSES].values.size() == 0) + { + return FALSE; + } + + + int c = atoi(m_mapfile.sections[(LPCTSTR)node.house].values["NodeCount"]); + + c++; + char sc[50]; + itoa(c, sc, 10); + m_mapfile.sections[(LPCTSTR)node.house].values["NodeCount"] = sc; + + c--; + CString p; + GetNodeName(p, c); + + + m_mapfile.sections[(LPCTSTR)node.house].values[p] = node.type; + m_mapfile.sections[(LPCTSTR)node.house].values[p] += ","; + m_mapfile.sections[(LPCTSTR)node.house].values[p] += node.y; + m_mapfile.sections[(LPCTSTR)node.house].values[p] += ","; + m_mapfile.sections[(LPCTSTR)node.house].values[p] += node.x; + + UpdateNodes(FALSE); + + return TRUE; +} + +BOOL CMapData::AddInfantry(INFANTRY* lpInfantry, LPCTSTR lpType, LPCTSTR lpHouse, DWORD dwPos, int suggestedIndex) +{ + + INFANTRY infantry; + if (lpInfantry != NULL) + { + infantry = *lpInfantry; + dwPos = atoi(infantry.x) + atoi(infantry.y) * Map->GetIsoSize(); + + // MW Bugfix: not checking if infantry.pos does already exist caused crashes with user scripts! + if (GetInfantryAt(dwPos, atoi(infantry.pos)) >= 0) + infantry.pos = "-1"; + } + else + { + char cx[10], cy[10]; + itoa(dwPos % Map->GetIsoSize(), cx, 10); + itoa(dwPos / Map->GetIsoSize(), cy, 10); + + + + infantry.action = "Guard"; + infantry.tag = "None"; + infantry.direction = "64"; + infantry.flag1 = "0"; + infantry.flag2 = "-1"; + infantry.flag3 = "0"; + infantry.flag4 = "1"; + infantry.flag5 = "0"; + infantry.strength = "256"; + infantry.house = lpHouse; + infantry.pos = "-1"; + infantry.type = lpType; + infantry.x = cx; + infantry.y = cy; + + + } + + if (infantry.pos == "-1") + { + int subpos = -1; + int i; + + if (GetInfantryCountAt(dwPos) == 0) + subpos = 0; + else + { + int oldInf = GetInfantryAt(dwPos, 0); + if (oldInf > -1) + { + INFANTRY inf; + GetInfantryData(oldInf, &inf); + + if (inf.pos == "0") + for (i = 1;i < SUBPOS_COUNT;i++) + { + if (GetInfantryAt(dwPos, i) == -1) + { + //subpos=i+1; + + char c[50]; + itoa(i, c, 10); + inf.pos = c; + DeleteInfantry(oldInf); + AddInfantry(&inf); + break; + } + + } + } + + // if(GetInfantryAt(dwPos, 0)==oldInf) return FALSE; + + for (i = 0;i < SUBPOS_COUNT;i++) + { + if (GetInfantryAt(dwPos, i) == -1) + { + subpos = i + 1; + break; + } + } + } + + if (subpos < 0) return FALSE; + char c[50]; + itoa(subpos, c, 10); + + infantry.pos = c; + } + + + + /* + CString id=GetFree("Infantry"); + + CString value; + value=infantry.house+","+infantry.type+","+infantry.strength+","+infantry.y+ + ","+infantry.x+","+infantry.pos+","+infantry.action+","+infantry.direction+","+ + infantry.tag+","+infantry.flag1+","+infantry.flag2+","+infantry.flag3+","+ + infantry.flag4+","+infantry.flag5; + + m_mapfile.sections["Infantry"].values[id]=(LPCTSTR)value; + + UpdateInfantry(FALSE); + */ + + infantry.deleted = 0; + + /* This code just pushed it back to the end, caused some trouble (and used memory) + m_infantry.push_back(infantry); + + int sp=atoi(infantry.pos); + if(sp>0) sp--; + + int pos=dwPos; + fielddata[pos].infantry[sp]=m_infantry.size()-1; + */ + + // below code should be much more compatible to the very old code (the direct ini one) + + int sp = atoi(infantry.pos); + if (sp > 0) sp--; + + int i; + BOOL bFound = FALSE; + if (suggestedIndex >= 0 && suggestedIndex < m_infantry.size()) + { + if (m_infantry[suggestedIndex].deleted) + { + m_infantry[suggestedIndex] = infantry; + if (dwPos < fielddata_size) fielddata[dwPos].infantry[sp] = suggestedIndex; + bFound = TRUE; + + } + } + + if (!bFound) + for (i = 0;i < m_infantry.size();i++) + { + if (m_infantry[i].deleted) // yep, found one, replace it + { + m_infantry[i] = infantry; + if (dwPos < fielddata_size) fielddata[dwPos].infantry[sp] = i; + bFound = TRUE; + break; + } + } + + if (!bFound) + { + m_infantry.push_back(infantry); + if (dwPos < fielddata_size) fielddata[dwPos].infantry[sp] = m_infantry.size() - 1; + } + + + return TRUE; +} + +BOOL CMapData::AddStructure(STRUCTURE* lpStructure, LPCTSTR lpType, LPCTSTR lpHouse, DWORD dwPos, CString suggestedID) +{ + STRUCTURE structure; + if (lpStructure != NULL) + { + structure = *lpStructure; + } + else + { + char cx[10], cy[10]; + itoa(dwPos % Map->GetIsoSize(), cx, 10); + itoa(dwPos / Map->GetIsoSize(), cy, 10); + + structure.tag = "None"; + structure.direction = "64"; + structure.flag1 = "1"; + structure.flag2 = "0"; + structure.spotlight = "0"; + structure.flag3 = "0"; + structure.flag4 = "0"; + structure.energy = "1"; + structure.upgrade1 = "None"; + structure.upgrade2 = "None"; + structure.upgrade3 = "None"; + structure.upgradecount = "0"; + structure.strength = "256"; + structure.house = lpHouse; + structure.type = lpType; + structure.x = cx; + structure.y = cy; + + + } + + + CString id = GetFree("Structures"); + + if (suggestedID.GetLength() > 0) + { + if (m_mapfile.sections["Structures"].values.find(suggestedID) == m_mapfile.sections["Structures"].values.end()) + id = suggestedID; + } + + CString value; + value = structure.house + "," + structure.type + "," + structure.strength + "," + structure.y + + "," + structure.x + "," + structure.direction + "," + structure.tag + "," + structure.flag1 + "," + + structure.flag2 + "," + structure.energy + "," + structure.upgradecount + "," + structure.spotlight + "," + + structure.upgrade1 + "," + structure.upgrade2 + "," + structure.upgrade3 + "," + structure.flag3 + "," + structure.flag4; + + m_mapfile.sections["Structures"].values[id] = (LPCTSTR)value; + + if (!m_noAutoObjectUpdate) UpdateStructures(FALSE); + + return TRUE; +} + + + +void CMapData::InitializeUnitTypes() +{ + buildingid.clear(); + terrainid.clear(); + + int i; + m_overlayCredits[OverlayCredits_Riparius] = atoi(m_mapfile.GetValueByName("Riparius", "Value", rules.sections["Riparius"].AccessValueByName("Value"))); + m_overlayCredits[OverlayCredits_Cruentus] = atoi(m_mapfile.GetValueByName("Cruentus", "Value", rules.sections["Cruentus"].AccessValueByName("Value"))); + m_overlayCredits[OverlayCredits_Vinifera] = atoi(m_mapfile.GetValueByName("Vinifera", "Value", rules.sections["Vinifera"].AccessValueByName("Value"))); + m_overlayCredits[OverlayCredits_Aboreus] = atoi(m_mapfile.GetValueByName("Aboreus", "Value", rules.sections["Aboreus"].AccessValueByName("Value"))); + for (i = 0;i < rules.sections["BuildingTypes"].values.size();i++) + { + CString type = *rules.sections["BuildingTypes"].GetValue(i); + + int n = GetBuildingNumber(type); + buildingid[type] = n; + } + + for (i = 0;i < m_mapfile.sections["BuildingTypes"].values.size();i++) + { + CString type = *m_mapfile.sections["BuildingTypes"].GetValue(i); + + int n = GetBuildingNumber(type); + buildingid[type] = n; + } + + for (i = 0;i < rules.sections["TerrainTypes"].values.size();i++) + { + CString type = *rules.sections["TerrainTypes"].GetValue(i); + + int n = GetTerrainNumber(type); + terrainid[type] = n; + } + + for (i = 0;i < m_mapfile.sections["TerrainTypes"].values.size();i++) + { + CString type = *m_mapfile.sections["TerrainTypes"].GetValue(i); + + int n = GetTerrainNumber(type); + terrainid[type] = n; + } + +#ifdef SMUDGE_SUPP + + for (i = 0;i < rules.sections["SmudgeTypes"].values.size();i++) + { + CString type = *rules.sections["SmudgeTypes"].GetValue(i); + + int n = GetSmudgeNumber(type); + smudgeid[type] = n; + } + + for (i = 0;i < m_mapfile.sections["SmudgeTypes"].values.size();i++) + { + CString type = *m_mapfile.sections["SmudgeTypes"].GetValue(i); + + int n = GetSmudgeNumber(type); + smudgeid[type] = n; + } + +#endif + + +} + +INT CMapData::GetUnitTypeID(LPCTSTR lpType) +{ + // we only support building types, terrain types and smudge types at the moment + if (buildingid.find(lpType) != buildingid.end()) return buildingid[lpType]; + if (terrainid.find(lpType) != terrainid.end()) return terrainid[lpType]; +#ifdef SMUDGE_SUPP + if (smudgeid.find(lpType) != smudgeid.end()) return smudgeid[lpType]; +#endif + return 0; +} + +void CMapData::GetStdInfantryData(DWORD dwIndex, STDOBJECTDATA* lpStdInfantry) const +{ + /*CString data=*m_mapfile.sections["Infantry"].GetValue(dwIndex); + + lpStdInfantry->house=GetParam(data, 0); + lpStdInfantry->type=GetParam(data, 1); + lpStdInfantry->strength=atoi(GetParam(data, 2)); + lpStdInfantry->y=GetParam(data, 3); + lpStdInfantry->x=atoi(GetParam(data, 4));*/ + + lpStdInfantry->house = m_infantry[dwIndex].house; + lpStdInfantry->type = m_infantry[dwIndex].type; + lpStdInfantry->strength = m_infantry[dwIndex].strength; + lpStdInfantry->y = m_infantry[dwIndex].y; + lpStdInfantry->x = m_infantry[dwIndex].x; + +} + +void CMapData::GetInfantryData(DWORD dwIndex, INFANTRY* lpInfantry) const +{ + ASSERT(dwIndex < m_infantry.size()); + + if (dwIndex >= m_infantry.size()) return; + + /*lpInfantry->house=m_infantry.house; + lpInfantry->type=m_infantry.; + lpInfantry->strength=m_infantry.; + lpInfantry->y=m_infantry.; + lpInfantry->x=m_infantry.; + lpInfantry->pos=m_infantry.; + lpInfantry->action=m_infantry.; + lpInfantry->direction=m_infantry.; + lpInfantry->tag=m_infantry.; + lpInfantry->flag1=m_infantry.; + lpInfantry->flag2=m_infantry.; + lpInfantry->flag3=m_infantry.; + lpInfantry->flag4=m_infantry.; + lpInfantry->flag5=m_infantry.;*/ + *lpInfantry = m_infantry[dwIndex]; + + //memcpy(lpInfantry, &m_infantry[dwIndex], sizeof(INFANTRY)); + + //ASSERT(dwIndex>=0 && dwIndex=m_mapfile.sections["Infantry"].values.size()) return; + + CString data=*m_mapfile.sections["Infantry"].GetValue(dwIndex); + + lpInfantry->house=GetParam(data, 0); + lpInfantry->type=GetParam(data, 1); + lpInfantry->strength=GetParam(data, 2); + lpInfantry->y=GetParam(data, 3); + lpInfantry->x=GetParam(data, 4); + lpInfantry->pos=GetParam(data, 5); + lpInfantry->action=GetParam(data, 6); + lpInfantry->direction=GetParam(data, 7); + lpInfantry->tag=GetParam(data, 8); + lpInfantry->flag1=GetParam(data, 9); + lpInfantry->flag2=GetParam(data, 10); + lpInfantry->flag3=GetParam(data, 11); + lpInfantry->flag4=GetParam(data, 12); + lpInfantry->flag5=GetParam(data, 13);*/ + +} + +void CMapData::GetUnitData(DWORD dwIndex, UNIT* lpUnit) const +{ + const auto section = m_mapfile.GetSection("Units"); + if (!section || dwIndex >= section->values.size()) + return; + + CString data = *section->GetValue(dwIndex); + + lpUnit->house = GetParam(data, 0); + lpUnit->type = GetParam(data, 1); + lpUnit->strength = GetParam(data, 2); + lpUnit->y = GetParam(data, 3); + lpUnit->x = GetParam(data, 4); + lpUnit->direction = GetParam(data, 5); + lpUnit->action = GetParam(data, 6); + lpUnit->tag = GetParam(data, 7); + lpUnit->flag1 = GetParam(data, 8); + lpUnit->flag2 = GetParam(data, 9); + lpUnit->flag3 = GetParam(data, 10); + lpUnit->flag4 = GetParam(data, 11); + lpUnit->flag5 = GetParam(data, 12); + lpUnit->flag6 = GetParam(data, 13); +} + +void CMapData::GetAircraftData(DWORD dwIndex, AIRCRAFT* lpAircraft) const +{ + const auto section = m_mapfile.GetSection("Aircraft"); + if (!section || dwIndex >= section->values.size()) + return; + + CString data = *section->GetValue(dwIndex); + + lpAircraft->house = GetParam(data, 0); + lpAircraft->type = GetParam(data, 1); + lpAircraft->strength = GetParam(data, 2); + lpAircraft->y = GetParam(data, 3); + lpAircraft->x = GetParam(data, 4); + lpAircraft->direction = GetParam(data, 5); + lpAircraft->action = GetParam(data, 6); + lpAircraft->tag = GetParam(data, 7); + lpAircraft->flag1 = GetParam(data, 8); + lpAircraft->flag2 = GetParam(data, 9); + lpAircraft->flag3 = GetParam(data, 10); + lpAircraft->flag4 = GetParam(data, 11); +} + +BOOL CMapData::AddCelltag(LPCTSTR lpTag, DWORD dwPos) +{ + char j[15]; + char k[15]; + memset(j, 0, 15); + memset(k, 0, 15); + itoa(dwPos / GetIsoSize(), j, 10); + if (strlen(j) < 3) + { + strcpy_safe(j + 1, j); + j[0] = '0'; + } + if (strlen(j) < 3) + { + strcpy_safe(j + 1, j); + j[0] = '0'; + } + itoa(dwPos % GetIsoSize(), k, 10); + strcat(k, j); + + m_mapfile.sections["CellTags"].values[k] = lpTag; + + if (!m_noAutoObjectUpdate) UpdateCelltags(FALSE); + return TRUE; +} + +void CMapData::GetCelltagData(DWORD dwIndex, CString* lpTag, DWORD* lpdwPos) const +{ + const auto section = m_mapfile.GetSection("CellTags"); + if (!section || dwIndex >= section->values.size()) + return; + + int x, y; + CString pos; + + pos = *section->GetValueName(dwIndex); + PosToXY(pos, &x, &y); + + const auto tag = section->GetValueByName(pos); + *lpTag = tag; + *lpdwPos = x + y * GetIsoSize(); +} + +BOOL CMapData::AddAircraft(AIRCRAFT* lpAircraft, LPCTSTR lpType, LPCTSTR lpHouse, DWORD dwPos, CString suggestedID) +{ + AIRCRAFT aircraft; + + if (lpAircraft != NULL) + { + aircraft = *lpAircraft; + } + else + { + char sx[15], sy[15]; + itoa(dwPos % GetIsoSize(), sx, 10); + itoa(dwPos / GetIsoSize(), sy, 10); + + aircraft.type = lpType; + aircraft.house = lpHouse; + aircraft.action = "Guard"; + aircraft.tag = "None"; + aircraft.direction = "64"; + aircraft.strength = "256"; + aircraft.x = sx; + aircraft.y = sy; + aircraft.flag1 = "0"; + aircraft.flag2 = "0"; + aircraft.flag3 = "1"; + aircraft.flag4 = "0"; + } + + CString id = GetFree("Aircraft"); + + if (suggestedID.GetLength() > 0) + { + if (m_mapfile.sections["Aircraft"].values.find(suggestedID) == m_mapfile.sections["Aircraft"].values.end()) + id = suggestedID; + } + + CString value; + value = aircraft.house + "," + aircraft.type + "," + aircraft.strength + "," + aircraft.y + "," + + aircraft.x + "," + aircraft.direction + "," + aircraft.action + "," + aircraft.tag + "," + + aircraft.flag1 + "," + aircraft.flag2 + "," + aircraft.flag3 + "," + aircraft.flag4; + + m_mapfile.sections["Aircraft"].values[id] = value; + + if (!m_noAutoObjectUpdate) UpdateAircraft(FALSE); + + return TRUE; +} + +BOOL CMapData::AddUnit(UNIT* lpUnit, LPCTSTR lpType, LPCTSTR lpHouse, DWORD dwPos, CString suggestedID) +{ + UNIT unit; + + if (lpUnit != NULL) + { + unit = *lpUnit; + } + else + { + char sx[15], sy[15]; + itoa(dwPos % GetIsoSize(), sx, 10); + itoa(dwPos / GetIsoSize(), sy, 10); + + unit.type = lpType; + unit.house = lpHouse; + unit.action = "Guard"; + unit.tag = "None"; + unit.direction = "64"; + unit.strength = "256"; + unit.x = sx; + unit.y = sy; + unit.flag1 = "0"; + unit.flag2 = "-1"; + unit.flag3 = "0"; + unit.flag4 = "-1"; + unit.flag5 = "1"; + unit.flag6 = "0"; + + } + + CString id = GetFree("Units"); + + if (suggestedID.GetLength() > 0) + { + if (m_mapfile.sections["Units"].values.find(suggestedID) == m_mapfile.sections["Units"].values.end()) + id = suggestedID; + } + + CString value; + value = unit.house + "," + unit.type + "," + unit.strength + "," + unit.y + "," + + unit.x + "," + unit.direction + "," + unit.action + "," + unit.tag + "," + + unit.flag1 + "," + unit.flag2 + "," + unit.flag3 + "," + unit.flag4 + "," + unit.flag5 + "," + unit.flag6; + + m_mapfile.sections["Units"].values[id] = value; + + if (!m_noAutoObjectUpdate) UpdateUnits(FALSE); + return TRUE; +} + +void CMapData::GetTerrainData(DWORD dwIndex, CString* lpType) const +{ + ASSERT(m_terrain.size() > dwIndex); + + /* if(m_mapfile.sections["Terrain"].values.size()<=dwIndex) + { + errstream << "GetTerrainData() fails..." << endl; + errstream.flush(); + *lpType=""; + return; + }*/ + *lpType = m_terrain[dwIndex].type;//*m_mapfile.sections["Terrain"].GetValue(dwIndex); +} + +// MW New for script interpreter: +void CMapData::GetTerrainData(DWORD dwIndex, TERRAIN* lpType) const +{ + ASSERT(m_terrain.size() > dwIndex); + + *lpType = m_terrain[dwIndex]; +} + +BOOL CMapData::AddTerrain(LPCTSTR lpType, DWORD dwPos, int suggestedIndex) +{ + /*char j1[15]; + char k1[15];*/ + + int x, y; + x = dwPos % GetIsoSize(); + y = dwPos / GetIsoSize(); + + /*itoa(y, j1, 10); + if(strlen(j1)<3) + { + strcpy_safe(j1+1, j1); + j1[0]='0'; + } + if(strlen(j1)<3) + { + strcpy_safe(j1+1, j1); + j1[0]='0'; + } + itoa(x, k1, 10); + strcat(k1, j1);*/ + + + + /* + March 23th, 2001: Replaced slow UpdateTerrain() call with direct modification: + */ + + TERRAIN td; + td.deleted = 0; + td.type = lpType; + td.x = x; + td.y = y; + + if (terrainid.find(td.type) == terrainid.end()) return FALSE; + + BOOL bFound = FALSE; + + if (suggestedIndex >= 0 && suggestedIndex < m_terrain.size()) + { + if (m_terrain[suggestedIndex].deleted) + { + m_terrain[suggestedIndex] = td; + if (dwPos < fielddata_size) + { + fielddata[dwPos].terrain = suggestedIndex; + fielddata[dwPos].terraintype = terrainid[lpType]; + } + bFound = TRUE; + + } + } + + int i; + if (!bFound) + for (i = 0;i < m_terrain.size();i++) + { + if (m_terrain[i].deleted) // yep, found one, replace it + { + m_terrain[i] = td; + if (dwPos < fielddata_size) + { + fielddata[dwPos].terrain = i; + fielddata[dwPos].terraintype = terrainid[lpType]; + } + bFound = TRUE; + break; + } + } + + if (!bFound) + { + m_terrain.push_back(td); + int pos = x + y * GetIsoSize(); + if (pos < fielddata_size) + { + fielddata[pos].terrain = m_terrain.size() - 1; + fielddata[pos].terraintype = terrainid[lpType]; + } + } + + //UpdateTerrain(); + + return TRUE; + +} + +BOOL CMapData::IsGroundObjectAt(DWORD dwPos) const +{ + int m_id = 0; + + m_id = GetInfantryAt(dwPos); + if (m_id < 0) + m_id = GetUnitAt(dwPos); + if (m_id < 0) + m_id = GetAirAt(dwPos); + if (m_id < 0) + m_id = GetStructureAt(dwPos); + if (m_id < 0) + m_id = GetTerrainAt(dwPos); + + if (m_id < 0) return FALSE; + + return TRUE; + +} + +void CMapData::GetWaypointData(DWORD dwIndex, CString* lpID, DWORD* lpdwPos) const +{ + if (lpID) *lpID = ""; + if (lpdwPos) *lpdwPos = 0; + + const auto section = m_mapfile.GetSection("Waypoints"); + if (!section || dwIndex >= section->values.size()) + return; + + CString data = *section->GetValue(dwIndex); + + int x, y; + PosToXY(data, &x, &y); + + if (lpID) *lpID = *section->GetValueName(dwIndex); + if (lpdwPos) *lpdwPos = x + y * GetIsoSize(); + +} + +void CMapData::GetStdAircraftData(DWORD dwIndex, STDOBJECTDATA* lpStdAircraft) const +{ + const auto section = m_mapfile.GetSection("Aircraft"); + if (!section || dwIndex >= section->values.size()) + return; + + CString data = *section->GetValue(dwIndex); + + lpStdAircraft->house = GetParam(data, 0); + lpStdAircraft->type = GetParam(data, 1); + lpStdAircraft->strength.Format("%d", atoi(GetParam(data, 2))); + lpStdAircraft->y = GetParam(data, 3); + lpStdAircraft->x.Format("%d", atoi(GetParam(data, 4))); +} + +void CMapData::GetStdUnitData(DWORD dwIndex, STDOBJECTDATA* lpStdUnit) const +{ + const auto section = m_mapfile.GetSection("Units"); + if (!section || dwIndex >= section->values.size()) + return; + + CString data = *section->GetValue(dwIndex); + + lpStdUnit->house = GetParam(data, 0); + lpStdUnit->type = GetParam(data, 1); + lpStdUnit->strength.Format("%d", atoi(GetParam(data, 2))); + lpStdUnit->y = GetParam(data, 3); + lpStdUnit->x.Format("%d", atoi(GetParam(data, 4))); +} + +DWORD CMapData::GetInfantryCount() const +{ + return m_infantry.size();//m_mapfile.sections["Infantry"].values.size(); +} + +DWORD CMapData::GetUnitCount() const +{ + const auto section = m_mapfile.GetSection("Units"); + return section ? section->values.size() : 0; +} + +DWORD CMapData::GetStructureCount() const +{ + const auto section = m_mapfile.GetSection("Structures"); + return section ? section->values.size() : 0; +} + +DWORD CMapData::GetAircraftCount() const +{ + const auto section = m_mapfile.GetSection("Aircraft"); + return section ? section->values.size() : 0; +} + +DWORD CMapData::GetTerrainCount() const +{ + return m_terrain.size();//m_mapfile.sections["Terrain"].values.size(); +} + +/* +CString CMapData::GetUnitName(LPCTSTR lpID); + +Returns the name of the unit identified with the ID lpID. +Note: takes care of the current mapfile settings +*/ +WCHAR unknown[] = L"MISSING"; +WCHAR* CMapData::GetUnitName(LPCTSTR lpID) const +{ + WCHAR* res = NULL; + + if (g_data.sections["Rename"].FindName(lpID) >= 0) + { + CCStrings[lpID].SetString((LPSTR)(LPCSTR)GetLanguageStringACP(g_data.sections["Rename"].values[(LPCSTR)lpID])); + res = CCStrings[lpID].wString; + return res; + } + + if (CCStrings.find(lpID) != CCStrings.end() && CCStrings[lpID].len > 0) res = CCStrings[lpID].wString; + + if (!res && m_mapfile.sections.find(lpID) != m_mapfile.sections.end()) + { + const auto section = m_mapfile.GetSection(lpID); + if (section && section->values.find("Name") != section->values.end()) + { + CCStrings[lpID].SetString(section->values.at("Name")); + + res = CCStrings[lpID].wString; + } + } + + if (!res && rules.sections.find(lpID) != rules.sections.end()) + { + const auto section = rules.GetSection(lpID); + if (section && section->values.find("Name") != section->values.end()) + { + CCStrings[lpID].SetString(section->values.at("Name")); + res = CCStrings[lpID].wString; + } + } + + if (!res) + { + CCStrings[lpID].SetString(L"MISSING", 7); + res = CCStrings[lpID].wString; + } + + + return res; + + //return CString(""); +} + +DWORD CMapData::GetCelltagCount() const +{ + const auto section = m_mapfile.GetSection("CellTags"); + return section ? section->values.size() : 0; +} + +DWORD CMapData::GetWaypointCount() const +{ + const auto section = m_mapfile.GetSection("Waypoints"); + return section ? section->values.size() : 0; +} + +void CMapData::DeleteRulesSections() +{ + int i; + + // delete any rules sections except the types lists (we need those to get the data of new units in the map)... + for (i = 0; i < m_mapfile.sections.size(); i++) + { + CString name = *m_mapfile.GetSectionName(i); + + if (IsRulesSection(name) && name.Find("Types") < 0) + { + m_mapfile.sections.erase(name); + } + } + + // now delete these types lists... + for (i = 0; i < m_mapfile.sections.size(); i++) + { + CString name = *m_mapfile.GetSectionName(i); + + if (IsRulesSection(name)) + { + m_mapfile.sections.erase(name); + } + } +} + +BOOL CMapData::IsRulesSection(LPCTSTR lpSection) +{ + int i; + for (i = 0;i < GetHousesCount();i++) + if (GetHouseID(i) == lpSection) return FALSE; + + if (strcmp(lpSection, HOUSES) == NULL) return FALSE; + if (strcmp(lpSection, "VariableNames") == NULL) return FALSE; + + if (rules.sections.find(lpSection) != rules.sections.end()) return TRUE; + + + if (m_mapfile.sections.find("InfantryTypes") != m_mapfile.sections.end()) + if (m_mapfile.sections["InfantryTypes"].FindValue(lpSection) >= 0) + return TRUE; + + if (m_mapfile.sections.find("VehicleTypes") != m_mapfile.sections.end()) + if (m_mapfile.sections["VehicleTypes"].FindValue(lpSection) >= 0) + return TRUE; + + if (m_mapfile.sections.find("AircraftTypes") != m_mapfile.sections.end()) + if (m_mapfile.sections["AircraftTypes"].FindValue(lpSection) >= 0) + return TRUE; + + if (m_mapfile.sections.find("BuildingTypes") != m_mapfile.sections.end()) + if (m_mapfile.sections["BuildingTypes"].FindValue(lpSection) >= 0) + return TRUE; + + if (m_mapfile.sections.find("TerrainTypes") != m_mapfile.sections.end()) + if (m_mapfile.sections["TerrainTypes"].FindValue(lpSection) >= 0) + return TRUE; + + if ((CString)"IsoMapPack5" != lpSection && (CString)"OverlayPack" != lpSection && (CString)"OverlayDataPack" != lpSection && m_mapfile.sections.find(lpSection) != m_mapfile.sections.end()) + { + CIniFileSection& sec = m_mapfile.sections[lpSection]; + if (sec.FindName("ROF") > -1 && sec.FindName("Range") > -1 && + sec.FindName("Damage") > -1 && sec.FindName("Warhead") > -1) + return TRUE; // a weapon + + if (sec.FindName("Spread") > -1 && sec.FindName("Range") > -1 && + sec.FindName("Damage") > -1 && sec.FindName("Warhead") > -1) + return TRUE; // a warhead + + // check for projectile/warhead + for (i = 0;i < m_mapfile.sections.size();i++) + { + CString name = *m_mapfile.GetSectionName(i); + if ((CString)"IsoMapPack5" != name && (CString)"OverlayPack" != name && (CString)"OverlayDataPack" != name && (m_mapfile.GetSection(i)->FindName("Projectile") > -1 || m_mapfile.GetSection(i)->FindName("Warhead") > -1)) + { + // MW Bugfix: Check if is found in Projectile first... + // This may have caused several crashes while saving + if (m_mapfile.GetSection(i)->FindName("Projectile") >= 0) + if (*m_mapfile.GetSection(i)->GetValue(m_mapfile.GetSection(i)->FindName("Projectile")) == lpSection) + return TRUE; + } + } + } + + + + return FALSE; + +} + +void CMapData::ExportRulesChanges(const char* filename) +{ + CIniFile rul; + + int i; + for (i = 0;i < m_mapfile.sections.size();i++) + { + + CString name = *m_mapfile.GetSectionName(i); + + if (IsRulesSection(name)) + { + + rul.sections[name] = *m_mapfile.GetSection(i); + + } + } + + rul.SaveFile(std::string(filename)); +} + +void CMapData::ImportRUL(LPCTSTR lpFilename) +{ + m_mapfile.InsertFile(std::string(lpFilename), NULL); + m_mapfile.sections.erase("Editor"); + UpdateBuildingInfo(); + UpdateTreeInfo(); +} + +void CMapData::UpdateMapFieldData(BOOL bSave) +{ + if (bSave == FALSE) + { + int i; + int e; + /*for(i=0;iGetWidth(); + int mapheight=Map->GetHeight(); + int k=1; + + if( dwX<1|| dwY<1 || dwX+dwYmapwidth+mapheight*2 || (dwY+k>mapwidth && dwX-kmapwidth && dwY+mapwidth-kwY==dwX && mfd->wX==dwY) + { + bFound=TRUE; + break; + } + } + + if(!bFound) + { + errstream << dwX << " " << dwY << " not found"; + errstream.flush(); + } + } + }*/ + + /* int count=0; + int max_count=0; + BYTE b; + b=m_mfd[0]; + for (i=0;i10) MessageBox(0,"uh","",0); + } + + char c[50]; + itoa(max_count,c,10); + MessageBox(0,c,"",0);*/ + + const bool mp = IsMultiplayer(); + for (i = 0;i < dwIsoMapSize;i++) + { + MAPFIELDDATA* mfd = (MAPFIELDDATA*)&m_mfd[i * MAPFIELDDATA_SIZE]; + int pos = mfd->wY + mfd->wX * GetIsoSize(); + if (dwIsoMapSize - i < 50) errstream << mfd->wY << " " << mfd->wX << endl; + if (pos < (GetIsoSize() + 1) * (GetIsoSize() + 1)) + { + fielddata[pos].wGround = mfd->wGround; + fielddata[pos].bHeight = mfd->bHeight; + memcpy(&fielddata[pos].bMapData, mfd->bData, 3); + memcpy(&fielddata[pos].bMapData2, mfd->bData2, 1); + + int replacement = 0; + int ground = mfd->wGround; + if (ground == 0xFFFF) ground = 0; + + if ((*tiledata)[ground].bReplacementCount && atoi((*tiles).sections["General"].values["BridgeSet"]) != (*tiledata)[ground].wTileSet) + { + replacement = rand() * (1 + (*tiledata)[ground].bReplacementCount) / RAND_MAX; + } + + fielddata[pos].bRNDImage = replacement; + + Mini_UpdatePos(i % GetIsoSize(), i / GetIsoSize(), mp); + + /*int dwX=mfd->wY; + int dwY=mfd->wX; + int mapwidth=Map->GetWidth(); + int mapheight=Map->GetHeight(); + const int k=1; + if( dwX<1|| dwY<1 || dwX+dwYmapwidth+mapheight*2 || (dwY+k>mapwidth && dwX-kmapwidth && dwY+mapwidth-kwY==0xFFFE && mfd->wX==0xFFFE) + { + char c[2]; + c[0] = mfd->bHeight; + c[1] = 0; + OutputDebugString(c); + } + + /*if(mfd->bData[0] || mfd->bData[1] || mfd->bData2[0]) + { + char c[50]; + itoa(mfd->wY, c, 10); + OutputDebugString("Data at "); + OutputDebugString(c); + OutputDebugString(" "); + itoa(mfd->wX,c,10); + OutputDebugString(c); + OutputDebugString(": "); + itoa(mfd->bData[0], c, 10); + OutputDebugString(c); + OutputDebugString(" "); + itoa(mfd->bData[1], c, 10); + OutputDebugString(c); + OutputDebugString(" "); + itoa(mfd->bData[2], c, 10); + OutputDebugString(c); + OutputDebugString(" "); + itoa(mfd->bData2[0], c, 10); + OutputDebugString(c); + OutputDebugString("\n"); + }*/ + + } + + for (i = 0;i < m_IsoSize;i++) + { + for (e = 0;e < m_IsoSize;e++) + { + int pos = i + e * m_IsoSize; + int xx, yy; + fielddata[pos].bRedrawTerrain = FALSE; + for (xx = -2;xx < 0;xx++) + { + for (yy = -2;yy < 0;yy++) + { + int npos = pos + xx + yy * m_IsoSize; + if (npos > 0 && fielddata[pos].bHeight - fielddata[npos].bHeight >= 4) + { + fielddata[pos].bRedrawTerrain = TRUE; + break; + } + } + if (fielddata[pos].bRedrawTerrain) break; + } + } + } + } + else + { + int x, y, n = 0; + + // this code here must be improved to produce smaller maps. Just ignore the data outside the visible rect! + + if (m_mfd) delete[] m_mfd; + dwIsoMapSize = m_IsoSize * m_IsoSize + 15; + m_mfd = new(BYTE[(dwIsoMapSize + m_IsoSize * m_IsoSize) * MAPFIELDDATA_SIZE]); + memset(m_mfd, 0, dwIsoMapSize * MAPFIELDDATA_SIZE); + + + + int p = 0; + const int width = m_maprect.right; + const int height = m_maprect.bottom; + + errstream << "Memory allocated for mappack, saving fielddata into mapfields" << endl; + errstream.flush(); + + int i; + int mapwidth = m_maprect.right; + int mapheight = m_maprect.bottom; + + //#ifdef UNUSED + int dwX, dwY; + for (dwX = 0;dwX <= m_IsoSize;dwX++) + { + for (dwY = 0;dwY <= m_IsoSize;dwY++) + { + /*for(i=0;imapwidth+mapheight*2 || (dwY+2>mapwidth && dwX-2mapwidth && dwY+mapwidth-2mapwidth + mapheight * 2 || (dwY + 1 > mapwidth && dwX - 1 < dwY - mapwidth) || (dwX + 1 > mapwidth && dwY + mapwidth - 1 < dwX)) continue; + + + MAPFIELDDATA* mfd = (MAPFIELDDATA*)&m_mfd[p * MAPFIELDDATA_SIZE]; + mfd->wGround = fielddata[i].wGround; + mfd->wX = dwY; + mfd->wY = dwX; + mfd->bHeight = fielddata[i].bHeight; + memcpy(&mfd->bData, &fielddata[i].bMapData, 3); // includes fielddata[i].bSubTile! + memcpy(&mfd->bData2, &fielddata[i].bMapData2, 1); + + p++; + } + + } + //#endif + + /* + + + if(width>height) + { + int add_bottom=1; + int add_top=-1; + int n_bottom, n_top; + n_bottom=n_top=width; + for(x=0;x=0) + { + if( x<1|| y<1 || x+ymapwidth+mapheight*2 || (y+1>mapwidth && x-1mapwidth && y+mapwidth-1wGround=fielddata[pos].wGround; + mfd->wX=x; + mfd->wY=y; + mfd->bHeight=fielddata[pos].bHeight; + memcpy(&mfd->bData, &fielddata[pos].bMapData, 3); + memcpy(&mfd->bData2, &fielddata[pos].bMapData2, 1); + + p++; + } + } + + if(x==height) add_bottom=-1; + if(x==width) add_top=1; + + n_top+=add_top; + n_bottom+=add_bottom; + } + } + else + { + int add_right=1; + int add_left=-1; + int n_right, n_left; + n_right=n_left=height; + for(y=width+height;y>=0;y--) + { + + for(x=n_left;x<=n_right;x++) + { + if(x=0) + { + if( x<1|| y<1 || x+ymapwidth+mapheight*2 || (y+1>mapwidth && x-1mapwidth && y+mapwidth-10 && pos<= + MAPFIELDDATA* mfd=(MAPFIELDDATA*)&m_mfd[p*MAPFIELDDATA_SIZE]; + mfd->wGround=fielddata[pos].wGround; + mfd->wX=x; + mfd->wY=y; + mfd->bHeight=fielddata[pos].bHeight; + memcpy(&mfd->bData, &fielddata[pos].bMapData, 3); + memcpy(&mfd->bData2, &fielddata[pos].bMapData2, 1); + + p++; + } + } + + if(y==height) add_right=-1; + if(y==width) add_left=1; + + n_left+=add_left; + n_right+=add_right; + } + }*/ + + /* + else + { + for(y=height;y>=0;y--) + { + for(x=0;x<=n;x++) + { + int pos=y+x*GetIsoSize(); + + MAPFIELDDATA* mfd=(MAPFIELDDATA*)&m_mfd[p*MAPFIELDDATA_SIZE]; + mfd->wGround=fielddata[pos].wGround; + mfd->wX=x; + mfd->wY=y; + mfd->bHeight=fielddata[pos].bHeight; + memcpy(&mfd->bData, &fielddata[pos].bMapData, 3); + memcpy(&mfd->bData2, &fielddata[pos].bMapData2, 1); + char c[50]; + itoa(x,c,10); + OutputDebugString(c); + OutputDebugString(" "); + itoa(y,c,10); + OutputDebugString(c); + OutputDebugString(" "); + itoa(p,c,10); + OutputDebugString(c); + OutputDebugString(" "); + OutputDebugString("\n"); + p++; + } + if(height-ywX=0xFFFE; + mfd->wY=0xFFFE; + int c; + switch(i) + { + case 0: + c='F'; + break; + case 1: + c='I'; + break; + case 2: + c='N'; + break; + case 3: + c='A'; + break; + case 4: + c='L'; + break; + case 5: + c='S'; + break; + case 6: + c='U'; + break; + case 7: + c='N'; + break; + case 8: + c='/'; + break; + case 9: + c='A'; + break; + case 10: + c='L'; + break; + case 11: + c='E'; + break; + case 12: + c='R'; + break; + case 13: + c='T'; + break; + } + mfd->bHeight=c; + + }*/ + /*for(i=0;iwGround=fielddata[pos].wGround; + mfd->wX=i; + mfd->wY=e; + mfd->bHeight=fielddata[pos].bHeight; + memcpy(&mfd->bData, &fielddata[pos].bMapData, 3); + memcpy(&mfd->bData2, &fielddata[pos].bMapData2, 1); + n++; + } + }*/ + + + } +} + +void CMapData::UpdateBuildingInfo(LPCSTR lpUnitType) +{ + CIniFile& ini = GetIniFile(); + + if (!lpUnitType) + { + memset(buildinginfo, 0, 0x0F00 * sizeof(BUILDING_INFO)); + + int i; + for (i = 0;i < rules.sections["BuildingTypes"].values.size();i++) + { + + + CString type = *rules.sections["BuildingTypes"].GetValue(i); + CString artname = type; + + + if (rules.sections[type].values.find("Image") != rules.sections[type].values.end()) + { + artname = rules.sections[type].values["Image"]; + } + if (ini.sections.find(type) != ini.sections.end()) + { + if (ini.sections[type].values.find("Image") != ini.sections[type].values.end()) + { + artname = ini.sections[type].values["Image"]; + } + } + + int w, h; + char d[6]; + memcpy(d, art.sections[artname].values["Foundation"], 1); + d[1] = 0; + w = atoi(d); + if (w == 0) w = 1; + memcpy(d, (LPCTSTR)art.sections[artname].values["Foundation"] + 2, 1); + d[1] = 0; + h = atoi(d); + if (h == 0) h = 1; + + int n = Map->GetUnitTypeID(type); + + if (n >= 0 && n < 0x0F00) + { + buildinginfo[n].w = w; + buildinginfo[n].h = h; + + buildinginfo[n].bSnow = FALSE; + buildinginfo[n].bTemp = FALSE; + buildinginfo[n].bUrban = FALSE; + + + CString lpPicFile = GetUnitPictureFilename(type, 0); + + if (pics.find(lpPicFile) != pics.end()) + { + if (pics[lpPicFile].bTerrain == TheaterChar::None) + { + buildinginfo[n].bSnow = TRUE; + buildinginfo[n].bTemp = TRUE; + buildinginfo[n].bUrban = TRUE; + } + else if (pics[lpPicFile].bTerrain == TheaterChar::T) buildinginfo[n].bTemp = TRUE; + else if (pics[lpPicFile].bTerrain == TheaterChar::A) buildinginfo[n].bSnow = TRUE; + else if (pics[lpPicFile].bTerrain == TheaterChar::U) buildinginfo[n].bUrban = TRUE; + } + else + { + buildinginfo[n].bSnow = TRUE; + buildinginfo[n].bTemp = TRUE; + buildinginfo[n].bUrban = TRUE; + } + + buildinginfo[n].pic_count = 8; + int k; + for (k = 0;k < 8;k++) + { + lpPicFile = GetUnitPictureFilename(type, k); + + if (pics.find(lpPicFile) != pics.end()) + { + buildinginfo[n].pic[k] = pics[lpPicFile]; + } + else + { + buildinginfo[n].pic[k].pic = NULL; + } + + } + + + } + else + { + errstream << "Building not found " << endl; + errstream.flush(); + } + + } + + for (i = 0;i < ini.sections["BuildingTypes"].values.size();i++) + { + + + CString type = *ini.sections["BuildingTypes"].GetValue(i); + CString artname = type; + + + if (ini.sections.find(type) != ini.sections.end()) + { + if (ini.sections[type].values.find("Image") != ini.sections[type].values.end()) + { + artname = ini.sections[type].values["Image"]; + } + } + + int w, h; + char d[6]; + memcpy(d, art.sections[artname].values["Foundation"], 1); + d[1] = 0; + w = atoi(d); + if (w == 0) w = 1; + memcpy(d, (LPCTSTR)art.sections[artname].values["Foundation"] + 2, 1); + d[1] = 0; + h = atoi(d); + if (h == 0) h = 1; + + int n = Map->GetUnitTypeID(type); + + if (n >= 0 && n < 0x0F00) + { + buildinginfo[n].w = w; + buildinginfo[n].h = h; + buildinginfo[n].bSnow = TRUE; + buildinginfo[n].bTemp = TRUE; + buildinginfo[n].bUrban = TRUE; + + CString lpPicFile = GetUnitPictureFilename(type, 0); + + int k; + for (k = 0;k < 8;k++) + { + lpPicFile = GetUnitPictureFilename(type, k); + + if (pics.find(lpPicFile) != pics.end()) + { + buildinginfo[n].pic[k] = pics[lpPicFile]; + } + else + { + buildinginfo[n].pic[k].pic = NULL; + } + } + + } + + } + } + else + { + // only for specific building -> faster + CString type = lpUnitType; + CString artname = type; + + + if (rules.sections[type].values.find("Image") != rules.sections[type].values.end()) + { + artname = rules.sections[type].values["Image"]; + } + if (ini.sections.find(type) != ini.sections.end()) + { + if (ini.sections[type].values.find("Image") != ini.sections[type].values.end()) + { + artname = ini.sections[type].values["Image"]; + } + } + + int w, h; + char d[6]; + memcpy(d, art.sections[artname].values["Foundation"], 1); + d[1] = 0; + w = atoi(d); + if (w == 0) w = 1; + memcpy(d, (LPCTSTR)art.sections[artname].values["Foundation"] + 2, 1); + d[1] = 0; + h = atoi(d); + if (h == 0) h = 1; + + int n = Map->GetUnitTypeID(type); + + if (n >= 0 && n < 0x0F00) + { + buildinginfo[n].w = w; + buildinginfo[n].h = h; + CString lpPicFile = GetUnitPictureFilename(type, 0); + buildinginfo[n].pic_count = 8; + + int k; + for (k = 0;k < 8;k++) + { + lpPicFile = GetUnitPictureFilename(type, k); + + if (pics.find(lpPicFile) != pics.end()) + { + buildinginfo[n].pic[k] = pics[lpPicFile]; + } + else + { + buildinginfo[n].pic[k].pic = NULL; + } + } + + } + } + +} + +void CMapData::UpdateTreeInfo(LPCSTR lpTreeType) +{ + CIniFile& ini = GetIniFile(); + + if (!lpTreeType) + { + memset(treeinfo, 0, 0x0F00 * sizeof(TREE_INFO)); + + int i; + for (i = 0;i < rules.sections["TerrainTypes"].values.size();i++) + { + + + CString type = *rules.sections["TerrainTypes"].GetValue(i); + CString artname = type; + + + if (rules.sections[type].values.find("Image") != rules.sections[type].values.end()) + { + artname = rules.sections[type].values["Image"]; + } + if (ini.sections.find(type) != ini.sections.end()) + { + if (ini.sections[type].values.find("Image") != ini.sections[type].values.end()) + { + artname = ini.sections[type].values["Image"]; + } + } + + int w, h; + char d[6]; + memcpy(d, art.sections[artname].values["Foundation"], 1); + d[1] = 0; + w = atoi(d); + if (w == 0) w = 1; + memcpy(d, (LPCTSTR)art.sections[artname].values["Foundation"] + 2, 1); + d[1] = 0; + h = atoi(d); + if (h == 0) h = 1; + + int n = GetUnitTypeID(type); + + if (n >= 0 && n < 0x0F00) + { + treeinfo[n].w = w; + treeinfo[n].h = h; + + CString lpPicFile = GetUnitPictureFilename(type, 0); + + if (pics.find(lpPicFile) != pics.end()) + { + + treeinfo[n].pic = pics[lpPicFile]; + } + else + treeinfo[n].pic.pic = NULL; + } + + } + + for (i = 0;i < ini.sections["TerrainTypes"].values.size();i++) + { + + + CString type = *ini.sections["TerrainTypes"].GetValue(i); + CString artname = type; + + + if (ini.sections.find(type) != ini.sections.end()) + { + if (ini.sections[type].values.find("Image") != ini.sections[type].values.end()) + { + artname = ini.sections[type].values["Image"]; + } + } + + int w, h; + char d[6]; + memcpy(d, art.sections[artname].values["Foundation"], 1); + d[1] = 0; + w = atoi(d); + if (w == 0) w = 1; + memcpy(d, (LPCTSTR)art.sections[artname].values["Foundation"] + 2, 1); + d[1] = 0; + h = atoi(d); + if (h == 0) h = 1; + + int n = Map->GetUnitTypeID(type); + + if (n >= 0 && n < 0x0F00) + { + treeinfo[n].w = w; + treeinfo[n].h = h; + + CString lpPicFile = GetUnitPictureFilename(type, 0); + + if (pics.find(lpPicFile) != pics.end()) + { + treeinfo[n].pic = pics[lpPicFile]; + } + else + treeinfo[n].pic.pic = NULL; + } + + } + } + else + { + CString type = lpTreeType; + CString artname = type; + + + if (rules.sections[type].values.find("Image") != rules.sections[type].values.end()) + { + artname = rules.sections[type].values["Image"]; + } + if (ini.sections.find(type) != ini.sections.end()) + { + if (ini.sections[type].values.find("Image") != ini.sections[type].values.end()) + { + artname = ini.sections[type].values["Image"]; + } + } + + int w, h; + char d[6]; + memcpy(d, art.sections[artname].values["Foundation"], 1); + d[1] = 0; + w = atoi(d); + if (w == 0) w = 1; + memcpy(d, (LPCTSTR)art.sections[artname].values["Foundation"] + 2, 1); + d[1] = 0; + h = atoi(d); + if (h == 0) h = 1; + int n = Map->GetUnitTypeID(type); + + if (n >= 0 && n < 0x0F00) + { + treeinfo[n].w = w; + treeinfo[n].h = h; + + CString lpPicFile = GetUnitPictureFilename(type, 0); + if (pics.find(lpPicFile) != pics.end()) + { + + treeinfo[n].pic = pics[lpPicFile]; + } + else + treeinfo[n].pic.pic = NULL; + } + + } + +} + +int CMapData::GetBuildingID(LPCSTR lpBuildingName) +{ + if (buildingid.find(lpBuildingName) == buildingid.end()) return -1; + return buildingid[lpBuildingName]; +} + + + +MAPFIELDDATA* CMapData::GetMappackPointer(DWORD dwPos) +{ + int x = dwPos % GetIsoSize(); // note that x=y and y=x in the mappack (according to our struct)! + int y = dwPos / GetIsoSize(); + + int i = 0; + for (i = 0;i < dwIsoMapSize;i++) + { + MAPFIELDDATA* cur = (MAPFIELDDATA*)&m_mfd[i * MAPFIELDDATA_SIZE]; + if (cur->wX == y && cur->wY == x) + return cur; + } + + return NULL; +} + + +void CMapData::CreateMap(DWORD dwWidth, DWORD dwHeight, LPCTSTR lpTerrainType, DWORD dwGroundHeight) +{ + if (fielddata != NULL) delete[] fielddata; + int i; + for (i = 0;i < dwSnapShotCount;i++) + { + delete[] m_snapshots[i].bHeight; + delete[] m_snapshots[i].bMapData; + delete[] m_snapshots[i].bSubTile; + delete[] m_snapshots[i].bMapData2; + delete[] m_snapshots[i].wGround; + delete[] m_snapshots[i].bRedrawTerrain; + delete[] m_snapshots[i].overlay; + delete[] m_snapshots[i].overlaydata; + // m_snapshots[i].mapfile.Clear(); + } + if (m_snapshots != NULL) delete[] m_snapshots; + + + + + + fielddata = NULL; + fielddata_size = 0; + m_snapshots = NULL; + dwSnapShotCount = 0; + m_cursnapshot = -1; + + + m_tubes.clear(); + m_tubes.reserve(32); + + m_infantry.clear(); + m_terrain.clear(); + m_units.clear(); + m_structures.clear(); +#ifdef SMUDGE_SUPP + m_smudges.clear(); +#endif + + + m_mapfile.Clear(); + + CString stdMap; + stdMap = AppPath; +#ifdef TS_MODE + stdMap += "\\StdMapTS.ini"; +#endif +#ifdef RA2_MODE + stdMap += "\\StdMapRA2.ini"; +#endif + + m_mapfile.InsertFile(stdMap, NULL); + + char c[50]; + CString mapsize; + itoa(dwWidth, c, 10); + mapsize = "0,0,"; + mapsize += c; + itoa(dwHeight, c, 10); + mapsize += ","; + mapsize += c; + + m_mapfile.sections["Map"].values["Size"] = mapsize; + + itoa(dwWidth - 4, c, 10); + mapsize = "2,4,"; + mapsize += c; + itoa(dwHeight - 6, c, 10); + mapsize += ","; + mapsize += c; + + m_mapfile.sections["Map"].values["Theater"] = lpTerrainType; + m_mapfile.sections["Map"].values["LocalSize"] = mapsize; + + map::iterator it = pics.begin(); + for (int e = 0;e < pics.size();e++) + { + try + { +#ifdef NOSURFACES_OBJECTS + if (it->second.bType == PICDATA_TYPE_BMP) + { + if (it->second.pic != NULL) + { + ((LPDIRECTDRAWSURFACE4)it->second.pic)->Release(); + } + } + else + { + if (it->second.pic != NULL) + { + delete[] it->second.pic; + } + if (it->second.vborder) delete[] it->second.vborder; + } +#else + if (it->second.pic != NULL) it->second.pic->Release(); +#endif + + it->second.pic = NULL; + } + catch (...) + { + CString err; + err = "Access violation while trying to release surface "; + char c[6]; + itoa(e, c, 10); + err += c; + + err += "\n"; + OutputDebugString(err); + continue; + } + + it++; + } + + std::unique_ptr dlg; + if (theApp.m_pMainWnd) + { + dlg.reset(new CDynamicGraphDlg(theApp.m_pMainWnd)); + dlg->ShowWindow(SW_SHOW); + dlg->UpdateWindow(); + } + + pics.clear(); + missingimages.clear(); + + UpdateBuildingInfo(); + UpdateTreeInfo(); + + if (theApp.m_loading) + { + theApp.m_loading->Unload(); + theApp.m_loading->InitMixFiles(); + + if (theApp.m_pMainWnd) + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->UpdateOverlayPictures(); + + theApp.m_loading->InitPics(); + + if (m_mapfile.sections["Map"].values["Theater"] == THEATER0) + { + tiledata = &s_tiledata; + tiledata_count = &s_tiledata_count; + tiles = &tiles_s; + theApp.m_loading->FreeTileSet(); + tiledata = &u_tiledata; + tiledata_count = &u_tiledata_count; + tiles = &tiles_u; + theApp.m_loading->FreeTileSet(); + + // MW new tilesets + tiledata = &un_tiledata; + tiledata_count = &un_tiledata_count; + tiles = &tiles_un; + theApp.m_loading->FreeTileSet(); + tiledata = &d_tiledata; + tiledata_count = &d_tiledata_count; + tiles = &tiles_d; + theApp.m_loading->FreeTileSet(); + tiledata = &l_tiledata; + tiledata_count = &l_tiledata_count; + tiles = &tiles_l; + theApp.m_loading->FreeTileSet(); + + tiledata = &t_tiledata; + tiledata_count = &t_tiledata_count; + tiles = &tiles_t; + theApp.m_loading->FreeTileSet(); + if (dlg) + theApp.m_loading->InitTMPs(&dlg->m_Progress); + theApp.m_loading->cur_theat = 'T'; + + } + else if (m_mapfile.sections["Map"].values["Theater"] == THEATER1) + { + tiledata = &t_tiledata; + tiledata_count = &t_tiledata_count; + tiles = &tiles_t; + theApp.m_loading->FreeTileSet(); + tiledata = &u_tiledata; + tiledata_count = &u_tiledata_count; + tiles = &tiles_u; + theApp.m_loading->FreeTileSet(); + + // MW new tilesets + tiledata = &un_tiledata; + tiledata_count = &un_tiledata_count; + tiles = &tiles_un; + theApp.m_loading->FreeTileSet(); + tiledata = &d_tiledata; + tiledata_count = &d_tiledata_count; + tiles = &tiles_d; + theApp.m_loading->FreeTileSet(); + tiledata = &l_tiledata; + tiledata_count = &l_tiledata_count; + tiles = &tiles_l; + theApp.m_loading->FreeTileSet(); + + tiledata = &s_tiledata; + tiledata_count = &s_tiledata_count; + tiles = &tiles_s; + theApp.m_loading->FreeTileSet(); + if (dlg) + theApp.m_loading->InitTMPs(&dlg->m_Progress); + theApp.m_loading->cur_theat = 'A'; + } + else if (m_mapfile.sections["Map"].values["Theater"] == THEATER2) + { + tiledata = &t_tiledata; + tiledata_count = &t_tiledata_count; + tiles = &tiles_t; + theApp.m_loading->FreeTileSet(); + tiledata = &s_tiledata; + tiledata_count = &s_tiledata_count; + tiles = &tiles_s; + theApp.m_loading->FreeTileSet(); + + // MW new tilesets + tiledata = &un_tiledata; + tiledata_count = &un_tiledata_count; + tiles = &tiles_un; + theApp.m_loading->FreeTileSet(); + tiledata = &d_tiledata; + tiledata_count = &d_tiledata_count; + tiles = &tiles_d; + theApp.m_loading->FreeTileSet(); + tiledata = &l_tiledata; + tiledata_count = &l_tiledata_count; + tiles = &tiles_l; + theApp.m_loading->FreeTileSet(); + + tiledata = &u_tiledata; + tiledata_count = &u_tiledata_count; + tiles = &tiles_u; + theApp.m_loading->FreeTileSet(); + if (dlg) + theApp.m_loading->InitTMPs(&dlg->m_Progress); + theApp.m_loading->cur_theat = 'U'; + } + else if (yuri_mode && m_mapfile.sections["Map"].values["Theater"] == THEATER3) + { + tiledata = &t_tiledata; + tiledata_count = &t_tiledata_count; + tiles = &tiles_t; + theApp.m_loading->FreeTileSet(); + tiledata = &s_tiledata; + tiledata_count = &s_tiledata_count; + tiles = &tiles_s; + theApp.m_loading->FreeTileSet(); + + // MW new tilesets + + tiledata = &d_tiledata; + tiledata_count = &d_tiledata_count; + tiles = &tiles_d; + theApp.m_loading->FreeTileSet(); + tiledata = &l_tiledata; + tiledata_count = &l_tiledata_count; + tiles = &tiles_l; + theApp.m_loading->FreeTileSet(); + + tiledata = &u_tiledata; + tiledata_count = &u_tiledata_count; + tiles = &tiles_u; + theApp.m_loading->FreeTileSet(); + + tiledata = &un_tiledata; + tiledata_count = &un_tiledata_count; + tiles = &tiles_un; + theApp.m_loading->FreeTileSet(); + + if (dlg) + theApp.m_loading->InitTMPs(&dlg->m_Progress); + theApp.m_loading->cur_theat = 'N'; + } + else if (yuri_mode && m_mapfile.sections["Map"].values["Theater"] == THEATER4) + { + tiledata = &t_tiledata; + tiledata_count = &t_tiledata_count; + tiles = &tiles_t; + theApp.m_loading->FreeTileSet(); + tiledata = &s_tiledata; + tiledata_count = &s_tiledata_count; + tiles = &tiles_s; + theApp.m_loading->FreeTileSet(); + + // MW new tilesets + tiledata = &un_tiledata; + tiledata_count = &un_tiledata_count; + tiles = &tiles_un; + theApp.m_loading->FreeTileSet(); + tiledata = &d_tiledata; + tiledata_count = &d_tiledata_count; + tiles = &tiles_d; + theApp.m_loading->FreeTileSet(); + + + tiledata = &u_tiledata; + tiledata_count = &u_tiledata_count; + tiles = &tiles_u; + theApp.m_loading->FreeTileSet(); + + tiledata = &l_tiledata; + tiledata_count = &l_tiledata_count; + tiles = &tiles_l; + theApp.m_loading->FreeTileSet(); + + if (dlg) + { + theApp.m_loading->InitTMPs(&dlg->m_Progress); + } + theApp.m_loading->cur_theat = 'L'; + } + else if (m_mapfile.sections["Map"].values["Theater"] == THEATER5) + { + tiledata = &t_tiledata; + tiledata_count = &t_tiledata_count; + tiles = &tiles_t; + theApp.m_loading->FreeTileSet(); + tiledata = &s_tiledata; + tiledata_count = &s_tiledata_count; + tiles = &tiles_s; + theApp.m_loading->FreeTileSet(); + + // MW new tilesets + tiledata = &un_tiledata; + tiledata_count = &un_tiledata_count; + tiles = &tiles_un; + theApp.m_loading->FreeTileSet(); + + tiledata = &l_tiledata; + tiledata_count = &l_tiledata_count; + tiles = &tiles_l; + theApp.m_loading->FreeTileSet(); + + + tiledata = &u_tiledata; + tiledata_count = &u_tiledata_count; + tiles = &tiles_u; + theApp.m_loading->FreeTileSet(); + + tiledata = &d_tiledata; + tiledata_count = &d_tiledata_count; + tiles = &tiles_d; + theApp.m_loading->FreeTileSet(); + + if (dlg) + theApp.m_loading->InitTMPs(&dlg->m_Progress); + theApp.m_loading->cur_theat = 'D'; + } + else + { + theApp.m_loading->FreeAll(); + CString s = "Fatal error! %9 doesn´t support the theater of this map!"; + s = TranslateStringACP(s); + MessageBox(0, s, "Error", 0); + exit(0); + } + } + else + { + // e.g. unittests + tiles = &tiles_t; + } + + + errstream << "CreateMap() clears data\n"; + errstream.flush(); + + CalcMapRect(); + ClearOverlay(); + ClearOverlayData(); + + isInitialized = TRUE; + if (fielddata != NULL) delete[] fielddata; + + errstream << "CreateMap() allocates memory\n"; + errstream.flush(); + fielddata = new(FIELDDATA[(GetIsoSize() + 1) * (GetIsoSize() + 1)]); // +1 because of some unpacking problems + fielddata_size = (GetIsoSize() + 1) * (GetIsoSize() + 1); + dwIsoMapSize = 0; + + errstream << "CreateMap() frees m_mfd\n"; + errstream.flush(); + if (m_mfd != NULL) delete[] m_mfd; + m_mfd = NULL; + + errstream << "CreateMap() loads from ini\n"; + errstream.flush(); + UpdateIniFile(MAPDATA_UPDATE_FROM_INI); + + AddWaypoint("98", (dwWidth + dwHeight) / 2 + (dwWidth + dwHeight) * (dwWidth + dwHeight) / 2); + AddWaypoint("99", (dwWidth + dwHeight) / 2 + (dwWidth + dwHeight) * (dwWidth + dwHeight) / 2 - 1); + + errstream << "CreateMap() sets terrain height\n"; + errstream.flush(); + + + for (i = 0;i < fielddata_size;i++) + { + fielddata[i].bHeight = dwGroundHeight; + } + + errstream << "CreateMap() finished\n"; + errstream.flush(); + +} + +/*void CMapData::CreateSlopesAt(DWORD dwPos) +{ + //OutputDebugString("CreateSlopes()\n"); + + FIELDDATA m=*GetFielddataAt(dwPos); + if(m.wGround==0xFFFF) m.wGround=0; + + TILEDATA& d=(*tiledata)[m.wGround]; + + int ns=-1; + int i,e,p=0; + int h[3][3]; + for(i=0;i<3; i++) + { + for(e=0;e<3;e++) + { + int pos=dwPos+(i-1)+(e-1)*m_IsoSize; + if(pos<0 || pos>=m_IsoSize*m_IsoSize) + { + h[i][e]=0; + } + else + { + FIELDDATA m2=*GetFielddataAt(pos); + + h[i][e]=m.bHeight-m2.bHeight; + } + + + } + } + + // hmm... check if the current tile must be heightened anyway + if(!theApp.m_Options.bDisableSlopeCorrection && d.bMorphable) + { + if((h[0][1]<0 && h[2][1]<0) || (h[1][0]<0 && h[1][2]<0) + + || (h[1][0]<0 && h[0][2]<0 && h[0][1]>=0) + || (h[1][0]<0 && h[2][2]<0 && h[2][1]>=0) + + || (h[0][1]<0 && h[2][0]<0 && h[1][0]>=0) + || (h[0][1]<0 && h[2][2]<0 && h[1][2]>=0) + + || (h[1][2]<0 && h[0][0]<0 && h[0][1]>=0) + || (h[1][2]<0 && h[2][0]<0 && h[2][1]>=0) + + || (h[2][1]<0 && h[0][0]<0 && h[1][0]>=0) + || (h[2][1]<0 && h[0][2]<0 && h[1][2]>=0) + + || (h[1][0]<0 && h[0][1]<0 && h[0][0]>=0) + || (h[0][1]<0 && h[1][2]<0 && h[0][2]>=0) + || (h[1][2]<0 && h[2][1]<0 && h[2][2]>=0) + || (h[2][1]<0 && h[1][0]<0 && h[2][0]>=0) + + ) + { + SetHeightAt(dwPos, m.bHeight+1); + for(i=-1;i<2;i++) + for(e=-1;e<2;e++) + CreateSlopesAt(dwPos+i+e*m_IsoSize); + + return; + } + } + + //OutputDebugString("Running check\n"); + + BOOL checkOtherSlopes=FALSE; + /*if(h[0][0] && h[0][1] && h[0][2] && h[1][0] && h[1][2] && h[2][0] && h[2][1] && h[2][2]) + { + ns=-1; + checkOtherSlopes=TRUE; + }*//* + + if(h[0][0]==-1 && h[2][2]==-1 && h[2][0]>=0 && h[0][2]>=0 && h[1][0]>=0 && h[1][2]>=0 && h[0][1]>=0 && h[2][1]>=0) ns=SLOPE_UP_LEFTTOP_AND_RIGHTBOTTOM; + if(h[0][2]==-1 && h[2][0]==-1 && h[0][0]>=0 && h[2][2]>=0 && h[0][1]>=0 && h[1][0]>=0 && h[1][2]>=0 && h[2][1]>=0) ns=SLOPE_UP_LEFTBOTTOM_AND_RIGHTTOP; + + // that would just be another solution: + // if(h[0][0]==-1 && h[2][2]==-1 && h[2][0]>=0 && h[0][2]>=0 && h[1][0]>=0 && h[1][2]>=0 && h[0][1]>=0 && h[2][1]>=0) ns=SLOPE_UP_LEFTTOP_AND_RIGHTBOTTOM2; + // if(h[0][2]==-1 && h[2][0]==-1 && h[0][0]>=0 && h[2][2]>=0 && h[0][1]>=0 && h[1][0]>=0 && h[1][2]>=0 && h[2][1]>=0) ns=SLOPE_UP_LEFTBOTTOM_AND_RIGHTTOP2; + + + + if(ns==-1) + if(h[1][0]==-1 && h[0][1]!=-1 && h[1][2]!=-1 && h[2][1]!=-1) + { + ns=SLOPE_UP_LEFT; + } + else if(h[0][1]==-1 && h[1][0]!=-1 && h[2][1]!=-1 && h[1][2]!=-1) + { + ns=SLOPE_UP_TOP; + } + else if(h[1][2]==-1 && h[0][1]!=-1 && h[1][0]!=-1 && h[2][1]!=-1) + { + ns=SLOPE_UP_RIGHT; + } + else if(h[2][1]==-1 && h[0][1]!=-1 && h[1][0]!=-1 && h[1][2]!=-1) + { + ns=SLOPE_UP_BOTTOM; + } + + if(ns==-1) + { + if(h[0][0]==-2) ns=SLOPE_DOWN_BOTTOM; + if(h[2][0]==-2) ns=SLOPE_DOWN_RIGHT; + if(h[0][2]==-2) ns=SLOPE_DOWN_LEFT; + if(h[2][2]==-2) ns=SLOPE_DOWN_TOP; + } + + if(ns==-1 && h[0][0]==-1) + { + if(h[1][0]==-1 && h[0][1]==-1 ) ns=SLOPE_DOWN_RIGHTBOTTOM; + else if(h[1][0]==0 && h[0][1]==0) ns=SLOPE_UP_LEFTTOP; + //else if(h[2][2]==1) ns=SLOPE_DOWN_BOTTOM; + } + + if( ns==-1 && h[2][0]==-1) + { + if(h[1][0]==-1 && h[2][1]==-1 ) ns=SLOPE_DOWN_RIGHTTOP; + else if(h[1][0]==0 && h[2][1]==0) ns=SLOPE_UP_LEFTBOTTOM; + //else if(h[0][2]==1) ns=SLOPE_DOWN_RIGHT; + } + if( ns==-1 && h[0][2]==-1) + { + if(h[1][2]==-1 && h[0][1]==-1 ) ns=SLOPE_DOWN_LEFTBOTTOM; + else if(h[1][2]==0 && h[0][1]==0) ns=SLOPE_UP_RIGHTTOP; + //else if(h[2][0]==1) ns=SLOPE_DOWN_LEFT; + } + if( ns==-1 && h[2][2]==-1) + { + if(h[1][2]==-1 && h[2][1]==-1 ) ns=SLOPE_DOWN_LEFTTOP; + else if(h[1][2]==0 && h[2][1]==0) ns=SLOPE_UP_RIGHTBOTTOM; + //else if(h[0][0]==1) ns=SLOPE_DOWN_TOP; + } + + if(ns==-1 && h[1][0]==-1 && h[2][1]==-1 ) ns=SLOPE_DOWN_RIGHTTOP; + if(ns==-1 && h[1][2]==-1 && h[2][1]==-1 ) ns=SLOPE_DOWN_LEFTTOP; + if(ns==-1 && h[1][0]==-1 && h[0][1]==-1 ) ns=SLOPE_DOWN_RIGHTBOTTOM; + if(ns==-1 && h[1][2]==-1 && h[0][1]==-1 ) ns=SLOPE_DOWN_LEFTBOTTOM; + + + //OutputDebugString("Applying changes()\n"); + + + + int rampbase=atoi((*tiles).sections["General"].values["RampBase"]); + int rampsmooth=atoi((*tiles).sections["General"].values["RampSmooth"]); + + //if((rampbase==d.wTileSet || rampsmooth==d.wTileSet) && m.bSubTile==ns) + // return; + + if(ns==-1 && (d.wTileSet==rampbase || d.wTileSet==rampsmooth) && d.bMorphable) + { + SetTileAt(dwPos, 0, 0); + } + if(d.bMorphable && ns!=-1) + { + SetTileAt(dwPos, GetTileID(rampbase, ns-1), 0); + + } + + + + /*if(ns!=-1 || checkOtherSlopes) + { + for(i=-1;i<2;i++) + { + for(e=-1;e<2;e++) + { + int pos=dwPos+(i)+(e)*m_IsoSize; + if(pos>0 && possections.find(sec) == tiles->sections.end()) return 0xFFFFFFFF; + + + for (e = 0;e < atoi(tiles->sections[sec].values["TilesInSet"]);e++) + { + if (i == dwTileSet && e == iTile) return tilecount; + tilecount++; + + } + + + } + + return tilecount; + +} + +void CMapData::SetReserved(DWORD dwPos, BYTE val) +{ + fielddata[dwPos].bReserved = val; +} + + + +void CMapData::HideField(DWORD dwPos, BOOL bHide) +{ + fielddata[dwPos].bHide = bHide; +} + + + +void CMapData::UpdateTubes(BOOL bSave) +{ + if (!bSave) + { + m_tubes.clear(); + if (m_mapfile.sections.find("Tubes") == m_mapfile.sections.end()) + return; + + auto& tubeSection = m_mapfile.sections["Tubes"]; + + std::uint16_t secSize = tubeSection.values.size(); + m_tubes.reserve(secSize + 10); + + for (auto& [sTubeId, value] : tubeSection) + { + const auto tubeId = std::atoi(sTubeId); + if (tubeId < 0 || tubeId >= std::numeric_limits::max()) + continue; + m_tubes.push_back(std::make_unique(static_cast(tubeId), value.GetString())); + } + } + else + { + + } + +} + + + +void CMapData::SetTube(CTube* lpTI) +{ + CString sTubeId; + if (lpTI->hasId()) + sTubeId = std::to_string(lpTI->getId()).c_str(); + else + { + for (std::uint16_t i = 0;i < 10000;i++) + { + sTubeId = std::to_string(i).c_str(); + if (m_mapfile.sections["Tubes"].values.find(sTubeId) == m_mapfile.sections["Tubes"].values.end()) + { + lpTI->setId(i); + break; + } + } + } + + if (!lpTI->hasId()) + return; + + m_mapfile.sections["Tubes"].values[sTubeId] = lpTI->toString().c_str(); + UpdateTubes(FALSE); +} + +CTube* CMapData::GetTube(std::uint16_t wID) +{ + auto it = std::find_if(m_tubes.begin(), m_tubes.end(), [wID](const auto& el) {return el->getId() == wID;}); + if (it == m_tubes.end()) + return nullptr; + + return it->get(); +} + + +void CMapData::DeleteTube(std::uint16_t wID) +{ + if (m_mapfile.sections.find("Tubes") == m_mapfile.sections.end()) + return; + + auto& tubeSection = m_mapfile.sections["Tubes"]; + const CString sTubeId = std::to_string(wID).c_str(); + + std::erase_if(tubeSection.values, [&sTubeId](const auto& el) {return el.first == sTubeId;}); + + //CString id1 = *m_mapfile.sections["Tubes"].GetValueName(wID); + + /*CTube i1 = m_tubes[wID]; + + vector toErase; + toErase.reserve(10); + + // we delete every tube with same starting coordinates or when starting coordinate of i1 is ending of curi + int i; + for (i = 0;i < m_tubes.size();i++) + { + CTube& curi = m_tubes[i]; + if ((curi.getEndX() == i1.getStartX() && curi.getEndY() == i1.getStartY()) || (curi.getStartX() == i1.getStartX() && curi.getStartY() == i1.getStartY())) + { + toErase.push_back(*m_mapfile.sections["Tubes"].GetValueName(i)); + } + } + + for (i = 0;i < toErase.size();i++) + { + m_mapfile.sections["Tubes"].values.erase(toErase[i]); + }*/ + + UpdateTubes(FALSE); +} + +int CMapData::GetInfantryCountAt(DWORD dwPos) +{ + int i; + int sc = 0; + for (i = 0;i < SUBPOS_COUNT;i++) + { + if (fielddata[dwPos].infantry[i] > -1) sc++; + } + + return sc; +} + +/* +Checks if the map data is valid +May fail if the user changed the tileset manually, +or if loading maps made with modified tilesets +*/ +BOOL CMapData::CheckMapPackData() +{ + int i; + for (i = 0;i < fielddata_size;i++) + { + int gr = fielddata[i].wGround; + if (gr != 0xFFFF && gr >= (*tiledata_count)) + return FALSE; + if (gr == 0xFFFF) gr = 0; + if ((*tiledata)[gr].wTileCount <= fielddata[i].bSubTile) return FALSE; + } + + return TRUE; +} + +/* +Takes a snapshot of the map at a certain location. +Be aware that this won´t make a copy of any units etc. + +This is used for undo and similar things (like displaying and immediatly removing tiles when moving +the mouse on the map before placing a tile). +This method is very fast, as long as you don´t copy the whole map all the time. +*/ +void CMapData::TakeSnapshot(BOOL bEraseFollowing, int left, int top, int right, int bottom) +{ + DWORD dwOldSnapShotCount = dwSnapShotCount; + + if (left < 0) left = 0; + if (top < 0) top = 0; + if (right > m_IsoSize) right = m_IsoSize; + if (bottom > m_IsoSize) bottom = m_IsoSize; + + if (right == 0) right = m_IsoSize; + if (bottom == 0) bottom = m_IsoSize; + + int e; + if (bEraseFollowing) + { + for (e = dwSnapShotCount - 1;e > m_cursnapshot;e--) + { + delete[] m_snapshots[e].bHeight; + delete[] m_snapshots[e].bMapData; + delete[] m_snapshots[e].bSubTile; + delete[] m_snapshots[e].bMapData2; + delete[] m_snapshots[e].overlay; + delete[] m_snapshots[e].overlaydata; + delete[] m_snapshots[e].wGround; + delete[] m_snapshots[e].bRedrawTerrain; + delete[] m_snapshots[e].bRNDData; + // m_snapshots[0].mapfile.Clear(); + } + dwSnapShotCount = m_cursnapshot + 1; + } + + + dwSnapShotCount += 1; + m_cursnapshot++; + + if (dwSnapShotCount > 64) + { + dwSnapShotCount = 64; + m_cursnapshot = 63; + int i; + delete[] m_snapshots[0].bHeight; + delete[] m_snapshots[0].bMapData; + delete[] m_snapshots[0].bSubTile; + delete[] m_snapshots[0].bMapData2; + delete[] m_snapshots[0].overlay; + delete[] m_snapshots[0].overlaydata; + delete[] m_snapshots[0].wGround; + delete[] m_snapshots[0].bRedrawTerrain; + delete[] m_snapshots[0].bRNDData; + // m_snapshots[0].mapfile.Clear(); + for (i = 1;i < dwSnapShotCount;i++) + { + m_snapshots[i - 1] = m_snapshots[i]; + } + + } + else + { + SNAPSHOTDATA* b = new(SNAPSHOTDATA[dwSnapShotCount]); + + if (m_snapshots) + { + memcpy(b, m_snapshots, sizeof(SNAPSHOTDATA) * (dwSnapShotCount - 1)); + delete[] m_snapshots; + } + + m_snapshots = b; + } + + + m_cursnapshot = dwSnapShotCount - 1; + + + SNAPSHOTDATA ss = m_snapshots[dwSnapShotCount - 1]; + // ss.mapfile=m_mapfile; + int width, height; + width = right - left; + height = bottom - top; + + int size = width * height; + ss.left = left; + ss.top = top; + ss.right = right; + ss.bottom = bottom; + ss.bHeight = new(BYTE[size]); + ss.bMapData = new(WORD[size]); + ss.bSubTile = new(BYTE[size]); + ss.bMapData2 = new(BYTE[size]); + ss.wGround = new(WORD[size]); + ss.overlay = new(BYTE[size]); + ss.overlaydata = new(BYTE[size]); + ss.bRedrawTerrain = new(BOOL[size]); + ss.bRNDData = new(BYTE[size]); + int i; + for (i = 0;i < width;i++) + { + for (e = 0;e < height;e++) + { + int pos_w, pos_r; + pos_w = i + e * width; + pos_r = left + i + (top + e) * m_IsoSize; + ss.bHeight[pos_w] = fielddata[pos_r].bHeight; + ss.bMapData[pos_w] = fielddata[pos_r].bMapData; + ss.bSubTile[pos_w] = fielddata[pos_r].bSubTile; + ss.bMapData2[pos_w] = fielddata[pos_r].bMapData2; + ss.wGround[pos_w] = fielddata[pos_r].wGround; + ss.overlay[pos_w] = fielddata[pos_r].overlay; + ss.overlaydata[pos_w] = fielddata[pos_r].overlaydata; + ss.bRedrawTerrain[pos_w] = fielddata[pos_r].bRedrawTerrain; + ss.bRNDData[pos_w] = fielddata[pos_r].bRNDImage; + } + } + + m_snapshots[dwSnapShotCount - 1] = ss; + +} + +/* +Just uses the last SnapShot to reverse changes on the map. +Very fast +*/ +void CMapData::Undo() +{ + if (dwSnapShotCount == 0) return; + if (m_cursnapshot < 0) return; + + + //dwSnapShotCount--; + m_cursnapshot -= 1; + + int left, top, width, height; + left = m_snapshots[m_cursnapshot + 1].left; + top = m_snapshots[m_cursnapshot + 1].top; + width = m_snapshots[m_cursnapshot + 1].right - left; + height = m_snapshots[m_cursnapshot + 1].bottom - top; + + const bool mp = IsMultiplayer(); + int i, e; + for (i = 0;i < width;i++) + { + for (e = 0;e < height;e++) + { + int pos_w, pos_r; + pos_r = i + e * width; + pos_w = left + i + (top + e) * m_IsoSize; + fielddata[pos_w].bHeight = m_snapshots[m_cursnapshot + 1].bHeight[pos_r]; + fielddata[pos_w].bMapData = m_snapshots[m_cursnapshot + 1].bMapData[pos_r]; + fielddata[pos_w].bSubTile = m_snapshots[m_cursnapshot + 1].bSubTile[pos_r]; + fielddata[pos_w].bMapData2 = m_snapshots[m_cursnapshot + 1].bMapData2[pos_r]; + fielddata[pos_w].wGround = m_snapshots[m_cursnapshot + 1].wGround[pos_r]; + + RemoveOvrlMoney(fielddata[pos_w].overlay, fielddata[pos_w].overlaydata); + fielddata[pos_w].overlay = m_snapshots[m_cursnapshot + 1].overlay[pos_r]; + fielddata[pos_w].overlaydata = m_snapshots[m_cursnapshot + 1].overlaydata[pos_r]; + AddOvrlMoney(fielddata[pos_w].overlay, fielddata[pos_w].overlaydata); + + + + fielddata[pos_w].bRedrawTerrain = m_snapshots[m_cursnapshot + 1].bRedrawTerrain[pos_r]; + fielddata[pos_w].bRNDImage = m_snapshots[m_cursnapshot + 1].bRNDData[pos_r]; + + + Mini_UpdatePos(left + i, top + e, mp); + } + } + + // no need for SmoothTiberium: handled externally, because we undo more than just the very needed area + // when changing overlay! + + + +} + +BOOL CMapData::GetLocalSize(RECT* rect) const +{ + if (!isInitialized) return FALSE; + + *rect = m_vismaprect; + + return TRUE; +} + + + +/* +Opposite of Undo(). If possible, redoes the changes. +Very fast. +*/ +void CMapData::Redo() +{ + if (dwSnapShotCount <= m_cursnapshot + 1 || !dwSnapShotCount) return; + + m_cursnapshot += 1; // dwSnapShotCount-1; + + if (m_cursnapshot + 1 >= dwSnapShotCount) m_cursnapshot = dwSnapShotCount - 2; + + int left, top, width, height; + left = m_snapshots[m_cursnapshot + 1].left; + top = m_snapshots[m_cursnapshot + 1].top; + width = m_snapshots[m_cursnapshot + 1].right - left; + height = m_snapshots[m_cursnapshot + 1].bottom - top; + + int i, e; + const bool mp = IsMultiplayer(); + for (i = 0;i < width;i++) + { + for (e = 0;e < height;e++) + { + int pos_w, pos_r; + pos_r = i + e * width; + pos_w = left + i + (top + e) * m_IsoSize; + fielddata[pos_w].bHeight = m_snapshots[m_cursnapshot + 1].bHeight[pos_r]; + fielddata[pos_w].bMapData = m_snapshots[m_cursnapshot + 1].bMapData[pos_r]; + fielddata[pos_w].bSubTile = m_snapshots[m_cursnapshot + 1].bSubTile[pos_r]; + fielddata[pos_w].bMapData2 = m_snapshots[m_cursnapshot + 1].bMapData2[pos_r]; + fielddata[pos_w].wGround = m_snapshots[m_cursnapshot + 1].wGround[pos_r]; + RemoveOvrlMoney(fielddata[pos_w].overlay, fielddata[pos_w].overlaydata); + fielddata[pos_w].overlay = m_snapshots[m_cursnapshot + 1].overlay[pos_r]; + fielddata[pos_w].overlaydata = m_snapshots[m_cursnapshot + 1].overlaydata[pos_r]; + AddOvrlMoney(fielddata[pos_w].overlay, fielddata[pos_w].overlaydata); + fielddata[pos_w].bRedrawTerrain = m_snapshots[m_cursnapshot + 1].bRedrawTerrain[pos_r]; + fielddata[pos_w].bRNDImage = m_snapshots[m_cursnapshot + 1].bRNDData[pos_r]; + + Mini_UpdatePos(left + i, top + e, mp); + } + } + + /* + int i; + for(i=0;i= *tiledata_count) + return false; + const auto set = (*tiledata)[wGround].wTileSet; + + const auto& sec = tiles->sections["General"]; + const CString empty; + + for (int i = 0; i < tile_to_lat_count; ++i) + { + const int tile = atoi(sec.GetValueByName(tile_to_lat[i][0], empty)); + const int lat = atoi(sec.GetValueByName(tile_to_lat[i][1], empty)); + const int target_tile = atoi(sec.GetValueByName(tile_to_lat[i][2], empty)); + if (lat && + (set == tile || + set == lat || + set == target_tile)) + return true; + } + + return false; +} + +void CMapData::SmoothAllAt(DWORD dwPos) +{ + if (theApp.m_Options.bDisableAutoLat) return; + + if (dwPos > fielddata_size) return; + + int set = 0, ground = fielddata[dwPos].wGround; + + if (ground == 0xFFFF) ground = 0; + set = (*tiledata)[ground].wTileSet; + + const auto& sec = tiles->sections["General"]; + const CString empty; + + for (int i = 0; i < tile_to_lat_count; ++i) + { + const int tile = atoi(sec.GetValueByName(tile_to_lat[i][0], empty)); + const int lat = atoi(sec.GetValueByName(tile_to_lat[i][1], empty)); + const int target_tile = atoi(sec.GetValueByName(tile_to_lat[i][2], empty)); + if (strlen(tile_to_lat[i][2]) && + lat && + (set == tile || + set == lat)) + SmoothAt(dwPos, tile, lat, target_tile); + } +} + +void CMapData::CreateShore(int left, int top, int right, int bottom, BOOL bRemoveUseless) +{ + + + int i; + int isosize = Map->GetIsoSize(); + int mapsize = isosize * isosize; + int mapwidth = Map->GetWidth(); + int mapheight = Map->GetHeight(); + // int shoreset=atoi((*tiles).sections["General"].values["ShorePieces"]); + + short* tsets = new(short[mapsize]); + BYTE* terrain = new(BYTE[mapsize]); + int* tile = new(int[mapsize]); + BOOL* hasChanged = new(BOOL[isosize * isosize]); + BOOL* noChange = new(BOOL[isosize * isosize]); + //BOOL* replaced=new(BOOL[isosize*isosize]); // replaced by water<->ground + + memset(hasChanged, 0, sizeof(BOOL) * isosize * isosize); + memset(noChange, 0, sizeof(BOOL) * isosize * isosize); + //memset(replaced, 0, sizeof(BOOL)*isosize*isosize); + + int watercliffset = atoi((*tiles).sections["General"].values["WaterCliffs"]); + int xx, yy; + + for (i = 0;i < *tiledata_count;i++) + { + if ((*tiledata)[i].wTileSet == waterset && (*tiledata)[i].cx == 1 && (*tiledata)[i].cy == 1) break; + } + + int smallwater = i; + + + + + last_succeeded_operation = 7002; + + + map softsets; + CString sec = "SoftTileSets"; + + for (i = 0;i < g_data.sections[sec].values.size();i++) + { + CString tset = *g_data.sections[sec].GetValueName(i); + TruncSpace(tset); + int p = (*tiles).sections["General"].FindName(tset); + if (p < 0) continue; + + int set = atoi(*(*tiles).sections["General"].GetValue(p)); + if (atoi(*g_data.sections[sec].GetValue(i))) softsets[set] = 1; + + + } + + + + + last_succeeded_operation = 7001; + + // remove partial shore pieces (wrong ones) + for (xx = left - 2;xx < right + 2;xx++) + { + for (yy = top - 2;yy < bottom + 2;yy++) + { + + if (xx < 1 || yy < 1 || xx + yymapwidth + mapheight * 2 || (yy + 1 > mapwidth && xx - 1 < yy - mapwidth) || (xx + 1 > mapwidth && yy + mapwidth - 1 < xx)) continue; + + int pos = xx + yy * isosize; + if (noChange[pos]) continue; + + FIELDDATA* fd = Map->GetFielddataAt(pos); + int ground = fd->wGround; + if (ground == 0xFFFF) ground = 0; + TILEDATA& td = (*tiledata)[ground]; + if (td.wTileSet != shoreset) continue; + + // we have a shore piece here. check if it is set correct + BOOL bCorrect = TRUE; + + int of = fd->bSubTile; + + int ox = of / td.cy; + int oy = of % td.cy; + + + int xxx, yyy; + int p = 0; + for (xxx = xx - ox;xxx < xx + td.cx - ox;xxx++) + { + for (yyy = yy - oy;yyy < yy + td.cy - oy;yyy++) + { + int pos = xxx + yyy * isosize; + if (td.tiles[p].pic != NULL) + { + FIELDDATA* curf = Map->GetFielddataAt(pos); + int curg = curf->wGround; + if (curg == 0xFFFF) curg = 0; + + if (curg != ground || curf->bSubTile != p) + { + bCorrect = FALSE; + break; + } + } + p++; + } + if (!bCorrect) break; + } + + if (!bCorrect) + { + int iWaterFound = 0; + /*for(xxx=xx-1;xxx<=xx+1;xxx++) + { + for(yyy=yy-1;yyy<=yy+1;yyy++) + { + if(xxx==xx && yyy==yy) continue; + + int pos=xxx+yyy*isosize; + FIELDDATA* curf=Map->GetFielddataAt(pos); + int curg=curf->wGround; + if(curg==0xFFFF) curg=0; + + if((*tiledata)[curg].tiles[curf->bSubTile].bHackedTerrainType==TERRAINTYPE_WATER) + iWaterFound++; + + } + }*/ + + int pos = xx + yy * isosize; + FIELDDATA* curf = Map->GetFielddataAt(pos); + int curg = curf->wGround; + if (curg == 0xFFFF) curg = 0; + + if ((*tiledata)[curg].tiles[curf->bSubTile].bHackedTerrainType == TERRAINTYPE_WATER) iWaterFound = 8; + + if (iWaterFound > 7) + { + for (i = 0;i < *tiledata_count;i++) + { + if ((*tiledata)[i].wTileSet == waterset && (*tiledata)[i].cx == 1 && (*tiledata)[i].cy == 1) break; + } + SetTileAt(xx + yy * isosize, i, 0); + noChange[xx + yy * isosize] = FALSE; + //replaced[xx+yy*isosize]=TRUE; + } + else + { + SetTileAt(xx + yy * isosize, 0, 0); + noChange[xx + yy * isosize] = FALSE; + //replaced[xx+yy*isosize]=TRUE; + + } + } + + } + } + + + // remove too small water and ground pieces (NEW) + if (bRemoveUseless) + { + for (xx = left;xx < right;xx++) + { + for (yy = top;yy < bottom;yy++) + { + + if (xx < 1 || yy < 1 || xx + yymapwidth + mapheight * 2 || (yy + 1 > mapwidth && xx - 1 < yy - mapwidth) || (xx + 1 > mapwidth && yy + mapwidth - 1 < xx)) continue; + + int dwPos = xx + yy * isosize; + + //if(noChange[dwPos]) continue; + + FIELDDATA* fd = Map->GetFielddataAt(dwPos); + int ground = fd->wGround; + if (ground == 0xFFFF) ground = 0; + TILEDATA& td = (*tiledata)[ground]; + + if (softsets.find(td.wTileSet) == softsets.end()) continue; + + if (td.tiles[fd->bSubTile].bHackedTerrainType != TERRAINTYPE_WATER && td.tiles[fd->bSubTile].bHackedTerrainType != TERRAINTYPE_GROUND) continue; + + int ts[3][3]; // terrain info + int i, e; + for (i = 0;i < 3; i++) + { + for (e = 0;e < 3;e++) + { + int pos = dwPos + (i - 1) + (e - 1) * m_IsoSize; + if (pos < 0 || pos >= fielddata_size) + { + ts[i][e] = 0; + } + else + { + FIELDDATA m2 = *GetFielddataAt(pos); + if (m2.wGround == 0xFFFF) m2.wGround = 0; + + ts[i][e] = (*tiledata)[m2.wGround].tiles[m2.bSubTile].bHackedTerrainType; + } + } + } + + + if ((ts[1][0] != ts[1][1] && ts[1][2] != ts[1][1]) || + (ts[0][1] != ts[1][1] && ts[2][1] != ts[1][1])) + { + if (ts[1][1] == TERRAINTYPE_WATER) + { + SetTileAt(dwPos, 0, 0); + //replaced[dwPos]=TRUE; + } + else if (ts[1][1] == TERRAINTYPE_GROUND) + { + if ((ts[1][0] == TERRAINTYPE_WATER && ts[1][2] == TERRAINTYPE_WATER) || (ts[0][1] == TERRAINTYPE_WATER && ts[2][1] == TERRAINTYPE_WATER)) + { + SetTileAt(dwPos, smallwater, 0); + //replaced[dwPos]=TRUE; + } + } + } + + } + } + } + + + last_succeeded_operation = 7003; + + // retrieve non-changeable fields + for (xx = left;xx < right;xx++) + { + for (yy = top;yy < bottom;yy++) + { + if (xx < 1 || yy < 1 || xx + yymapwidth + mapheight * 2 || (yy + 1 > mapwidth && xx - 1 < yy - mapwidth) || (xx + 1 > mapwidth && yy + mapwidth - 1 < xx)) continue; + + int pos = xx + yy * isosize; + FIELDDATA* fd = GetFielddataAt(pos); + int ground = fd->wGround; + if (ground == 0xFFFF) ground = 0; + + tsets[pos] = (*tiledata)[ground].wTileSet; + terrain[pos] = (*tiledata)[ground].tiles[fd->bSubTile].bHackedTerrainType; + tile[pos] = ground; + + if (xx >= left && xx < right && yy >= top && yy < bottom) + { + + if (softsets.find((*tiledata)[ground].wTileSet) == softsets.end()/*(*tiledata)[ground].wTileSet==cliffset || (*tiledata)[ground].wTileSet==watercliffset*/) + { + noChange[pos] = TRUE; continue; + } + + + + TILEDATA& td = (*tiledata)[ground]; + + if (td.wTileSet == shoreset) + { + int of = fd->bSubTile; + + int ox = of / td.cy; + int oy = of % td.cy; + + if (xx - ox < left || yy - oy < top || xx - ox + td.cx >= right || yy - oy + td.cy >= bottom) + { + /*if(!replaced[pos])*/ noChange[pos] = TRUE; + } + } + } + } + } + + + + + /*CProgressCtrl pc; + RECT r,rw; + GetWindowRect(&r); + rw.left=r.left+(r.right-r.left)/2-80; + rw.top=r.top+(r.bottom-r.top)/2-15; + rw.right=rw.left+160; + rw.bottom=rw.top+30; + pc.Create(WS_POPUPWINDOW | PBS_SMOOTH, rw, m_view.m_isoview, 0);*/ + + int tStart, tEnd; + tStart = -1; + tEnd = 0; + for (i = 0;i < *tiledata_count;i++) + { + if ((*tiledata)[i].wTileSet == shoreset) + { + if (tStart < 0) tStart = i; + if (i > tEnd) tEnd = i; + } + } + + /*pc.SetRange(0, (tEnd-tStart)*2); + pc.ShowWindow(SW_SHOW); + pc.RedrawWindow();*/ + + + last_succeeded_operation = 7004; + + for (i = tStart;i <= tEnd;i++) + { + /*pc.SetPos(i-tStart); + pc.UpdateWindow();*/ + TILEDATA& td = (*tiledata)[i]; + + if (td.wTileSet == shoreset) + { + int pos = i - tStart; + if (pos != 4 && pos != 5 && pos != 12 && pos != 13 && pos != 20 && pos != 21 && pos != 28 && pos != 29 + && pos != 6 && pos != 7 && pos != 14 && pos != 15 && pos != 22 && pos != 23 && pos != 30 && pos != 31 && (pos < 32 || pos>39)) + continue; + + int x, y; + int water_count = 0; + int p = 0; + for (x = 0;x < td.cx;x++) + { + for (y = 0;y < td.cy;y++) + { + if (td.tiles[p].bHackedTerrainType == TERRAINTYPE_WATER) + water_count++; + p++; + } + } + + // tsets now has the tileset of every single field in range (x+16, y+16) + // terrain has the terrain type of every single field + int max_x = td.cx < 16 ? td.cx : 16; + int max_y = td.cy < 16 ? td.cy : 16; + + for (x = left;x < right;x++) + { + for (y = top;y < bottom;y++) + { + last_succeeded_operation = 7010; + + int xx, yy; + + //if(!replaced[x+y*isosize] && (x=right || y>=bottom)) continue; + if (x < 1 || y < 1 || x + ymapwidth + mapheight * 2 || (y + 1 > mapwidth && x - 1 < y - mapwidth) || (x + 1 > mapwidth && y + mapwidth - 1 < x)) continue; + + + /*BOOL wat_ex=FALSE; + for(xx=x;xxGetFielddataAt(xx+yy*isosize); + int ground=fd->wGround; + if(ground==0xFFFF) ground=0; + int tile_t=(*tiledata)[ground].tiles[fd->bSubTile].bHackedTerrainType; + if(tile_t==TERRAINTYPE_WATER || tile_t==0xa) + wat_ex=TRUE; + if(wat_ex) break; + } + if(wat_ex) break; + } + if(!wat_ex) continue;*/ + + BOOL bFits = TRUE; + int p = 0; + for (xx = x;xx < x + max_x;xx++) + { + for (yy = y;yy < y + max_y;yy++) + { + if (xx >= isosize || yy >= isosize) continue; + + + int tpos = i - tStart; + int xadd = 0, yadd = 0; + + /* + if(tpos>=0 && tpos<=7) xadd=1; + if(tpos>=6 && tpos<=15) yadd=1; + if(tpos>=14 && tpos<=23) xadd=-1; + if(tpos>=22 && tpos<=31) yadd=-1; + if(tpos>=30 && tpos<=31) xadd=1; + + if(tpos>=32 && tpos<=33) + { + xadd=1; yadd=1; + + } + + if(tpos>=34 && tpos<=35) + { + xadd=-1; yadd=1; + + } + + if(tpos>=36 && tpos<=37) + { + xadd=-1; yadd=-1; + + } + + if(tpos>=38 && tpos<=39) + { + xadd=1; yadd=-1; + + }*/ + + /*if(tpos>=32 && tpos<=33) + { + xadd=1; yadd=1; + if( + terrain[xx+1+yy*isosize]==TERRAINTYPE_WATER || terrain[xx+(yy+1)*isosize]==TERRAINTYPE_WATER + ) + {bFits=FALSE; break;} + } + + if(tpos>=34 && tpos<=35) + { + xadd=-1; yadd=1; + if( + terrain[xx-1+yy*isosize]==TERRAINTYPE_WATER || terrain[xx+(yy+1)*isosize]==TERRAINTYPE_WATER + ) + {bFits=FALSE; break;} + } + + if(tpos>=36 && tpos<=37) + { + xadd=-1; yadd=-1; + if( + terrain[xx-1+yy*isosize]==TERRAINTYPE_WATER || terrain[xx+(yy-1)*isosize]==TERRAINTYPE_WATER + ) + {bFits=FALSE; break;} + } + + if(tpos>=38 && tpos<=39) + { + xadd=1; yadd=-1; + if( + terrain[xx+1+yy*isosize]==TERRAINTYPE_WATER || terrain[xx+(yy-1)*isosize]==TERRAINTYPE_WATER + ) + {bFits=FALSE; break;} + }*/ + + last_succeeded_operation = 7011; + + if (xadd && yadd) + { + if (tsets[xx + xadd + yy * isosize] == waterset || tsets[xx + (yy + yadd) * isosize] == waterset) + { + bFits = FALSE; + break; + } + } + + + int pos_water = xx + xadd + (yy + yadd) * isosize; + int pos_data = xx + yy * isosize; + + + + BYTE& tile_t = td.tiles[p].bHackedTerrainType; + + if (tsets[pos_data] == shoreset) + { + if (hasChanged[pos_data]) // only cancel if this routine set the shore + { + // curves are preferred + if ((max_x != 2 || max_y != 2 || water_count != 3)) + { + if (!((max_x == 3 && max_y == 2) || (max_x == 2 && max_y == 3))) + { + bFits = FALSE; + break; + } + + } + + } + } + + last_succeeded_operation = 7012; + + // one step curves + if (noChange[pos_data]) + { + bFits = FALSE; + break; + } + + + // 2 big shore pieces need special treatment + if (tile[pos_data] <= tEnd && tile[pos_data] >= tEnd - 2) + bFits = FALSE; + + if (tile_t == TERRAINTYPE_WATER) + { + if (terrain[pos_water] != TERRAINTYPE_WATER) + { + bFits = FALSE; + } + } + else + { + if (terrain[pos_water] != TERRAINTYPE_GROUND) + //if(tsets[pos_water]==waterset) + { + bFits = FALSE; + } + } + + + if (!bFits) break; + p++; + } + if (!bFits) break; + } + + last_succeeded_operation = 7012; + + if (bFits) // ok, place shore (later we need to do random choose of the different tiles here + { + // find similar shore piece (randomness) + int count = 0; + int pieces[16]; + int k; + TILEDATA& t_orig = (*tiledata)[i]; + for (k = 0;k < *tiledata_count;k++) + { + TILEDATA& t = (*tiledata)[k]; + + if (t.bMarbleMadness) continue; + + if (t.cx != t_orig.cx || t.cy != t_orig.cy) continue; + + if (k != 4 && k != 5 && k != 12 && k != 13 && k != 20 && k != 21 && k != 28 && k != 29 + && (k < 32 || k>39)) + { + } + else continue; + + int xx, yy; + BOOL bSame = TRUE; + int p = 0; + for (xx = 0;xx < t.cx;xx++) + { + for (yy = 0;yy < t.cy;yy++) + { + if (t.tiles[p].bHackedTerrainType != t_orig.tiles[p].bHackedTerrainType) + bSame = FALSE; + p++; + if (!bSame) break; + } + if (!bSame) break; + } + + if (bSame && count < 16) + { + pieces[count] = k; + count++; + } + } + + last_succeeded_operation = 7013; + + k = ((float)rand() * count) / (float)RAND_MAX; + if (k >= count) k = count - 1; + k = pieces[k]; + + TILEDATA& t = (*tiledata)[k]; + int p = 0; + int xx, yy; + int startheight = GetHeightAt(x + y * isosize); + for (xx = 0;xx < t.cx;xx++) + { + for (yy = 0;yy < t.cy;yy++) + { + if (x + xx >= isosize || y + yy >= isosize) continue; + + int pos = x + xx + (y + yy) * isosize; + last_succeeded_operation = 7014; + + if (t.tiles[p].pic != NULL) + { + SetHeightAt(pos, startheight + t.tiles[p].bZHeight); + SetTileAt(pos, k, p); + last_succeeded_operation = 7015; + tile[pos] = i; + tsets[pos] = (*tiledata)[k].wTileSet; + terrain[pos] = (*tiledata)[k].tiles[p].bHackedTerrainType; + hasChanged[pos] = TRUE; + if ((t.cx == 3 && t.cy == 2) || (t.cx == 2 && t.cy == 3)) noChange[pos] = TRUE; + } + p++; + } + } + + + } + + } + } + } + } + + last_succeeded_operation = 7005; + + + for (i = tStart;i <= tEnd;i++) + { + /*pc.SetPos(i-tStart+(tEnd-tStart)); + pc.UpdateWindow();*/ + TILEDATA& td = (*tiledata)[i]; + + if ((*tiledata)[i].wTileSet == shoreset) + { + int pos = i - tStart; + if (pos != 4 && pos != 5 && pos != 12 && pos != 13 && pos != 20 && pos != 21 && pos != 28 && pos != 29 + && pos != 6 && pos != 7 && pos != 14 && pos != 15 && pos != 22 && pos != 23 && pos != 30 && pos != 31 && (pos < 32 || pos>39)) + + { + } + else continue; + + int x, y; + int water_count = 0; + int p = 0; + for (x = 0;x < td.cx;x++) + { + for (y = 0;y < td.cy;y++) + { + if (td.tiles[p].bHackedTerrainType == TERRAINTYPE_WATER) + water_count++; + p++; + } + } + + + // tsets now has the tileset of every single field in range (x+16, y+16) + // terrain has the terrain type of every single field + int max_x = td.cx < 16 ? td.cx : 16; + int max_y = td.cy < 16 ? td.cy : 16; + + for (x = left;x < right;x++) + { + for (y = top;y < bottom;y++) + { + int xx, yy; + + //if(!replaced[x+y*isosize] && (x=right || y>=bottom)) continue; + if (x < 1 || y < 1 || x + ymapwidth + mapheight * 2 || (y + 1 > mapwidth && x - 1 < y - mapwidth) || (x + 1 > mapwidth && y + mapwidth - 1 < x)) continue; + + + + + + /*BOOL wat_ex=FALSE; + for(xx=x;xxGetFielddataAt(xx+yy*isosize); + int ground=fd->wGround; + if(ground==0xFFFF) ground=0; + int tile_t=(*tiledata)[ground].tiles[fd->bSubTile].bHackedTerrainType; + if(tile_t==TERRAINTYPE_WATER || tile_t==0xa) + wat_ex=TRUE; + if(wat_ex) break; + } + if(wat_ex) break; + } + if(!wat_ex) continue;*/ + + + BOOL bFits = TRUE; + int p = 0; + for (xx = x;xx < x + max_x;xx++) + { + for (yy = y;yy < y + max_y;yy++) + { + if (xx >= isosize || yy >= isosize) continue; + + int tpos = i - tStart; + int xadd = 0, yadd = 0; + + /*if(tpos>=0 && tpos<=7) xadd=1; + if(tpos>=6 && tpos<=15) yadd=1; + if(tpos>=14 && tpos<=23) xadd=-1; + if(tpos>=22 && tpos<=31) yadd=-1; + if(tpos>=30 && tpos<=31) xadd=1; + + if(tpos>=32 && tpos<=33) + { + xadd=1; yadd=1; + + } + + if(tpos>=34 && tpos<=35) + { + xadd=-1; yadd=1; + + } + + if(tpos>=36 && tpos<=37) + { + xadd=-1; yadd=-1; + + } + + if(tpos>=38 && tpos<=39) + { + xadd=1; yadd=-1; + + } + + + if(xadd && yadd) + { + if(tsets[xx+xadd+yy*isosize]==waterset || tsets[xx+(yy+yadd)*isosize]==waterset) + { + bFits=FALSE; + break; + } + }*/ + + + + + int pos_water = xx + xadd + (yy + yadd) * isosize; + int pos_data = xx + yy * isosize; + + BYTE& tile_t = td.tiles[p].bHackedTerrainType; + + if (tsets[pos_data] == shoreset) + { + if (hasChanged[pos_data]) // only cancel if this routine set the shore + { + // curves are preferred + if ((max_x != 2 || max_y != 2 || water_count != 3)) + { + if (!((max_x == 3 && max_y == 2) || (max_x == 2 && max_y == 3))) + { + bFits = FALSE; + break; + } + } + + } + } + + // one step curves + if (noChange[pos_data]) + { + bFits = FALSE; + break; + } + + + if (tile[pos_data] <= tEnd && tile[pos_data] >= tEnd - 2) + bFits = FALSE; + + if (tile_t == TERRAINTYPE_WATER) + { + if (terrain[pos_water] != TERRAINTYPE_WATER) + { + bFits = FALSE; + } + } + else + { + if (terrain[pos_water] != TERRAINTYPE_GROUND) + //if(tsets[pos_water]==waterset) + { + bFits = FALSE; + } + } + + + if (!bFits) break; + p++; + } + if (!bFits) break; + } + + last_succeeded_operation = 7031; + if (bFits) // ok, place shore + { + // find similar shore piece (randomness) + int count = 0; + int pieces[16]; + int k; + TILEDATA& t_orig = (*tiledata)[i]; + for (k = 0;k < *tiledata_count;k++) + { + TILEDATA& t = (*tiledata)[k]; + if (t.cx != t_orig.cx || t.cy != t_orig.cy) continue; + + if (t.bMarbleMadness) continue; + + if (k != 4 && k != 5 && k != 12 && k != 13 && k != 20 && k != 21 && k != 28 && k != 29 + && (k < 32 || k>39)) + { + } + else continue; + + int xx, yy; + BOOL bSame = TRUE; + int p = 0; + for (xx = 0;xx < t.cx;xx++) + { + for (yy = 0;yy < t.cy;yy++) + { + if (t.tiles[p].bHackedTerrainType != t_orig.tiles[p].bHackedTerrainType) + bSame = FALSE; + p++; + if (!bSame) break; + } + if (!bSame) break; + } + + if (bSame && count < 16) + { + pieces[count] = k; + count++; + } + } + + last_succeeded_operation = 7032; + + k = ((float)rand() * count) / (float)RAND_MAX; + if (k >= count) k = count - 1; + k = pieces[k]; + + TILEDATA& t = (*tiledata)[k]; + int p = 0; + int xx, yy; + int startheight = GetHeightAt(x + y * isosize); + for (xx = 0;xx < t.cx;xx++) + { + for (yy = 0;yy < t.cy;yy++) + { + if (x + xx >= isosize || y + yy >= isosize) continue; + + int pos = x + xx + (y + yy) * isosize; + + if (t.tiles[p].pic != NULL) + { + SetHeightAt(pos, startheight + t.tiles[p].bZHeight); + SetTileAt(pos, k, p); + tile[pos] = i; + tsets[pos] = (*tiledata)[k].wTileSet; + terrain[pos] = (*tiledata)[k].tiles[p].bHackedTerrainType; + hasChanged[pos] = TRUE; + if ((t.cx == 3 && t.cy == 2) || (t.cx == 2 && t.cy == 3)) noChange[pos] = TRUE; + } + p++; + } + } + } + + } + } + } + } + + last_succeeded_operation = 7006; + + memset(hasChanged, 0, sizeof(BOOL) * isosize * isosize); + + // now make LAT (RA2 only) + +#ifdef RA2_MODE + int x, y; + for (x = left;x < right;x++) + { + for (y = top;y < bottom;y++) + { + int xx, yy; + if (x < 1 || y < 1 || x + ymapwidth + mapheight * 2 || (y + 1 > mapwidth && x - 1 < y - mapwidth) || (x + 1 > mapwidth && y + mapwidth - 1 < x)) continue; + + int pos = x + y * isosize; + + if (noChange[pos]) continue; + if (terrain[pos] == TERRAINTYPE_GROUND && tsets[pos] != shoreset && tsets[pos] != cliffset && tsets[pos] != watercliffset) + { + int i, e; + BOOL bShoreFound = FALSE; + for (i = x - 1;i <= x + 1;i++) + { + for (e = y - 1;e <= y + 1;e++) + { + if (tsets[i + e * isosize] == shoreset) bShoreFound = TRUE; + if (bShoreFound) break; + } + if (bShoreFound) break; + } + + if (bShoreFound) + { + int sandtile = atoi(tiles->sections["General"].values["GreenTile"]); + int sandlat = atoi(tiles->sections["General"].values["ClearToGreenLat"]); + + int i; + for (i = 0;i < *tiledata_count;i++) + if ((*tiledata)[i].wTileSet == sandtile) break; + Map->SetTileAt(pos, i, 0); + hasChanged[pos] = TRUE; + + } + + } + } + } + + for (x = left - 1;x < right + 1;x++) + { + for (y = top - 1;y < bottom + 1;y++) + { + int xx, yy; + if (x < 1 || y < 1 || x + ymapwidth + mapheight * 2 || (y + 1 > mapwidth && x - 1 < y - mapwidth) || (x + 1 > mapwidth && y + mapwidth - 1 < x)) continue; + + int pos = x + y * isosize; + if (noChange[pos]) continue; + + if (terrain[pos] == TERRAINTYPE_GROUND && tsets[pos] != shoreset && tsets[pos] != cliffset && tsets[pos] != watercliffset) + { + int i, e; + BOOL bShoreFound = FALSE; + BOOL bSomethingChanged = FALSE; + for (i = x - 1;i <= x + 1;i++) + { + for (e = y - 1;e <= y + 1;e++) + { + if (tsets[i + e * isosize] == shoreset) bShoreFound = TRUE; + if (hasChanged[i + e * isosize]) bSomethingChanged = TRUE; + if (bShoreFound && hasChanged[i + e * isosize]) break; + } + if (bShoreFound && hasChanged[i + e * isosize]) break; + } + + + + if (bShoreFound && hasChanged) + { + int sandtile = atoi(tiles->sections["General"].values["GreenTile"]); + int sandlat = atoi(tiles->sections["General"].values["ClearToGreenLat"]); + + + SmoothAt(pos, sandtile, sandlat, atoi(tiles->sections["General"].values["ClearTile"])); + } + + } + } + } +#endif + + + + //delete[] replaced; + delete[] hasChanged; + delete[] noChange; + delete[] tsets; + delete[] terrain; + delete[] tile; + + //pc.DestroyWindow(); + + + +} + +BOOL CMapData::IsMultiplayer() +{ + if (m_mapfile.sections["Basic"].FindName("Player") >= 0) return FALSE; + if (isTrue(m_mapfile.sections["Basic"].values["MultiplayerOnly"])) return TRUE; + if (m_mapfile.sections.find(MAPHOUSES) == m_mapfile.sections.end()) return TRUE; + + return FALSE; +} + +CString CMapData::GetTheater() +{ + return m_mapfile.sections["Map"].values["Theater"]; +} + +void CMapData::Copy(int left, int top, int right, int bottom) +{ + if (left < 0) left = 0; + if (top < 0) top = 0; + if (right > m_IsoSize) right = m_IsoSize; + if (bottom > m_IsoSize) bottom = m_IsoSize; + + if (right == 0) right = m_IsoSize; + if (bottom == 0) bottom = m_IsoSize; + + if (left >= right) return; + if (top >= bottom) return; + + + CLIPBOARD_DATA cd; + cd.dwType = 1; + cd.iWidth = right - left; + cd.iHeight = bottom - top; + cd.dwVersion = 0; + cd.dwReserved = 0; + if (editor_mode == ra2_mode) cd.bGame = 1; else cd.bGame = 0; + + HGLOBAL hGlob = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(CLIPBOARD_DATA) + cd.iWidth * cd.iHeight * sizeof(CLIPBOARD_MAPCOPY_ENTRY)); + + last_succeeded_operation = 80200; + + void* lpVoid = GlobalLock(hGlob); + + if (!lpVoid) + { + MessageBox(0, "Failed to lock memory", "Error", 0); + return; + } + + memcpy(lpVoid, &cd, sizeof(CLIPBOARD_DATA)); + + CLIPBOARD_MAPCOPY_ENTRY* data = (CLIPBOARD_MAPCOPY_ENTRY*)(((BYTE*)lpVoid) + sizeof(CLIPBOARD_DATA)); + + int i; + int e; + + int lowestheight = 255; + for (i = 0;i < cd.iWidth;i++) + { + for (e = 0;e < cd.iHeight;e++) + { + if (i + left < 0 || e + top < 0 || i + left >= m_IsoSize || e + top >= m_IsoSize) continue; + + int pos_r; + pos_r = left + i + (top + e) * m_IsoSize; + + int ground = fielddata[pos_r].wGround; + if (ground == 0xFFFF) ground = 0; + + if (fielddata[pos_r].bHeight - (*tiledata)[ground].tiles[fielddata[pos_r].bSubTile].bZHeight < lowestheight) lowestheight = fielddata[pos_r].bHeight - (*tiledata)[ground].tiles[fielddata[pos_r].bSubTile].bZHeight; + } + } + + last_succeeded_operation = 80201; + + for (i = 0;i < cd.iWidth;i++) + { + for (e = 0;e < cd.iHeight;e++) + { + if (i + left < 0 || e + top < 0 || i + left >= m_IsoSize || e + top >= m_IsoSize) continue; + + int pos_w, pos_r; + pos_w = i + e * cd.iWidth; + pos_r = left + i + (top + e) * m_IsoSize; + + data[pos_w].bHeight = fielddata[pos_r].bHeight - lowestheight; + data[pos_w].bMapData = fielddata[pos_r].bMapData; + data[pos_w].bSubTile = fielddata[pos_r].bSubTile; + data[pos_w].bMapData2 = fielddata[pos_r].bMapData2; + data[pos_w].wGround = fielddata[pos_r].wGround; + data[pos_w].overlay = fielddata[pos_r].overlay; + data[pos_w].overlaydata = fielddata[pos_r].overlaydata; + data[pos_w].bRedrawTerrain = fielddata[pos_r].bRedrawTerrain; + + int ground = fielddata[pos_r].wGround; + if (ground == 0xFFFF) ground = 0; + int tset = (*tiledata)[ground].wTileSet; + + int k; + for (k = 0;k < *tiledata_count;k++) + { + if ((*tiledata)[k].wTileSet == tset) break; + } + + data[pos_w].wTileSet = tset; + data[pos_w].bTile = ground - k; + } + } + + last_succeeded_operation = 80202; + + while (GlobalUnlock(hGlob)); + + OpenClipboard(theApp.m_pMainWnd->m_hWnd); + EmptyClipboard(); + + if (!SetClipboardData(theApp.m_cf, hGlob)) + { + MessageBox(0, "Failed to set clipboard data", "Error", 0); + + } + + CloseClipboard(); + +} + +void CMapData::Paste(int x, int y, int z_mod) +{ + OpenClipboard(theApp.m_pMainWnd->m_hWnd); + HANDLE handle = GetClipboardData(theApp.m_cf); + + void* lpVoid = GlobalLock(handle); + + if (!lpVoid) + { + CloseClipboard(); + return; + } + + last_succeeded_operation = 3001; + + CLIPBOARD_DATA cd; + memcpy(&cd, lpVoid, sizeof(CLIPBOARD_DATA)); + + + x -= cd.iWidth / 2; + y -= cd.iHeight / 2; + + CLIPBOARD_MAPCOPY_ENTRY* data = (CLIPBOARD_MAPCOPY_ENTRY*)(((BYTE*)lpVoid) + sizeof(CLIPBOARD_DATA)); + + last_succeeded_operation = 3002; + + int lowestheight = 255; + int mapwidth, mapheight; + mapwidth = GetWidth(); + mapheight = GetHeight(); + + int i; + int e; + for (i = 0;i < cd.iWidth;i++) + { + for (e = 0;e < cd.iHeight;e++) + { + if (x + i < 0 || y + e < 0 || x + i >= m_IsoSize || y + e >= m_IsoSize) continue; + + FIELDDATA* fd = Map->GetFielddataAt(i + x + (y + e) * m_IsoSize); + int ground = fd->wGround; + if (ground = 0xFFFF) ground = 0; + + + int height = fd->bHeight;//-(*tiledata)[ground].tiles[fd->bSubTile].bZHeight; + + if (height < lowestheight) lowestheight = height; + + + } + } + + int ground = GetFielddataAt(x + y * m_IsoSize)->wGround; + if (ground == 0xFFFF) ground = 0; + int startheight = lowestheight + z_mod;//-(*tiledata)[ground].tiles[GetFielddataAt(x+y*m_IsoSize)->bSubTile].bZHeight; + + //char c[50]; + //itoa(startheight, c, 10); + //MessageBox(0,c,"",0); + + last_succeeded_operation = 3003; + + const bool mp = IsMultiplayer(); + for (i = 0;i < cd.iWidth;i++) + { + for (e = 0;e < cd.iHeight;e++) + { + int pos_w, pos_r; + pos_r = i + e * cd.iWidth; + pos_w = x + i + (y + e) * m_IsoSize; + + if (x + i < 0 || y + e < 0 || x + i >= m_IsoSize || y + e >= m_IsoSize) continue; + + RemoveOvrlMoney(fielddata[pos_w].overlay, fielddata[pos_w].overlaydata); + + fielddata[pos_w].overlay = data[pos_r].overlay; + fielddata[pos_w].overlaydata = data[pos_r].overlaydata; + + AddOvrlMoney(fielddata[pos_w].overlay, fielddata[pos_w].overlaydata); + + SetHeightAt(pos_w, startheight + data[pos_r].bHeight); + + int tset = data[pos_r].wTileSet; + int tile = data[pos_r].bTile; + int k; + int found = -1; + for (k = 0;k < *tiledata_count;k++) + { + if ((*tiledata)[k].wTileSet == tset) + { + found = k; + break; + } + } + + if (found < 0) continue; + if ((*tiledata)[found + tile].wTileSet != tset) + { + continue; + } + if ((*tiledata)[found + tile].wTileCount <= data[pos_r].bSubTile) continue; + + + fielddata[pos_w].bSubTile = data[pos_r].bSubTile; + fielddata[pos_w].bRedrawTerrain = data[pos_r].bRedrawTerrain; + fielddata[pos_w].wGround = found + tile; + + + + fielddata[pos_w].bMapData = data[pos_r].bMapData; + fielddata[pos_w].bMapData2 = data[pos_r].bMapData2; + + Mini_UpdatePos(x + i, y + e, mp); + } + } + + last_succeeded_operation = 3005; + GlobalUnlock(handle); + + CloseClipboard(); +} + +void CMapData::GetStructurePaint(int index, STRUCTUREPAINT* lpStructurePaint) const +{ + if (index < 0 || index >= m_structurepaint.size()) return; + + *lpStructurePaint = m_structurepaint[index]; +} + +void CMapData::InitMinimap() +{ + + int pwidth = GetWidth() * 2; + int pheight = GetHeight(); + + memset(&m_mini_biinfo, 0, sizeof(BITMAPINFO)); + m_mini_biinfo.bmiHeader.biBitCount = 24; + m_mini_biinfo.bmiHeader.biWidth = pwidth; + m_mini_biinfo.bmiHeader.biHeight = pheight; + m_mini_biinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + m_mini_biinfo.bmiHeader.biClrUsed = 0; + m_mini_biinfo.bmiHeader.biPlanes = 1; + m_mini_biinfo.bmiHeader.biCompression = BI_RGB; + m_mini_biinfo.bmiHeader.biClrImportant = 0; + + int pitch = pwidth * 3; + if (pitch == 0) return; + + if (pitch % sizeof(DWORD)) + { + pitch += sizeof(DWORD) - (pwidth * 3) % sizeof(DWORD); + } + + m_mini_pitch = pitch; + + //m_mini_colors=new(BYTE[pitch*pheight]); + m_mini_colors.resize(pitch * pheight); + + + memset(m_mini_colors.data(), 255, pitch * (pheight)); + + + /*DWORD dwIsoSize=GetIsoSize(); + + int mapwidth=GetWidth(); + int mapheight=GetHeight(); + int i,e; + + int size=pitch*pheight; + + for(i=0;i= RIPARIUS_BEGIN && ovrl <= RIPARIUS_END) + { + money += (ovrld + 1) * (atoi(rules.sections["Riparius"].values["Value"])); + } + + if (ovrl >= CRUENTUS_BEGIN && ovrl <= CRUENTUS_END) + { + money += (ovrld + 1) * (atoi(rules.sections["Cruentus"].values["Value"])); + } + + if (ovrl >= VINIFERA_BEGIN && ovrl <= VINIFERA_END) + { + money += (ovrld + 1) * (atoi(rules.sections["Vinifera"].values["Value"])); + } + + if (ovrl >= ABOREUS_BEGIN && ovrl <= ABOREUS_END) + { + money += (ovrld + 1) * (atoi(rules.sections["Aboreus"].values["Value"])); + } + } + + return money; +} + +int CMapData::GetMoneyOnMap() const +{ + return m_money; +} + +int CMapData::GetPowerOfHouse(LPCTSTR lpHouse) +{ + // stub + return 0; +} + +void CMapData::SmoothTiberium(DWORD dwPos) +{ + static int _adj[9] = { 0,1,3,4,6,7,8,10,11 }; + + BYTE& ovrl = fielddata[dwPos].overlay; + + if (!(ovrl >= RIPARIUS_BEGIN && ovrl <= RIPARIUS_END) && + !(ovrl >= CRUENTUS_BEGIN && ovrl <= CRUENTUS_END) && + !(ovrl >= VINIFERA_BEGIN && ovrl <= VINIFERA_END) && + !(ovrl >= ABOREUS_BEGIN && ovrl <= ABOREUS_END)) + return; + + RemoveOvrlMoney(ovrl, fielddata[dwPos].overlaydata); + + int i, e; + int x, y; + x = dwPos % m_IsoSize; + y = dwPos / m_IsoSize; + int count = 0; + + for (i = -1;i < 2;i++) + { + for (e = -1;e < 2;e++) + { + int xx = x + i; + int yy = y + e; + + if (xx < 0 || xx >= m_IsoSize || yy < 0 || yy >= m_IsoSize) continue; + + FIELDDATA& fd = fielddata[xx + yy * m_IsoSize]; + + BYTE& ovrl = fd.overlay; + BYTE& ovrld = fd.overlaydata; + + + if (ovrl >= RIPARIUS_BEGIN && ovrl <= RIPARIUS_END) + { + count++; + } + + if (ovrl >= CRUENTUS_BEGIN && ovrl <= CRUENTUS_END) + { + count++; + } + + if (ovrl >= VINIFERA_BEGIN && ovrl <= VINIFERA_END) + { + count++; + } + + if (ovrl >= ABOREUS_BEGIN && ovrl <= ABOREUS_END) + { + count++; + } + + } + } + + ASSERT(count); + + fielddata[dwPos].overlaydata = _adj[count - 1]; + m_OverlayData[y + x * 512] = _adj[count - 1]; + + AddOvrlMoney(ovrl, fielddata[dwPos].overlaydata); + +} + +void CMapData::ResizeMap(int iLeft, int iTop, DWORD dwNewWidth, DWORD dwNewHeight) +{ +#ifndef RA2_MODE + if (MessageBox(0, "Tunnels may be damaged after changing the map size. Continue?", "Warning", MB_YESNO) == IDNO) return; +#endif + + // MW: New object replacing code to fix crashes + INFANTRY* inf = new(INFANTRY[GetInfantryCount()]); + int inf_count = GetInfantryCount(); + STRUCTURE* str = new(STRUCTURE[GetStructureCount()]); + int str_count = GetStructureCount(); + UNIT* unit = new(UNIT[GetUnitCount()]); + int unit_count = GetUnitCount(); + AIRCRAFT* air = new(AIRCRAFT[GetAircraftCount()]); + int air_count = GetAircraftCount(); + TERRAIN* terrain = new(TERRAIN[GetTerrainCount()]); + int terrain_count = GetTerrainCount(); + CString* wp_id = new(CString[GetWaypointCount()]); + int wp_count = GetWaypointCount(); + DWORD* wp_pos = new(DWORD[GetWaypointCount()]); + CString* ct_tag = new(CString[GetCelltagCount()]); + int ct_count = GetCelltagCount(); + DWORD* ct_pos = new(DWORD[GetCelltagCount()]); + + int i; + + // Now copy the objects into above arrays and delete them from map + for (i = 0;i < inf_count;i++) + { + INFANTRY obj; + GetInfantryData(i, &obj); + inf[i] = obj; + } + for (i = inf_count - 1;i >= 0;i--) + DeleteInfantry(i); + + for (i = 0;i < air_count;i++) + { + AIRCRAFT obj; + GetAircraftData(i, &obj); + + air[i] = obj; + } + for (i = air_count - 1;i >= 0;i--) + DeleteAircraft(i); + + for (i = 0;i < str_count;i++) + { + STRUCTURE obj; + GetStructureData(i, &obj); + + str[i] = obj; + } + for (i = str_count - 1;i >= 0;i--) + DeleteStructure(i); + + for (i = 0;i < unit_count;i++) + { + UNIT obj; + GetUnitData(i, &obj); + + unit[i] = obj; + } + for (i = unit_count - 1;i >= 0;i--) + DeleteUnit(i); + + for (i = 0;i < terrain_count;i++) + { + terrain[i] = m_terrain[i]; + } + for (i = 0;i < terrain_count;i++) + DeleteTerrain(i); + + + for (i = 0;i < wp_count;i++) + { + DWORD pos; + CString id; + + GetWaypointData(i, &id, &pos); + + wp_id[i] = id; + wp_pos[i] = pos; + } + + // for(i=0;i= m_IsoSize || y >= m_IsoSize) continue; + + FIELDDATA& fdd = fielddata[x + y * m_IsoSize]; + FIELDDATA& fdo = old_fd[i + e * os]; + + fdd.bCliffHack = fdo.bCliffHack; + fdd.bHeight = fdo.bHeight; + fdd.bHide = fdo.bHide; + fdd.bMapData = fdo.bMapData; + fdd.bMapData2 = fdo.bMapData2; + fdd.bRedrawTerrain = fdo.bRedrawTerrain; + fdd.bRNDImage = fdo.bRNDImage; + fdd.bSubTile = fdo.bSubTile; + fdd.overlay = fdo.overlay; + fdd.overlaydata = fdo.overlaydata; + fdd.wGround = fdo.wGround; + } + } + + // MW 07/22/01: Added Progress dialog - it just was slow, and did not crash... + int allcount = GetInfantryCount() + GetAircraftCount() + GetUnitCount() + GetStructureCount() + GetTerrainCount() + GetWaypointCount() + GetCelltagCount(); + int curcount = 0; + CProgressDlg* dlg = new(CProgressDlg)("Updating objects, please wait"); + dlg->SetRange(0, allcount - 1); + dlg->ShowWindow(SW_SHOW); + + //m_noAutoObjectUpdate=TRUE; // deactivate Update*()... faster + + int count = inf_count; // this temp variable is *needed* (infinite loop)!!! + for (i = 0;i < count;i++) + { + if (inf[i].deleted) + { + dlg->SetPosition(i + curcount); + dlg->UpdateWindow(); + + continue; // MW June 12 01 + } + + INFANTRY obj; + obj = inf[i]; + + char c[50]; + obj.x = itoa(atoi(obj.x) + x_move, c, 10); + obj.y = itoa(atoi(obj.y) + y_move, c, 10); + + int x = atoi(obj.x); + int y = atoi(obj.y); + + + if (x < 0 || y < 0 || x >= m_IsoSize || y >= m_IsoSize) continue; + + AddInfantry(&obj); + + dlg->SetPosition(i + curcount); + dlg->UpdateWindow(); + + } + + curcount += count; + + count = air_count; + for (i = 0;i < count;i++) + { + // if(air[i].deleted) continue; + + AIRCRAFT obj; + obj = air[i]; + + char c[50]; + obj.x = itoa(atoi(obj.x) + x_move, c, 10); + obj.y = itoa(atoi(obj.y) + y_move, c, 10); + + int x = atoi(obj.x); + int y = atoi(obj.y); + + + if (x < 0 || y < 0 || x >= m_IsoSize || y >= m_IsoSize) continue; + + AddAircraft(&obj); + + dlg->SetPosition(i + curcount); + dlg->UpdateWindow(); + } + + UpdateAircraft(FALSE); + + curcount += count; + + count = str_count; + for (i = 0;i < count;i++) + { + // if(str[i].deleted) continue; + + STRUCTURE obj; + obj = str[i]; + + char c[50]; + obj.x = itoa(atoi(obj.x) + x_move, c, 10); + obj.y = itoa(atoi(obj.y) + y_move, c, 10); + + int x = atoi(obj.x); + int y = atoi(obj.y); + + + if (x < 0 || y < 0 || x >= m_IsoSize || y >= m_IsoSize) continue; + + AddStructure(&obj); + + dlg->SetPosition(i + curcount); + dlg->UpdateWindow(); + } + + UpdateStructures(FALSE); + + curcount += count; + + count = unit_count; + for (i = 0;i < count;i++) + { + // if(units[i].deleted) continue; + + UNIT obj; + obj = unit[i]; + + char c[50]; + obj.x = itoa(atoi(obj.x) + x_move, c, 10); + obj.y = itoa(atoi(obj.y) + y_move, c, 10); + + int x = atoi(obj.x); + int y = atoi(obj.y); + + + if (x < 0 || y < 0 || x >= m_IsoSize || y >= m_IsoSize) continue; + + AddUnit(&obj); + + dlg->SetPosition(i + curcount); + dlg->UpdateWindow(); + } + + UpdateUnits(FALSE); + + curcount += count; + + count = terrain_count; + for (i = 0;i < count;i++) + { + if (terrain[i].deleted) + { + dlg->SetPosition(i + curcount); + dlg->UpdateWindow(); + continue; // MW June 12 01 + } + + CString obj; + int x = terrain[i].x; + int y = terrain[i].y; + obj = terrain[i].type; + + + char c[50]; + x = x + x_move; + y = y + y_move; + + + if (x < 0 || y < 0 || x >= m_IsoSize || y >= m_IsoSize) continue; + + AddTerrain(obj, x + y * m_IsoSize); + + dlg->SetPosition(i + curcount); + dlg->UpdateWindow(); + } + + //UpdateTerrain(TRUE); + //UpdateTerrain(FALSE); + + curcount += count; + + count = wp_count; + for (i = 0;i < count;i++) + { + DWORD pos; + CString id; + + pos = wp_pos[i]; + id = wp_id[i]; + + int x = pos % os + x_move; + int y = pos / os + y_move; + + if (x < 0 || y < 0 || x >= m_IsoSize || y >= m_IsoSize) continue; + + AddWaypoint(id, x + y * m_IsoSize); + + dlg->SetPosition(i + curcount); + dlg->UpdateWindow(); + } + + UpdateWaypoints(FALSE); + + curcount += count; + + + for (i = 0;i < ct_count;i++) + { + DWORD pos = ct_pos[i]; + CString tag = ct_tag[i]; + + int x = pos % os + x_move; + int y = pos / os + y_move; + + if (x < 0 || y < 0 || x >= m_IsoSize || y >= m_IsoSize) continue; + + AddCelltag(tag, x + y * m_IsoSize); + + dlg->SetPosition(i + curcount); + dlg->UpdateWindow(); + } + + UpdateCelltags(FALSE); + + m_noAutoObjectUpdate = FALSE; + + errstream << "Delete old_fd" << endl; + errstream.flush(); + + dlg->DestroyWindow(); + dlg = new(CProgressDlg)("Updating Minimap, please wait"); + count = 0; + dlg->SetRange(0, m_IsoSize * m_IsoSize); + dlg->ShowWindow(SW_SHOW); + + if (old_fd) delete[] old_fd; + + errstream << "Init minimap" << endl; + errstream.flush(); + + InitMinimap(); + + errstream << "Fill minimap" << endl; + errstream.flush(); + + const bool mp = IsMultiplayer(); + for (i = 0;i < m_IsoSize;i++) + { + for (e = 0;e < m_IsoSize;e++) + { + Mini_UpdatePos(i, e, mp); + + count++; + + } + dlg->SetPosition(count); + dlg->UpdateWindow(); + } + + errstream << "Finished" << endl; + errstream.flush(); + + if (inf) delete[] inf; + if (str) delete[] str; + if (unit) delete[] unit; + if (air) delete[] air; + if (terrain) delete[] terrain; + if (wp_id) delete[] wp_id; + if (wp_pos) delete[] wp_pos; + if (ct_tag) delete[] ct_tag; + if (ct_pos) delete[] ct_pos; + + dlg->DestroyWindow(); + + +} + +/* +Returns TRUE for all sections that should not be modified using the INI editor, +because they become modified whenever the map is saved by the editor itself. +*/ +BOOL CMapData::IsMapSection(LPCSTR lpSectionName) +{ + CString str; + str = lpSectionName; + + if (str == "IsoMapPack5" || str == "OverlayPack" || str == "OverlayDataPack" || + str == "Preview" || str == "PreviewPack" || str == "Map" || + str == "Structures" || str == "Terrain" || str == "Units" || str == "Aircraft" || str == "Infantry" + || str == "Variables") + return TRUE; + + return FALSE; +} + +int GetEventParamStart(CString& EventData, int param); + +BOOL CMapData::IsYRMap() +{ +#ifdef TS_MODE + return FALSE; +#else + + //if(yuri_mode) // always check for this + { + if (Map->GetTheater() == THEATER3 || Map->GetTheater() == THEATER4 || Map->GetTheater() == THEATER5) + return TRUE; + + int i; + int max = 0; + if (tiledata == &u_tiledata) + { + max = atoi(g_data.sections["RA2TileMax"].values["Urban"]); + } + else if (tiledata == &s_tiledata) max = atoi(g_data.sections["RA2TileMax"].values["Snow"]); + else if (tiledata == &t_tiledata) max = atoi(g_data.sections["RA2TileMax"].values["Temperat"]); + + int yroverlay = atoi(g_data.sections["YROverlay"].values["Begin"]); + + for (i = 0;i < fielddata_size;i++) + { + if (fielddata[i].wGround != 0xFFFF && fielddata[i].wGround >= max) + { + return TRUE; + } + if (fielddata[i].overlay >= yroverlay && fielddata[i].overlay != 0xFF) + return TRUE; + } + + int count; + + count = GetInfantryCount(); + for (i = 0;i < count;i++) + { + INFANTRY inf; + GetInfantryData(i, &inf); + + if (inf.deleted) continue; + + CIniFileSection& sec = g_data.sections["YRInfantry"]; + + if (sec.values.find(inf.type) != sec.values.end()) + { + return TRUE; + } + } + + count = GetStructureCount(); + for (i = 0;i < count;i++) + { + STRUCTURE str; + GetStructureData(i, &str); + + if (str.deleted) continue; + + CIniFileSection& sec = g_data.sections["YRBuildings"]; + + if (sec.values.find(str.type) != sec.values.end()) + { + return TRUE; + } + } + + count = GetUnitCount(); + for (i = 0;i < count;i++) + { + UNIT unit; + GetUnitData(i, &unit); + + if (unit.deleted) continue; + + CIniFileSection& sec = g_data.sections["YRUnits"]; + + if (sec.values.find(unit.type) != sec.values.end()) + { + return TRUE; + } + } + + count = GetAircraftCount(); + for (i = 0;i < count;i++) + { + AIRCRAFT air; + GetAircraftData(i, &air); + + if (air.deleted) continue; + + CIniFileSection& sec = g_data.sections["YRAircraft"]; + + if (sec.values.find(air.type) != sec.values.end()) + { + return TRUE; + } + } + + count = GetTerrainCount(); + for (i = 0;i < count;i++) + { + TERRAIN& tr = m_terrain[i]; + + + if (tr.deleted) continue; + + CIniFileSection& sec = g_data.sections["YRTerrain"]; + + if (sec.values.find(tr.type) != sec.values.end()) + { + return TRUE; + } + } + + count = m_mapfile.sections["Triggers"].values.size(); + for (i = 0;i < count;i++) + { + CString event; + CString action; + CString id; + + id = *m_mapfile.sections["Triggers"].GetValueName(i); + + event = m_mapfile.sections["Events"].values[id]; + action = m_mapfile.sections["Actions"].values[id]; + + int eventcount, actioncount; + eventcount = atoi(GetParam(event, 0)); + actioncount = atoi(GetParam(action, 0)); + + int e; + + for (e = 0;e < eventcount;e++) + { + CString type = GetParam(event, GetEventParamStart(event, e)); + if (g_data.sections["EventsRA2"].values.find(type) != g_data.sections["EventsRA2"].values.end()) + { + if (isTrue(GetParam(g_data.sections["EventsRA2"].values[type], 9))) + return TRUE; + } + } + + for (e = 0;e < actioncount;e++) + { + CString type = GetParam(action, 1 + e * 8); + if (g_data.sections["ActionsRA2"].values.find(type) != g_data.sections["ActionsRA2"].values.end()) + { + if (isTrue(GetParam(g_data.sections["ActionsRA2"].values[type], 14))) + return TRUE; + } + } + } + } + + return FALSE; +#endif +} + +#ifdef SMUDGE_SUPP +BOOL CMapData::AddSmudge(SMUDGE* lpSmudge) +{ + + + SMUDGE td; + td = *lpSmudge; + int pos = td.x + td.y * GetIsoSize(); + + if (smudgeid.find(td.type) == smudgeid.end()) return FALSE; + + BOOL bFound = FALSE; + + int i; + for (i = 0;i < m_smudges.size();i++) + { + if (m_smudges[i].deleted) // yep, found one, replace it + { + m_smudges[i] = td; + if (pos < fielddata_size) + { + fielddata[pos].smudge = i; + fielddata[pos].smudgetype = smudgeid[td.type]; + } + + bFound = TRUE; + break; + } + } + + if (!bFound) + { + m_smudges.push_back(td); + + if (pos < fielddata_size) + { + fielddata[pos].smudge = m_smudges.size() - 1; + fielddata[pos].smudgetype = smudgeid[td.type]; + } + } + + + return TRUE; +} + +void CMapData::DeleteSmudge(DWORD dwIndex) +{ + if (m_smudges[dwIndex].deleted) return; + + int x, y; + + x = m_smudges[dwIndex].x; + y = m_smudges[dwIndex].y; + m_smudges[dwIndex].deleted = 1; + + int pos = x + y * GetIsoSize(); + if (x + y * m_IsoSize < fielddata_size) + { + fielddata[pos].smudge = -1; + fielddata[pos].smudgetype = -1; + } +} + +void CMapData::UpdateSmudges(BOOL bSave, int num) +{ + vector& t = m_smudges; + + if (bSave == FALSE) + { + if (m_mapfile.sections.find("Smudge") == m_mapfile.sections.end() || m_mapfile.sections["Smudge"].values.size() <= 0) + return; + + if (num < 0) + { + t.clear(); + t.reserve(100); + + int i; + for (i = 0;i < GetIsoSize() * GetIsoSize();i++) + { + fielddata[i].smudge = -1; + } + + + + CIniFileSection& sec = m_mapfile.sections["Smudge"]; + + for (i = 0;i < sec.values.size();i++) + { + int x, y; + x = atoi(GetParam(*sec.GetValue(i), 2)); + y = atoi(GetParam(*sec.GetValue(i), 1)); + + // check for valid coordinates ; MW May 17th 2001 + ASSERT(x >= 0 && x < GetIsoSize()); + ASSERT(y >= 0 && y < GetIsoSize()); + if (x < 0 || x >= GetIsoSize() || y < 0 || y >= GetIsoSize()) + { + // invalid coordinates - ignore in release + } + else + { + SMUDGE td; + td.deleted = 0; + td.type = GetParam(*sec.GetValue(i), 0); + td.x = x; + td.y = y; + + t.push_back(td); + + int pos = x + y * GetIsoSize(); + fielddata[pos].smudge = i; + fielddata[pos].smudgetype = smudgeid[td.type]; + } + } + + m_mapfile.sections.erase("Smudge"); + + } + + } + else + { + + //if(num<0) + { + //if(m_mapfile.sections.find("Smudge")!=m_mapfile.sections.end()) MessageBox(0,"Reupdate!","",0); + m_mapfile.sections.erase("Smudge"); + int i; + + for (i = 0;i < t.size();i++) + { + SMUDGE& td = t[i]; + if (!td.deleted) + { + char c[50]; + CString val = td.type; + val += ","; + itoa(td.y, c, 10); + val += c; + val += ","; + itoa(td.x, c, 10); + val += c; + val += ",0"; + + itoa(i, c, 10); + + m_mapfile.sections["Smudge"].values[c] = val; + } + } + } + + } + +} + +void CMapData::UpdateSmudgeInfo(LPCSTR lpSmudgeType) +{ + CIniFile& ini = GetIniFile(); + + if (!lpSmudgeType) + { + memset(smudgeinfo, 0, 0x0F00 * sizeof(SMUDGE_INFO)); + + int i; + for (i = 0;i < rules.sections["SmudgeTypes"].values.size();i++) + { + + + CString type = *rules.sections["SmudgeTypes"].GetValue(i); + CString artname = type; + + + int n = GetUnitTypeID(type); + + if (n >= 0 && n < 0x0F00) + { + + CString lpPicFile = GetUnitPictureFilename(type, 0); + + if (pics.find(lpPicFile) != pics.end()) + { + + smudgeinfo[n].pic = pics[lpPicFile]; + } + else + smudgeinfo[n].pic.pic = NULL; + } + + } + + for (i = 0;i < ini.sections["SmudgeTypes"].values.size();i++) + { + + + CString type = *ini.sections["SmudgeTypes"].GetValue(i); + CString artname = type; + + + + int n = Map->GetUnitTypeID(type); + + if (n >= 0 && n < 0x0F00) + { + //smudgeinfo[n].w=w; + //smudgeinfo[n].h=h; + + CString lpPicFile = GetUnitPictureFilename(type, 0); + + if (pics.find(lpPicFile) != pics.end()) + { + smudgeinfo[n].pic = pics[lpPicFile]; + } + else + smudgeinfo[n].pic.pic = NULL; + } + + } + } + else + { + CString type = lpSmudgeType; + CString artname = type; + + + + int n = Map->GetUnitTypeID(type); + + if (n >= 0 && n < 0x0F00) + { + + CString lpPicFile = GetUnitPictureFilename(type, 0); + if (pics.find(lpPicFile) != pics.end()) + { + + smudgeinfo[n].pic = pics[lpPicFile]; + } + else + smudgeinfo[n].pic.pic = NULL; + } + + } + + +} + +void CMapData::GetSmudgeData(DWORD dwIndex, SMUDGE* lpData) const +{ + ASSERT(m_smudges.size() > dwIndex); + + + *lpData = m_smudges[dwIndex];//*m_mapfile.sections["Terrain"].GetValue(dwIndex); +} +#endif + + + + +BOOL CMapData::GetInfantryINIData(int index, CString* lpINI) +{ + ASSERT(index < m_infantry.size()); + + if (index >= m_infantry.size() || index < 0) return FALSE; + + INFANTRY& infantry = m_infantry[index]; + CString value; + value = infantry.house + "," + infantry.type + "," + infantry.strength + "," + infantry.y + + "," + infantry.x + "," + infantry.pos + "," + infantry.action + "," + infantry.direction + "," + + infantry.tag + "," + infantry.flag1 + "," + infantry.flag2 + "," + infantry.flag3 + "," + + infantry.flag4 + "," + infantry.flag5; + + *lpINI = value; + + return TRUE; + +} + +void CMapData::RedrawMinimap() +{ + const bool mp = IsMultiplayer(); + int i, e; + for (i = 0; i < m_IsoSize; i++) + for (e = 0; e < m_IsoSize; e++) + Mini_UpdatePos(i, e, mp); +} diff --git a/MissionEditor/MapData.h b/MissionEditor/MapData.h new file mode 100644 index 0000000..2ae8f86 --- /dev/null +++ b/MissionEditor/MapData.h @@ -0,0 +1,1306 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Map->h: Interface for the class CMap. +// +// CMap holds all information for the current map +// +////////////////////////////////////////////////////////////////////// + +#include "structs.h" +#include +#include "variables.h" +#include "macros.h" +#include "ovrlinline.h" +#include "Tube.h" + + +extern TILEDATA** tiledata; +extern DWORD* tiledata_count; +extern ofstream errstream; +extern map tilesets_start; +extern CIniFile* tiles; +extern CFinalSunApp theApp; +extern int shoreset; + +extern CIniFile rules; + +extern TILEDATA* un_tiledata; +extern CIniFile g_data; + +extern int ramp2set; +extern int pave2set; +extern int ramp2set_start; +extern int pave2set_start; +extern int rampset_start; +extern int rampset; + + + +#if !defined(AFX_MAP_H__9278CAC0_D4E7_11D3_B63B_444553540001__INCLUDED_) +#define AFX_MAP_H__9278CAC0_D4E7_11D3_B63B_444553540001__INCLUDED_ + +#include "IniFile.h" // HinzugefĂ¼gt von der Klassenansicht +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +#include + +#define MAPDATA_UPDATE_FROM_INI 0 +#define MAPDATA_UPDATE_TO_INI 1 +#define MAPDATA_UPDATE_TO_INI_ALL 2 +#define MAPDATA_UPDATE_TO_INI_ALL_PREVIEW 4 +#define MAPDATA_UPDATE_TO_INI_ALL_COMPRESSED 8 + +struct NODEDATA +{ + NODEDATA(); + int type; + int index; + CString house; +}; + +// mapfielddata is the data of every field in an extracted isomappack! +struct MAPFIELDDATA +{ + unsigned short wX; + unsigned short wY; + WORD wGround; + BYTE bData[3]; + BYTE bHeight; + BYTE bData2[1]; +}; +#define MAPFIELDDATA_SIZE 11 + +/* +struct TILEDATA{}; + +contains the information needed for one field of the map. +*/ +struct FIELDDATA +{ + FIELDDATA(); + short unit; // unit number + short infantry[SUBPOS_COUNT]; // infantry number + short aircraft; // aircraft number + short structure; // structure number + short structuretype; // structure type id + short terrain; // terrain number + int terraintype; // terrain type id +#ifdef SMUDGE_SUPP + short smudge; + int smudgetype; +#endif + short waypoint; // waypoint number + + NODEDATA node; // node info + BYTE overlay; // overlay number + BYTE overlaydata; // overlay data info + WORD wGround; // ground type (tile) + WORD bMapData; // add. data + BYTE bSubTile; + BYTE bHeight; // height of tile + BYTE bMapData2; // add. data2 + short celltag; // celltag uses + + //std::uint16_t wTubeId; // tube ID + //char cTubePart; // 0 is start, 1 is exit, and 2-101 are tube parts + unsigned bReserved : 1; // for program usage + unsigned bHide : 1; + unsigned bRedrawTerrain : 1; // force redraw + unsigned bCliffHack : 1; + unsigned bRNDImage : 4; // for using a,b,c of tmp tiles +}; + +struct SNAPSHOTDATA +{ + SNAPSHOTDATA(); + int left; + int top; + int bottom; + int right; + + BOOL* bRedrawTerrain; + BYTE* overlay; + BYTE* overlaydata; + WORD* wGround; + WORD* bMapData; + BYTE* bSubTile; + BYTE* bHeight; + BYTE* bMapData2; + BYTE* bRNDData; + //CIniFile mapfile; +}; + + + +class CMapData +{ +public: + + BOOL m_noAutoObjectUpdate; + + void SetFielddataAt(DWORD dwPos, FIELDDATA* lpFd) + { + if (dwPos >= fielddata_size) return; + + RemoveOvrlMoney(fielddata[dwPos].overlay, fielddata[dwPos].overlaydata); + fielddata[dwPos] = (*lpFd); + AddOvrlMoney(fielddata[dwPos].overlay, fielddata[dwPos].overlaydata); + }; + + DWORD GetMapPos(int mapX, int mapY) const + { + return mapX + mapY * m_IsoSize; + } + DWORD GetMapPos(const MapCoords& coords) const + { + return coords.x + coords.y * m_IsoSize; + } + + bool hasLat(WORD wTileSet) const; + + void HideField(DWORD dwPos, BOOL bHide); + void SetReserved(DWORD dwPos, BYTE val); + DWORD GetTileID(DWORD dwTileSet, int iTile); + int GetNecessarySlope(DWORD dwPos); + void CreateSlopesAt(DWORD dwPos) + { + //OutputDebugString("CreateSlopes()\n"); + + FIELDDATA m = *GetFielddataAt(dwPos); + if (m.wGround == 0xFFFF) m.wGround = 0; + + TILEDATA& d = (*tiledata)[m.wGround]; + + int ns = -1; + int i, e, p = 0; + int h[3][3]; + for (i = 0;i < 3; i++) + { + for (e = 0;e < 3;e++) + { + int pos = dwPos + (i - 1) + (e - 1) * m_IsoSize; + if (pos < 0 || pos >= m_IsoSize * m_IsoSize) + { + h[i][e] = 0; + } + else + { + FIELDDATA m2 = *GetFielddataAt(pos); + + h[i][e] = m.bHeight - m2.bHeight; + } + + + } + } + + // check if the current tile must be heightened anyway + if (!theApp.m_Options.bDisableSlopeCorrection && d.bMorphable) + { + if ((h[0][1] < 0 && h[2][1] < 0) || (h[1][0] < 0 && h[1][2] < 0) + + || (h[1][0] < 0 && h[0][2] < 0 && h[0][1] >= 0) + || (h[1][0] < 0 && h[2][2] < 0 && h[2][1] >= 0) + + || (h[0][1] < 0 && h[2][0] < 0 && h[1][0] >= 0) + || (h[0][1] < 0 && h[2][2] < 0 && h[1][2] >= 0) + + || (h[1][2] < 0 && h[0][0] < 0 && h[0][1] >= 0) + || (h[1][2] < 0 && h[2][0] < 0 && h[2][1] >= 0) + + || (h[2][1] < 0 && h[0][0] < 0 && h[1][0] >= 0) + || (h[2][1] < 0 && h[0][2] < 0 && h[1][2] >= 0) + + || (h[1][0] < 0 && h[0][1] < 0 && h[0][0] >= 0) + || (h[0][1] < 0 && h[1][2] < 0 && h[0][2] >= 0) + || (h[1][2] < 0 && h[2][1] < 0 && h[2][2] >= 0) + || (h[2][1] < 0 && h[1][0] < 0 && h[2][0] >= 0) + + ) + { + SetHeightAt(dwPos, m.bHeight + 1); + for (i = -1;i < 2;i++) + for (e = -1;e < 2;e++) + CreateSlopesAt(dwPos + i + e * m_IsoSize); + + return; + } + } + + + + BOOL checkOtherSlopes = FALSE; + + + if (h[0][0] == -1 && h[2][2] == -1 && h[2][0] >= 0 && h[0][2] >= 0 && h[1][0] >= 0 && h[1][2] >= 0 && h[0][1] >= 0 && h[2][1] >= 0) ns = SLOPE_UP_LEFTTOP_AND_RIGHTBOTTOM; + if (h[0][2] == -1 && h[2][0] == -1 && h[0][0] >= 0 && h[2][2] >= 0 && h[0][1] >= 0 && h[1][0] >= 0 && h[1][2] >= 0 && h[2][1] >= 0) ns = SLOPE_UP_LEFTBOTTOM_AND_RIGHTTOP; + + + + + if (ns == -1) + if (h[1][0] == -1 && h[0][1] != -1 && h[1][2] != -1 && h[2][1] != -1) + { + ns = SLOPE_UP_LEFT; + } + else if (h[0][1] == -1 && h[1][0] != -1 && h[2][1] != -1 && h[1][2] != -1) + { + ns = SLOPE_UP_TOP; + } + else if (h[1][2] == -1 && h[0][1] != -1 && h[1][0] != -1 && h[2][1] != -1) + { + ns = SLOPE_UP_RIGHT; + } + else if (h[2][1] == -1 && h[0][1] != -1 && h[1][0] != -1 && h[1][2] != -1) + { + ns = SLOPE_UP_BOTTOM; + } + + if (ns == -1) + { + if (h[0][0] == -2) ns = SLOPE_DOWN_BOTTOM; + if (h[2][0] == -2) ns = SLOPE_DOWN_RIGHT; + if (h[0][2] == -2) ns = SLOPE_DOWN_LEFT; + if (h[2][2] == -2) ns = SLOPE_DOWN_TOP; + } + + if (ns == -1 && h[0][0] == -1) + { + if (h[1][0] == -1 && h[0][1] == -1) ns = SLOPE_DOWN_RIGHTBOTTOM; + else if (h[1][0] == 0 && h[0][1] == 0) ns = SLOPE_UP_LEFTTOP; + //else if(h[2][2]==1) ns=SLOPE_DOWN_BOTTOM; + } + + if (ns == -1 && h[2][0] == -1) + { + if (h[1][0] == -1 && h[2][1] == -1) ns = SLOPE_DOWN_RIGHTTOP; + else if (h[1][0] == 0 && h[2][1] == 0) ns = SLOPE_UP_LEFTBOTTOM; + //else if(h[0][2]==1) ns=SLOPE_DOWN_RIGHT; + } + if (ns == -1 && h[0][2] == -1) + { + if (h[1][2] == -1 && h[0][1] == -1) ns = SLOPE_DOWN_LEFTBOTTOM; + else if (h[1][2] == 0 && h[0][1] == 0) ns = SLOPE_UP_RIGHTTOP; + //else if(h[2][0]==1) ns=SLOPE_DOWN_LEFT; + } + if (ns == -1 && h[2][2] == -1) + { + if (h[1][2] == -1 && h[2][1] == -1) ns = SLOPE_DOWN_LEFTTOP; + else if (h[1][2] == 0 && h[2][1] == 0) ns = SLOPE_UP_RIGHTBOTTOM; + //else if(h[0][0]==1) ns=SLOPE_DOWN_TOP; + } + + if (ns == -1 && h[1][0] == -1 && h[2][1] == -1) ns = SLOPE_DOWN_RIGHTTOP; + if (ns == -1 && h[1][2] == -1 && h[2][1] == -1) ns = SLOPE_DOWN_LEFTTOP; + if (ns == -1 && h[1][0] == -1 && h[0][1] == -1) ns = SLOPE_DOWN_RIGHTBOTTOM; + if (ns == -1 && h[1][2] == -1 && h[0][1] == -1) ns = SLOPE_DOWN_LEFTBOTTOM; + + + int rampbase = rampset_start;//atoi((*tiles).sections["General"].values["RampBase"]); + int rampsmooth = atoi((*tiles).sections["General"].AccessValueByName("RampSmooth")); + + if (ns == -1 && (d.wTileSet == rampset || d.wTileSet == rampsmooth) && d.bMorphable) + { + SetTileAt(dwPos, 0, 0); + } + if (tiledata == &un_tiledata) + { + int r = ramp2set; + int m = pave2set; + + if (ns == -1 && (d.wTileSet == r || d.wTileSet == m) && d.bMorphable) + { + SetTileAt(dwPos, pave2set_start/*GetTileID(m,0)*/, 0); + } + } + if (d.bMorphable && ns != -1) + { + if (tiledata == &un_tiledata) // NEW URBAN FIX FOR URBAN PAVEMENT + { + + //[NewUrbanInfo] + //Morphable2=114 + //Ramps2=117 + int r = ramp2set; + int m = pave2set; + if (d.wTileSet == r || d.wTileSet == m) + rampbase = ramp2set_start; + + + } + + SetTileAt(dwPos, rampbase + ns - 1, 0); + + } + + + } + void CreateMap(DWORD dwWidth, DWORD dwHeight, LPCTSTR lpTerrainType, DWORD dwGroundHeight); + BOOL SetTileAt(DWORD dwPos, DWORD dwID, DWORD dwTile) + { + if (dwPos > fielddata_size) return FALSE; + + int replacement = 0; // MW fix: ignore for bridges + if ((*tiledata)[dwID].bReplacementCount && atoi((*tiles).sections["General"].AccessValueByName("BridgeSet")) != (*tiledata)[dwID].wTileSet) + { + replacement = rand() * (1 + (*tiledata)[dwID].bReplacementCount) / RAND_MAX; + } + + fielddata[dwPos].wGround = dwID; + fielddata[dwPos].bSubTile = dwTile; + fielddata[dwPos].bRNDImage = replacement; + + int e; + fielddata[dwPos].bRedrawTerrain = FALSE; + int xx, yy; + for (xx = -2;xx < 0;xx++) + { + for (yy = -2;yy < 0;yy++) + { + int npos = dwPos + xx + yy * m_IsoSize; + if (npos > 0 && fielddata[dwPos].bHeight - fielddata[npos].bHeight >= 4) + { + fielddata[dwPos].bRedrawTerrain = TRUE; + break; + } + } + if (fielddata[dwPos].bRedrawTerrain) break; + } + + Mini_UpdatePos(dwPos % m_IsoSize, dwPos / m_IsoSize, IsMultiplayer()); + + return TRUE; + } + + void SetHeightAt(DWORD dwPos, BYTE bHeight) + { + int height = (char)bHeight; + if (height > MAXHEIGHT) height = MAXHEIGHT; // too high else + if (height < 0) height = 0; + if (dwPos < fielddata_size) fielddata[dwPos].bHeight = height; + } + + + int GetBuildingID(LPCSTR lpBuildingName); + void ImportRUL(LPCTSTR lpFilename); + void ExportRulesChanges(const char* filename); + void DeleteRulesSections(); + DWORD GetWaypointCount() const; + DWORD GetCelltagCount() const; + WCHAR* GetUnitName(LPCTSTR lpID) const; + DWORD GetTerrainCount() const; + DWORD GetAircraftCount() const; + DWORD GetStructureCount() const; + DWORD GetUnitCount() const; + DWORD GetInfantryCount() const; + void GetStdUnitData(DWORD dwIndex, STDOBJECTDATA* lpStdUnit) const; + void GetStdAircraftData(DWORD dwIndex, STDOBJECTDATA* lpStdAircraft) const; + void GetWaypointData(DWORD dwIndex, CString* lpID, DWORD* lpdwPos) const; + BOOL IsGroundObjectAt(DWORD dwPos) const; + BOOL AddTerrain(LPCTSTR lpType, DWORD dwPos, int suggestedIndex = -1); + void GetTerrainData(DWORD dwIndex, CString* lpType) const; + void GetTerrainData(DWORD dwIndex, TERRAIN* lpTerrain) const; + BOOL AddUnit(UNIT* lpUnit, LPCTSTR lpType = NULL, LPCTSTR lpHouse = NULL, DWORD dwPos = 0, CString suggestedID = ""); + BOOL AddAircraft(AIRCRAFT* lpAircraft, LPCTSTR lpType = NULL, LPCTSTR lpHouse = NULL, DWORD dwPos = 0, CString suggestedID = ""); + void GetCelltagData(DWORD dwIndex, CString* lpTag, DWORD* lpdwPos) const; + BOOL AddCelltag(LPCTSTR lpTag, DWORD dwPos); + void GetAircraftData(DWORD dwIndex, AIRCRAFT* lpAircraft) const; + void GetUnitData(DWORD dwIndex, UNIT* lpUnit) const; + void GetInfantryData(DWORD dwIndex, INFANTRY* lpInfantry) const; + void GetStdInfantryData(DWORD dwIndex, STDOBJECTDATA* lpStdInfantry) const; + INT GetUnitTypeID(LPCTSTR lpType); + void InitializeUnitTypes(); + BOOL AddStructure(STRUCTURE* lpStructure, LPCTSTR lpType = NULL, LPCTSTR lpHouse = NULL, DWORD dwPos = 0, CString suggestedID = ""); + BOOL AddInfantry(INFANTRY* lpInfantry, LPCTSTR lpType = NULL, LPCTSTR lpHouse = NULL, DWORD dwPos = 0, int suggestedIndex = -1); + BOOL AddNode(NODE* lpNode, WORD dwPos); + void GetStdStructureData(DWORD dwIndex, STDOBJECTDATA* lpStdStructure) const; + void GetStructureData(DWORD dwIndex, STRUCTURE* lpStructure) const; + BOOL AddWaypoint(CString lpID, DWORD dwPos); + + void DeleteNode(LPCTSTR lpHouse, DWORD dwIndex); + void DeleteTerrain(DWORD dwIndex); + void DeleteAircraft(DWORD dwIndex); + void DeleteStructure(DWORD dwIndex); + void DeleteUnit(DWORD dwIndex); + void DeleteCelltag(DWORD dwIndex); + void DeleteWaypoint(DWORD dwIndex); + void DeleteInfantry(DWORD dwIndex); + + INT GetCelltagAt(DWORD dwPos) const + { + return fielddata[dwPos].celltag; + } + INT GetCelltagAt(MapCoords pos) const + { + return GetCelltagAt(GetMapPos(pos)); + } + INT GetWaypointAt(DWORD dwPos) const + { + return fielddata[dwPos].waypoint; + } + INT GetWaypointAt(MapCoords pos) const + { + return GetWaypointAt(GetMapPos(pos)); + } + INT GetTerrainAt(DWORD dwPos) const + { + return fielddata[dwPos].terrain; + } + INT GetTerrainAt(MapCoords pos) const + { + return GetTerrainAt(GetMapPos(pos)); + } + INT GetAirAt(DWORD dwPos) const + { + return fielddata[dwPos].aircraft; + } + INT GetAirAt(MapCoords pos) const + { + return GetAirAt(GetMapPos(pos)); + } + INT GetStructureAt(DWORD dwPos) const + { + if (fielddata[dwPos].structure > -1) return fielddata[dwPos].structure; return -1; + } + INT GetStructureAt(MapCoords pos) const + { + return GetStructureAt(GetMapPos(pos)); + } + INT GetUnitAt(DWORD dwPos) const + { + return fielddata[dwPos].unit; + } + INT GetUnitAt(MapCoords pos) const + { + return GetUnitAt(GetMapPos(pos)); + } + INT GetInfantryAt(DWORD dwPos, DWORD dwSubPos = 0xFFFFFFFF) const + { + if (dwSubPos == 0xFFFFFFFF) + { + int i; + for (i = 0;i < SUBPOS_COUNT;i++) + if (fielddata[dwPos].infantry[i] != -1) + return fielddata[dwPos].infantry[i]; + return -1; + } + return fielddata[dwPos].infantry[dwSubPos]; + } + INT GetInfantryAt(MapCoords pos, DWORD dwSubPos = 0xFFFFFFFF) + { + return GetInfantryAt(GetMapPos(pos), dwSubPos); + } + INT GetNodeAt(DWORD dwPos, CString& lpHouse) const; + INT GetNodeAt(MapCoords pos, CString& lpHouse) const + { + return GetNodeAt(GetMapPos(pos), lpHouse); + } + INT GetHeightAt(DWORD dwPos) const + { + return fielddata[dwPos].bHeight; + } + INT GetHeightAt(const MapCoords& coords) const + { + return GetHeightAt(GetMapPos(coords)); + } + + const FIELDDATA* GetFielddataAt(DWORD dwPos) const + { + if (dwPos >= fielddata_size) + { + outside_f.bReserved = 1; + return &outside_f; + } + + return &fielddata[dwPos]; + }; + + FIELDDATA* GetFielddataAt(DWORD dwPos) + { + if (dwPos >= fielddata_size) + { + outside_f.bReserved = 1; + return &outside_f; + } + + return &fielddata[dwPos]; + }; + + const FIELDDATA* GetFielddataAt(const MapCoords& pos) const + { + auto dwPos = GetMapPos(pos); + if (dwPos >= fielddata_size) + { + outside_f.bReserved = 1; + return &outside_f; + } + + return &fielddata[dwPos]; + }; + + FIELDDATA* GetFielddataAt(const MapCoords& pos) + { + auto dwPos = GetMapPos(pos); + if (dwPos >= fielddata_size) + { + outside_f.bReserved = 1; + return &outside_f; + } + + return &fielddata[dwPos]; + }; + + BYTE GetOverlayDataAt(DWORD dwPos); + void SetOverlayDataAt(DWORD dwPos, BYTE bValue); + BYTE GetOverlayAt(DWORD dwPos); + void SetOverlayAt(DWORD dwPos, BYTE bValue); + void ClearOverlay(); + void ClearOverlayData(); + + const std::vector>& GetTubes() const + { + return m_tubes; + } + + DWORD GetIsoSize() const + { + return m_IsoSize; + } + void LoadMap(const std::string& file); + void UpdateIniFile(DWORD dwFlags = MAPDATA_UPDATE_TO_INI); + CIniFile& GetIniFile(); + CString GetAITriggerTypeID(DWORD dwAITriggerType); + DWORD GetAITriggerTypeIndex(LPCTSTR lpID); + WORD GetHouseIndex(LPCTSTR lpHouse); + void GetAITriggerType(DWORD dwAITriggerType, AITRIGGERTYPE* pAITrg); + DWORD GetAITriggerTypeCount(); + CString GetHouseID(WORD wHouse, BOOL bCountry = FALSE); + WORD GetHousesCount(BOOL bCountries = FALSE); + WORD GetHeight() const + { + return m_maprect.bottom; + }; + WORD GetWidth() const + { + return m_maprect.right; + }; + BOOL IsRulesSection(LPCTSTR lpSection); + + CMapData(); + virtual ~CMapData(); + void Pack(BOOL bCreatePreview = FALSE, BOOL bCompression = FALSE); + void Unpack(); + void UpdateTreeInfo(LPCSTR lpTreeType = NULL); + void UpdateBuildingInfo(LPCSTR lpUnitType = NULL); + void CalcMapRect(); + + // MW change: UpdateStructures() public, so that houses dialog can access it + void UpdateStructures(BOOL bSave = FALSE); + + MapCoords ToMapCoords(ProjectedCoords xy) const; + MapCoords ToMapCoords3d(ProjectedCoords xy, int mapZ) const; + MapCoords ToMapCoords3d(ProjectedCoords xy, bool bAllowAccessBehindCliffs=false, bool ignoreHideFlagsAndOutside=false) const; + ProjectedCoords ProjectCoords(MapCoords xy) const; + ProjectedCoords ProjectCoords3d(MapCoords xy) const; + ProjectedCoords ProjectCoords3d(MapCoords xy, int z) const; + bool isInside(MapCoords xy) const; + + __forceinline CPoint GetMiniMapPos(MapCoords mapCoords) + { + int x, y; + GetMiniMapPos(mapCoords.x, mapCoords.y, x, y); + return CPoint(static_cast(x), static_cast(y)); + } + +private: + void UpdateTubes(BOOL bSave); + MAPFIELDDATA* GetMappackPointer(DWORD dwPos); + + void UpdateMapFieldData(BOOL bSave = FALSE); + + DWORD m_IsoSize; + mutable FIELDDATA outside_f; + BOOL isInitialized; + void UpdateCelltags(BOOL bSave = FALSE); + void UpdateOverlay(BOOL bSave = FALSE); + void UpdateNodes(BOOL bSave = FALSE); + void UpdateWaypoints(BOOL bSave = FALSE); + void UpdateUnits(BOOL bSave = FALSE); + void UpdateTerrain(BOOL bSave = FALSE, int num = -1); + void UpdateInfantry(BOOL bSave = FALSE); + void UpdateAircraft(BOOL bSave = FALSE); + + + + + + map buildingid; + map terrainid; +#ifdef SMUDGE_SUPP + map smudgeid; +#endif + BYTE m_Overlay[262144]; // overlay byte values (extracted) + BYTE m_OverlayData[262144]; // overlay data byte values (extracted) + BYTE* m_mfd; // map field data buffer + DWORD dwIsoMapSize; + CIniFile m_mapfile; + RECT m_maprect; + RECT m_vismaprect; + FIELDDATA* fielddata; + int fielddata_size; + SNAPSHOTDATA* m_snapshots; + DWORD dwSnapShotCount; + int m_cursnapshot; + int m_money; + + vector m_structurepaint; + + +protected: + + void InitMinimap(); + vector> m_tubes; + + // vectors for terrain, infantry, structures and units, as those need to be displayed very fast. + // we don´t need them for aircraft right now, as there won´t be many aircrafts on the map anyway. +#ifdef SMUDGE_SUPP + vector m_smudges; +#endif + vector m_terrain; + vector m_infantry; + vector m_units; + vector m_structures; + + // we use a dib to draw the minimap + std::vector m_mini_colors; + BITMAPINFO m_mini_biinfo; + int m_mini_pitch; + + enum OverlayCreditsType + { + OverlayCredits_Riparius = 0, + OverlayCredits_Cruentus = 1, + OverlayCredits_Vinifera = 2, + OverlayCredits_Aboreus = 3, + OverlayCredits_NumOf + }; + + std::array m_overlayCredits; + + + __forceinline void RemoveOvrlMoney(unsigned char ovrl, unsigned char ovrld) + { + if (ovrl >= RIPARIUS_BEGIN && ovrl <= RIPARIUS_END) + { + m_money -= (ovrld + 1) * m_overlayCredits[OverlayCredits_Riparius]; + } + + if (ovrl >= CRUENTUS_BEGIN && ovrl <= CRUENTUS_END) + { + m_money -= (ovrld + 1) * m_overlayCredits[OverlayCredits_Cruentus]; + } + + if (ovrl >= VINIFERA_BEGIN && ovrl <= VINIFERA_END) + { + m_money -= (ovrld + 1) * m_overlayCredits[OverlayCredits_Vinifera]; + } + + if (ovrl >= ABOREUS_BEGIN && ovrl <= ABOREUS_END) + { + m_money -= (ovrld + 1) * m_overlayCredits[OverlayCredits_Aboreus]; + } + } + + __forceinline void AddOvrlMoney(unsigned char ovrl, unsigned char ovrld) + { + if (ovrl >= RIPARIUS_BEGIN && ovrl <= RIPARIUS_END) + { + m_money += (ovrld + 1) * m_overlayCredits[OverlayCredits_Riparius]; + } + + if (ovrl >= CRUENTUS_BEGIN && ovrl <= CRUENTUS_END) + { + m_money += (ovrld + 1) * m_overlayCredits[OverlayCredits_Cruentus]; + } + + if (ovrl >= VINIFERA_BEGIN && ovrl <= VINIFERA_END) + { + m_money += (ovrld + 1) * m_overlayCredits[OverlayCredits_Vinifera]; + } + + if (ovrl >= ABOREUS_BEGIN && ovrl <= ABOREUS_END) + { + m_money += (ovrld + 1) * m_overlayCredits[OverlayCredits_Aboreus]; + } + } + + __forceinline void GetMiniMapPos(int i, int e, int& x, int& y) + { + const int pheight = m_mini_biinfo.bmiHeader.biHeight; + + const DWORD dwIsoSize = m_IsoSize; + y = e / 2 + i / 2; + x = dwIsoSize - i + e; + + int tx, ty; + tx = GetWidth(); + ty = GetHeight(); + + ty = ty / 2 + tx / 2; + tx = dwIsoSize - GetWidth() + GetHeight(); + + x -= tx; + y -= ty; + + x += pheight; + y += pheight / 2; + } + + + __forceinline void Mini_UpdatePos(const int i, const int e, bool isMultiplayer) + { + const int pwidth = m_mini_biinfo.bmiHeader.biWidth; + const int pheight = m_mini_biinfo.bmiHeader.biHeight; + + if (m_mini_colors.empty() || !tiledata) + return; + + + const DWORD dwIsoSize = m_IsoSize; + const int pitch = m_mini_pitch; + + int x = 0; + int y = 0; + GetMiniMapPos(i, e, x, y); + y = pheight - y - 1; + + int xiso = i; + int yiso = e; + + if (xiso >= m_IsoSize) + xiso = m_IsoSize - 1; + if (yiso >= m_IsoSize) + yiso = m_IsoSize - 1; + if (xiso < 0) + xiso = 0; + if (yiso < 0) + yiso = 0; + + DWORD dwPos = xiso + yiso * dwIsoSize; + + int dwDrawPos = (x * 3 + y * pitch); + + int size = pitch * pheight; + + if (dwDrawPos >= size || x >= pwidth || y >= pheight || x < 0 || y < 0) return; + if (dwPos >= m_IsoSize * m_IsoSize) return; + if (dwDrawPos + 3 >= m_mini_colors.size()) return; + + RGBTRIPLE& col = (RGBTRIPLE&)m_mini_colors[dwDrawPos]; + RGBTRIPLE& col_r = (RGBTRIPLE&)m_mini_colors[(dwDrawPos + sizeof(RGBTRIPLE)) < size ? dwDrawPos + sizeof(RGBTRIPLE) : dwDrawPos]; + + + FIELDDATA td; + td = *GetFielddataAt(dwPos); + + + + STDOBJECTDATA sod; + sod.house = ""; + int ic; + for (ic = 0;ic < SUBPOS_COUNT;ic++) + { + if (td.infantry[ic] >= 0) + { + GetStdInfantryData(td.infantry[ic], &sod); + } + } + if (td.structure >= 0) + { + GetStdStructureData(td.structure, &sod); + } + if (td.aircraft >= 0) + { + GetStdAircraftData(td.aircraft, &sod); + } + if (td.unit >= 0) + { + GetStdUnitData(td.unit, &sod); + } + + + int ground = (td.wGround >= (*tiledata_count)) ? 0 : td.wGround; + int subt = td.bSubTile; + int ttype = 0; + if (subt < (*tiledata)[ground].wTileCount) ttype = (*tiledata)[ground].tiles[subt].bTerrainType; + + + // mw added check: + if (subt >= (*tiledata)[ground].wTileCount) return; + + RGBTRIPLE& l = (*tiledata)[ground].tiles[subt].rgbLeft; + RGBTRIPLE& r = (*tiledata)[ground].tiles[subt].rgbRight; + + int pos = GetHeightAt(dwPos); + + col.rgbtBlue = l.rgbtBlue; + col.rgbtGreen = l.rgbtGreen; + col.rgbtRed = l.rgbtRed; + col_r.rgbtBlue = r.rgbtBlue; + col_r.rgbtGreen = r.rgbtGreen; + col_r.rgbtRed = r.rgbtRed; + + if (isGreenTiberium(td.overlay)) + { +#ifndef RA2_MODE + col.rgbtBlue = 0; + col.rgbtGreen = 200; + col.rgbtRed = 0; + col_r = col; +#else + col.rgbtBlue = 0; + col.rgbtGreen = 250; + col.rgbtRed = 250; + col_r = col; +#endif + } + else if (td.overlay == OVRL_VEINS) + { + col.rgbtBlue = 120; + col.rgbtGreen = 180; + col.rgbtRed = 190; + col_r = col; + } + else if (td.overlay == OVRL_VEINHOLE || td.overlay == OVRL_VEINHOLEBORDER) + { + col.rgbtBlue = 120; + col.rgbtGreen = 160; + col.rgbtRed = 165; + col_r = col; + } + else if (td.overlay != 0xFF) + { + col.rgbtBlue = 20; + col.rgbtGreen = 20; + col.rgbtRed = 20; + col_r = col; + } + + + if (sod.house.GetLength() > 0) + { + /* + if(strstr(sod.house, houses[1].name)) + { + col.rgbtRed=255; + col.rgbtGreen=0; + col.rgbtBlue=0; + } + else if(strstr(sod.house,houses[0].name)) + { + col.rgbtRed=180; + col.rgbtGreen=180; + col.rgbtBlue=0; + } + else + { + col.rgbtRed=200; + col.rgbtGreen=200; + col.rgbtBlue=200; + }*/ + COLORREF c = ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->GetColor(sod.house); + + col.rgbtRed = GetRValue(c); + col.rgbtBlue = GetBValue(c); + col.rgbtGreen = GetGValue(c); + col_r = col; + } + + // MW: ADD: make red start pos dots + if (isMultiplayer) + { + CString id; + DWORD p; + int wp = td.waypoint; + BOOL startpos = FALSE; + int i, e; + for (i = -1;i < 2;i++) + { + for (e = -1;e < 2;e++) + { + if (dwPos + i + e * m_IsoSize < fielddata_size) + { + int w = GetWaypointAt(dwPos + i + e * m_IsoSize); + if (w >= 0) + { + GetWaypointData(w, &id, &p); + if (atoi(id) < 8) + { + startpos = TRUE; + break; + } + } + + + } + } + if (startpos) break; + } + if (startpos) + { + col.rgbtBlue = 0; + col.rgbtGreen = 0; + col.rgbtRed = 255; + col_r = col; + + } + } + } + + + // helper function. Is val==iSet1 or val=iSet2? + __forceinline BOOL st(int val, int iSet) + { + + if (val == iSet) return TRUE; + return FALSE; + } + + +public: + void RedrawMinimap(); + BOOL GetInfantryINIData(int index, CString* lpINI); + + +#ifdef SMUDGE_SUPP + void UpdateSmudges(BOOL bSave = FALSE, int num = -1); + void DeleteSmudge(DWORD dwIndex); + BOOL AddSmudge(SMUDGE* lpSmudge); + void GetSmudgeData(DWORD dwIndex, SMUDGE* lpData) const; + void UpdateSmudgeInfo(LPCSTR lpSmudgeType = NULL); +#endif + + BOOL IsYRMap(); + BOOL IsMapSection(LPCSTR lpSectionName); + void ResizeMap(int iLeft, int iTop, DWORD dwNewWidth, DWORD dwNewHeight); + void SmoothTiberium(DWORD dwPos); + int GetPowerOfHouse(LPCTSTR lpHouse); + int GetMoneyOnMap() const; + int CalcMoneyOnMap(); + void GetMinimap(BYTE** lpData, BITMAPINFO* lpBI, int* pitch); + void GetStructurePaint(int index, STRUCTUREPAINT* lpStructurePaint) const; + void Paste(int x, int y, int z_mod); + void Copy(int left = 0, int top = 0, int right = 0, int bottom = 0); + CString GetTheater(); + BOOL IsMultiplayer(); + void CreateShore(int left, int top, int right, int bottom, BOOL bRemoveUseless = TRUE); + void Redo(); + void SmoothAllAt(DWORD dwPos); + + __forceinline void SmoothAt(DWORD dwPos, int iSmoothSet, int iLatSet, int iTargetSet, BOOL bIgnoreShore = TRUE) + { + int i; + int its, iss, ils; + int iLatGround = tilesets_start[iLatSet]; + int iSmoothGround = tilesets_start[iSmoothSet]; + its = (*tiledata)[tilesets_start[iTargetSet]].tiles[0].bTerrainType; + iss = (*tiledata)[iSmoothGround].tiles[0].bTerrainType; + ils = (*tiledata)[iLatGround].tiles[0].bTerrainType; + + + + FIELDDATA m = *GetFielddataAt(dwPos); + if (m.wGround == 0xFFFF) m.wGround = 0; + + // do we have that certain LAT tile here? + if ((*tiledata)[m.wGround].wTileSet != iSmoothSet && (*tiledata)[m.wGround].wTileSet != iLatSet) return; + + //if(m.wGround==iLatGround) m.wGround=iSmoothGround; + + if (its == iss && (*tiledata)[m.wGround].wTileSet == iSmoothSet) m.wGround = iLatGround; + + if (its == iss) ils += 1; + + BOOL bOnlyLat = TRUE; + //BOOL bNoLat=TRUE; + int ns = -1; + int e, p = 0; + int ts[3][3]; // terrain info + + int set = (*tiledata)[m.wGround].wTileSet; + + for (i = 0;i < 3; i++) + { + for (e = 0;e < 3;e++) + { + int pos = dwPos + (i - 1) + (e - 1) * m_IsoSize; + if (pos < 0 || pos >= fielddata_size) + { + ts[i][e] = 0; + } + else + { + FIELDDATA m2 = *GetFielddataAt(pos); + if (m2.wGround == 0xFFFF) m2.wGround = 0; + + int cur_set = (*tiledata)[m2.wGround].wTileSet; + + //if(cur_set==iSmoothSet) bNoLat=FALSE; + // + + if (its == iss && cur_set == iSmoothSet) + { + m2.wGround = iLatGround; cur_set = iLatSet; + } + + if (cur_set == iSmoothSet || cur_set == iTargetSet) bOnlyLat = FALSE; + + /*if(cur_set != iSmoothSet && cur_set!= iLatSet && cur_set!=iTargetSet) + { + ts[i][e]=(*tiledata)[m2.wGround].tiles[m2.bSubTile].bTerrainType; + if((*tiledata)[m2.wGround].wTileSet!=shoreset) + { + ts[i][e]=0;//ts[i][e]+1; // make sure you don´t smooth at it except it´s shore + } + //if(bIgnoreShore && (*tiledata)[m2.wGround].wTileSet==shoreset) + // ts[i][e]=0;//ts[i][e]+1; + } + else*/ if (its == iss && cur_set != set) + { + if (cur_set == shoreset && !bIgnoreShore) + ts[i][e] = its; + else if (cur_set != iSmoothSet && cur_set != iTargetSet && cur_set != iLatSet) + ts[i][e] = 0; + else + ts[i][e] = its; + } + else if (its == iss && cur_set == set) + ts[i][e] = ils; + else + { + ts[i][e] = (*tiledata)[m2.wGround].tiles[m2.bSubTile].bTerrainType; + + if (cur_set != shoreset && cur_set != iLatSet && cur_set != iSmoothSet) + { + ts[i][e] = 0;//ts[i][e]+1; // make sure you don´t smooth at it except it´s shore + } + + } + } + } + } + + //if(bOnlyLat) return; + + + int needed = -1; + + // 1/1 is smoothed tile + + if (ts[1][1] == ils) + { + // single lat + if (ts[0][1] != ils && ts[1][0] != ils + && ts[1][2] != ils && ts[2][1] != ils) + needed = 16; + else if (ts[0][1] == ils && ts[1][0] == ils + && ts[1][2] == ils && ts[2][1] == ils) + needed = 0; + else if (ts[0][1] == ils && ts[2][1] == ils && + ts[1][0] != ils && ts[1][2] != ils) + needed = 11; + else if (ts[1][0] == ils && ts[1][2] == ils && + ts[0][1] != ils && ts[2][1] != ils) + needed = 6; + else if (ts[1][0] != ils && ts[0][1] == ils && + ts[2][1] == ils) + needed = 9; + else if (ts[2][1] != ils && ts[1][0] == ils && + ts[1][2] == ils) + needed = 5; + else if (ts[1][2] != ils && ts[0][1] == ils && + ts[2][1] == ils) + needed = 3; + else if (ts[0][1] != ils && ts[1][0] == ils && + ts[1][2] == ils) + needed = 2; + else if (ts[0][1] == ils && ts[1][0] != ils && + ts[1][2] != ils && ts[2][1] != ils) + needed = 15; + else if (ts[1][2] == ils && ts[1][0] != ils && + ts[0][1] != ils && ts[2][1] != ils) + needed = 14; + else if (ts[2][1] == ils && ts[1][0] != ils && + ts[0][1] != ils && ts[1][2] != ils) + needed = 12; + else if (ts[1][0] == ils && ts[0][1] != ils && + ts[1][2] != ils && ts[2][1] != ils) + needed = 8; + else if (ts[1][0] != ils && ts[2][1] != ils) + needed = 13; + else if (ts[1][0] != ils && ts[0][1] != ils) + needed = 10; + else if (ts[2][1] != ils && ts[1][2] != ils) + needed = 7; + else if (ts[0][1] != ils && ts[1][2] != ils) + needed = 4; + + + } + else if (ts[1][1] == its) + { + // replace target set instead of smooth set + //if(st(ts[0][0], && ts[0][1] + } + + + needed -= 1; + if (needed >= 0) + { + /*for(i=0;i<*tiledata_count;i++) + { + if((*tiledata)[i].wTileSet==iLatSet) + { + break; + } + }*/ + i = tilesets_start[iLatSet]; + + // i is first lat tile + int e; + for (e = 0;e < needed;e++) + { + i += (*tiledata)[i].wTileCount; + } + + SetTileAt(dwPos, i, 0); + } + else if (needed == -1) + { + /*for(i=0;i<*tiledata_count;i++) + { + if((*tiledata)[i].wTileSet==iSmoothSet) + { + break; + } + }*/ + i = tilesets_start[iSmoothSet]; + + // i is first lat tile + SetTileAt(dwPos, i, 0); + } + } + + BOOL GetLocalSize(RECT* rect) const; + void Undo(); + void TakeSnapshot(BOOL bEraseFollowing = TRUE, int left = 0, int top = 0, int right = 0, int bottom = 0); + BOOL CheckMapPackData(); + int GetInfantryCountAt(DWORD dwPos); + void DeleteTube(std::uint16_t wID); + // void SetTube(WORD wID, CTube *lpTI); + void SetTube(CTube* lpTI); + CTube* GetTube(std::uint16_t wID); +}; + +inline bool CMapData::isInside(MapCoords xy) const +{ + return xy.x >= 0 && xy.y >= 0 && xy.x < m_IsoSize && xy.y < m_IsoSize; +} + +inline MapCoords CMapData::ToMapCoords(ProjectedCoords xy) const +{ + return ToMapCoords3d(xy, 0); +} + +inline MapCoords CMapData::ToMapCoords3d(ProjectedCoords xy, int mapZ) const +{ + float cx = xy.x, cy = xy.y + mapZ * f_y / 2; + return MapCoords( + cy / (float)f_y - cx / (float)f_x + (float)(m_IsoSize - 2) / 2 + (float)0.5, + cy / (float)f_y + cx / (float)f_x - (float)(m_IsoSize - 2) / 2.0f - (float)0.5 + ); +} + +inline MapCoords CMapData::ToMapCoords3d(const ProjectedCoords xy, bool bAllowAccessBehindCliffs, bool ignoreHideFlagsAndOutside) const +{ + auto xy2d = ToMapCoords(xy); + static const auto fxy = ProjectedVec(f_x, f_y).convertT(); + auto ret = ignoreHideFlagsAndOutside ? xy2d : MapCoords(-1, -1); + + for (int i = 15; i >= 0; i--) + { + for (int e = 0; e < 3; e++) + { + const MapVec off(i, i); // this is a vertical line starting from the bottom + const MapVec off2(e == 1 ? -1 : 0, e == 2 ? -1 : 0); // increase x or y or neither in map coordinates by one so that we have a broader area to check + const MapCoords cur = xy2d + off + off2; + + if (isInside(cur)) + { + const auto& mfd = *GetFielddataAt(GetMapPos(cur)); + const int ground = mfd.wGround == 0xFFFF ? 0 : mfd.wGround; + if (ignoreHideFlagsAndOutside || (!mfd.bHide && !(tiledata && (*tiledata)[ground].bHide))) + { + const auto curProj = ProjectCoords3d(cur); + + // now projCoords hold the logical pixel coordinates for the current field... + // we now need to check if cx and cy are in this field + //if(*x >= m && *x<= m+f_x && *y>=n && *y<=n+f_y) + { + auto df1 = (xy - curProj).convertT(); + auto dfScaled = df1 / fxy; + auto d = Vec2(dfScaled.y - dfScaled.x + 0.5f, dfScaled.y + dfScaled.x - 0.5f); + if (d.x >= 0.0f && d.y >= 0.0f && d.x <= 1.0f && d.y <= 1.0f)// || (!bAllowAccessBehindCliffs && xy.y >= curProj.y))) + //if (d == MapCoords(0, 0)) + { + if (bAllowAccessBehindCliffs) + ret = cur; + else + return cur; + } + } + } + } + } + } + return ret; +} + +inline ProjectedCoords CMapData::ProjectCoords(MapCoords xy) const +{ + return ProjectCoords3d(xy, 0); +} + +inline ProjectedCoords CMapData::ProjectCoords3d(MapCoords xy, int z) const +{ + return ProjectedCoords( + (m_IsoSize - 2 - xy.x + xy.y) * f_x / 2, + (xy.y + xy.x - z) * f_y / 2 + ); +} + +inline ProjectedCoords CMapData::ProjectCoords3d(MapCoords xy) const +{ + return ProjectCoords3d(xy, isInside(xy) ? GetHeightAt(xy) : 0); +} + +#endif // !defined(AFX_MAP_H__9278CAC0_D4E7_11D3_B63B_444553540001__INCLUDED_) diff --git a/MissionEditor/MapLoadingDlg.cpp b/MissionEditor/MapLoadingDlg.cpp new file mode 100644 index 0000000..dad0c42 --- /dev/null +++ b/MissionEditor/MapLoadingDlg.cpp @@ -0,0 +1,65 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// MapLoadingDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "MapLoadingDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CMapLoadingDlg + + +CMapLoadingDlg::CMapLoadingDlg(CWnd* pParent /*=NULL*/) + : CDialog(CMapLoadingDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CMapLoadingDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Elementinitialisierung ein + //}}AFX_DATA_INIT + + Create(CMapLoadingDlg::IDD); +} + + +void CMapLoadingDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMapLoadingDlg) + DDX_Control(pDX, IDC_PROGRESS, m_Progress); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CMapLoadingDlg, CDialog) + //{{AFX_MSG_MAP(CMapLoadingDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Zuordnungsmakros fĂ¼r Nachrichten ein + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CMapLoadingDlg diff --git a/MissionEditor/MapLoadingDlg.h b/MissionEditor/MapLoadingDlg.h new file mode 100644 index 0000000..ff99f14 --- /dev/null +++ b/MissionEditor/MapLoadingDlg.h @@ -0,0 +1,66 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_MAPLOADINGDLG_H__19690341_CE13_11D4_9C87_444553540000__INCLUDED_) +#define AFX_MAPLOADINGDLG_H__19690341_CE13_11D4_9C87_444553540000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// MapLoadingDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CMapLoadingDlg + +class CMapLoadingDlg : public CDialog +{ +// Konstruktion +public: + CMapLoadingDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CMapLoadingDlg) + enum { IDD = IDD_MAPLOAD }; + CProgressCtrl m_Progress; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CMapLoadingDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CMapLoadingDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Member-Funktionen ein + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_MAPLOADINGDLG_H__19690341_CE13_11D4_9C87_444553540000__INCLUDED_ diff --git a/MissionEditor/MapModifier.cpp b/MissionEditor/MapModifier.cpp new file mode 100644 index 0000000..57fe456 --- /dev/null +++ b/MissionEditor/MapModifier.cpp @@ -0,0 +1,47 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// MapModifier.cpp: Implementierung der Klasse CMapModifier. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "stdafx.h" +#include "MapModifier.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +////////////////////////////////////////////////////////////////////// +// Konstruktion/Destruktion +////////////////////////////////////////////////////////////////////// + +CMapModifier::CMapModifier() +{ + +} + +CMapModifier::~CMapModifier() +{ + +} diff --git a/MissionEditor/MapModifier.h b/MissionEditor/MapModifier.h new file mode 100644 index 0000000..06cb7b4 --- /dev/null +++ b/MissionEditor/MapModifier.h @@ -0,0 +1,40 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// MapModifier.h: Schnittstelle fĂ¼r die Klasse CMapModifier. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_MAPMODIFIER_H__3853D321_CD37_11D4_9C87_F2DC6A2E6849__INCLUDED_) +#define AFX_MAPMODIFIER_H__3853D321_CD37_11D4_9C87_F2DC6A2E6849__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CMapModifier +{ +public: + CMapModifier(); + virtual ~CMapModifier(); + +}; + +#endif // !defined(AFX_MAPMODIFIER_H__3853D321_CD37_11D4_9C87_F2DC6A2E6849__INCLUDED_) diff --git a/MissionEditor/MapOpenDialog.cpp b/MissionEditor/MapOpenDialog.cpp new file mode 100644 index 0000000..25eca84 --- /dev/null +++ b/MissionEditor/MapOpenDialog.cpp @@ -0,0 +1,88 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// MapOpenDialog.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "MapOpenDialog.h" +#include "inlines.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMapOpenDialog + +UINT CALLBACK OFNHookProc( + HWND hdlg, // handle to child dialog window + UINT uiMsg, // message identifier + WPARAM wParam, // message parameter + LPARAM lParam // message parameter +) +{ + if(uiMsg==WM_NOTIFY) + { + OFNOTIFY ofn; + ofn=*((OFNOTIFY*)lParam); + if(ofn.hdr.code==CDN_SELCHANGE) + { + // user selected another file + wchar_t psz[MAX_PATH] = { 0 }; // filename + CommDlg_OpenSave_GetFilePathW(GetParent(hdlg), psz, MAX_PATH); + + // lets parse the file. Only load Basic section + CIniFile CurMap; + CurMap.InsertFile(utf16ToUtf8(psz),"Basic"); + + SetDlgItemText(hdlg, IDC_MAPNAME, CurMap.sections["Basic"].values["Name"]); + + + } + else if (ofn.hdr.code==CDN_FOLDERCHANGE) + RedrawWindow(GetParent(hdlg),NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE ); + } + + return 0; +} + + +IMPLEMENT_DYNAMIC(CMapOpenDialog, CFileDialog) + +CMapOpenDialog::CMapOpenDialog(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName, + DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) : + CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd) +{ + m_ofn.Flags|=OFN_EXPLORER | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK; + m_ofn.lpTemplateName=MAKEINTRESOURCE(IDD_MYOPENDIALOG); + m_ofn.lpfnHook=OFNHookProc; +} + + +BEGIN_MESSAGE_MAP(CMapOpenDialog, CFileDialog) + //{{AFX_MSG_MAP(CMapOpenDialog) + // HINWEIS - Der Klassen-Assistent fĂ¼gt hier Zuordnungsmakros ein und entfernt diese. + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + diff --git a/MissionEditor/MapOpenDialog.h b/MissionEditor/MapOpenDialog.h new file mode 100644 index 0000000..f478162 --- /dev/null +++ b/MissionEditor/MapOpenDialog.h @@ -0,0 +1,55 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_MAPOPENDIALOG_H__BA196F80_ACBA_11D3_B63B_8A39ED4C0940__INCLUDED_) +#define AFX_MAPOPENDIALOG_H__BA196F80_ACBA_11D3_B63B_8A39ED4C0940__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// MapOpenDialog.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CMapOpenDialog + +class CMapOpenDialog : public CFileDialog +{ + DECLARE_DYNAMIC(CMapOpenDialog) + +public: + CMapOpenDialog(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs + LPCTSTR lpszDefExt = NULL, + LPCTSTR lpszFileName = NULL, + DWORD dwFlags = OFN_EXPLORER | OFN_ENABLETEMPLATE | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + LPCTSTR lpszFilter = NULL, + CWnd* pParentWnd = NULL); + +protected: + //{{AFX_MSG(CMapOpenDialog) + // HINWEIS - Der Klassen-Assistent fĂ¼gt hier Member-Funktionen ein und entfernt diese. + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_MAPOPENDIALOG_H__BA196F80_ACBA_11D3_B63B_8A39ED4C0940__INCLUDED_ diff --git a/MissionEditor/MapTool.h b/MissionEditor/MapTool.h new file mode 100644 index 0000000..60bab55 --- /dev/null +++ b/MissionEditor/MapTool.h @@ -0,0 +1,87 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include +#include "structs.h" +#include + +class CMapData; +class CIsoView; + +enum class MapToolMouseFlags +{ + DEFAULT = 0, + LBUTTON = 1, + MBUTTON = 2, + RBUTTON = 4, + SHIFT = 8 +}; +DEFINE_ENUM_FLAG_OPERATORS(MapToolMouseFlags); + +inline MapToolMouseFlags MapToolMouseFlagsFromWin32(UINT nFlags) { + + MapToolMouseFlags flags = MapToolMouseFlags::DEFAULT; + + if ((nFlags & MK_LBUTTON) == MK_LBUTTON) + flags |= MapToolMouseFlags::LBUTTON; + + if ((nFlags & MK_MBUTTON) == MK_MBUTTON) + flags |= MapToolMouseFlags::MBUTTON; + + if ((nFlags & MK_RBUTTON) == MK_RBUTTON) + flags |= MapToolMouseFlags::RBUTTON; + + if ((nFlags & MK_SHIFT) == MK_SHIFT) + flags |= MapToolMouseFlags::SHIFT; + + return flags; +} + +class MapTool +{ +public: + virtual ~MapTool() = default; + + // return false if tool has not handled this call (or doesn't want to override any caller behavior) + virtual bool onRButtonUp(const ProjectedCoords& projCoords, const MapCoords& mapCoords3d, MapToolMouseFlags flags) + { + return false; + }; + + virtual void onLButtonDblClick(const ProjectedCoords& projCoords, const MapCoords& mapCoords3d, MapToolMouseFlags flags) {}; + virtual void onLButtonUp(const ProjectedCoords& projCoords, const MapCoords& mapCoords3d, MapToolMouseFlags flags) {}; + virtual void onMouseMove(const ProjectedCoords& projCoords, const MapCoords& mapCoords3d, MapToolMouseFlags flags) {}; + virtual void render() {}; + +protected: + MapTool(CMapData& map, CIsoView& view) : m_map(map), m_view(view) {}; + MapTool& operator=(const MapTool& other) = delete; + + CMapData& getMap() { return m_map; } + const CMapData& getMap() const { return m_map; } + CIsoView& getView() { return m_view; } + const CIsoView& getView() const { return m_view; } + +private: + CMapData& m_map; + CIsoView& m_view; +}; \ No newline at end of file diff --git a/MissionEditor/MapValidator.cpp b/MissionEditor/MapValidator.cpp new file mode 100644 index 0000000..fbf4ec2 --- /dev/null +++ b/MissionEditor/MapValidator.cpp @@ -0,0 +1,387 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// MapValidator.cpp: implementation file +// + +#include "stdafx.h" +#include "finalsun.h" +#include "MapValidator.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" +#include "inlines.h" +#include +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// dialog field CMapValidator + + +CMapValidator::CMapValidator(CWnd* pParent /*=NULL*/) + : CDialog(CMapValidator::IDD, pParent) +{ + //{{AFX_DATA_INIT(CMapValidator) + + //}}AFX_DATA_INIT +} + + +void CMapValidator::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMapValidator) + DDX_Control(pDX, IDC_MAPPROBLEMS, m_MapProblemList); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CMapValidator, CDialog) + //{{AFX_MSG_MAP(CMapValidator) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// message handlers CMapValidator + +void CMapValidator::UpdateStrings() +{ + SetWindowText(GetLanguageStringACP("MapValidatorCap")); + SetDlgItemText(IDC_LPROBLEMSFOUND, GetLanguageStringACP("MapValidatorProblemsFound")); + SetDlgItemText(IDOK, GetLanguageStringACP("OK")); + SetDlgItemText(IDCANCEL, GetLanguageStringACP("Cancel")); +} + +BOOL CMapValidator::OnInitDialog() +{ + CDialog::OnInitDialog(); + + UpdateStrings(); + + m_ProblemImages.Create(16,16,ILC_COLOR8 | ILC_MASK,0, 50 ); + + CBitmap bmpIcons; + bmpIcons.LoadBitmap(IDB_MV_ICONS); + + m_ProblemImages.Add(&bmpIcons, RGB(255,255,255)); + m_MapProblemList.SetImageList(&m_ProblemImages,LVSIL_SMALL); + m_MapProblemList.SetImageList(&m_ProblemImages,LVSIL_NORMAL); + + auto col = m_MapProblemList.InsertColumn(0, ""); + //RECT r; + //m_MapProblemList.GetClientRect(&r); + + + + BOOL bSaveAble=CheckMap(); + + m_MapProblemList.SetColumnWidth(col, LVSCW_AUTOSIZE); + + + if(bSaveAble==FALSE) GetDlgItem(IDOK)->EnableWindow(FALSE); + + return TRUE; +} + +void AddItemWithNewLine(CListCtrl& ctrl, CString s, int image) +{ + s.Replace("\\n", "\n"); + int n = ctrl.GetItemCount(); + for (const auto& line : Split(s, '\n')) + { + ctrl.InsertItem(n++, line, image); + image = 2; + } +} + +/* +CMapValidator::CheckMap(); + +Returns TRUE, when the map is saveable, but may not work. +If FALSE is returned, you should not anymore allow to save the map. +*/ +BOOL CMapValidator::CheckMap() +{ + BOOL bAllow=TRUE; + + // now check the map + + Map->UpdateIniFile(MAPDATA_UPDATE_TO_INI); + CIniFile& ini=Map->GetIniFile(); + + if(ini.sections.find("Map")==ini.sections.end() ) + { + bAllow=FALSE; + AddItemWithNewLine(m_MapProblemList, GetLanguageStringACP("MV_NoMap"), 0); + } + if(ini.sections.find("Basic")==ini.sections.end() || ini.sections["Basic"].values.size()==0) + { + bAllow=FALSE; + AddItemWithNewLine(m_MapProblemList, GetLanguageStringACP("MV_NoBasic"), 0); + + } + else + { + if(ini.sections["Basic"].values["Name"].GetLength()==0) + AddItemWithNewLine(m_MapProblemList, GetLanguageStringACP("MV_NoName"), 1); + + if(ini.sections["Basic"].values.find("Player")==ini.sections["Basic"].values.end()) + { +#ifdef TS_MODE + if(ini.sections.find(MAPHOUSES)!=ini.sections.end() && ini.sections["Houses"].values.size()>0) + { + AddItemWithNewLine(m_MapProblemList, GetLanguageStringACP("MV_HousesButNoPlayer"), 1); + AddItemWithNewLine(m_MapProblemList, GetLanguageStringACP("MV_HousesInMultiplayer"), 1); + } +#endif + } + + if(ini.sections.find(MAPHOUSES)==ini.sections.end()) + { + int d=Map->GetWaypointCount(); + int below8found=0; + int i; + for(i=0;iGetWaypointData(i, &id, &pos); + if(atoi(id)<8) + { + below8found++; + } + } + + if(below8found<8) + { + if(isFalse(ini.sections["Basic"].values["Official"])) + { + AddItemWithNewLine(m_MapProblemList, GetLanguageStringACP("MV_Not8Waypoints"), 1); + } + + if(below8found<2) + AddItemWithNewLine(m_MapProblemList, GetLanguageStringACP("MV_HousesNoWaypoints"), 1); + } + +#ifdef RA2_MODE + if(isTrue(ini.sections["Basic"].values["Official"])) + AddItemWithNewLine(m_MapProblemList, GetLanguageStringACP("MV_OfficialYes"), 1); +#endif + + } + + int i; + for(i=0;i0 && ini.sections["TaskForces"].FindValue(taskforce)<0) + { + CString error; + error=GetLanguageStringACP("MV_TaskForceMissing"); + error=TranslateStringVariables(1, error, taskforce); + error=TranslateStringVariables(2, error, *ini.sections["TeamTypes"].GetValue(i)); + AddItemWithNewLine(m_MapProblemList, error, 1); + } + } + for(i=0;i0 && ini.sections["ScriptTypes"].FindValue(scripttype)<0) + { + CString error; + error=GetLanguageStringACP("MV_ScripttypeMissing"); + error=TranslateStringVariables(1, error, scripttype); + error=TranslateStringVariables(2, error, *ini.sections["TeamTypes"].GetValue(i)); + AddItemWithNewLine(m_MapProblemList, error, 1); + } + } + for(i=0;i=0) + { + CString tag=sec.values["Tag"]; + if(ini.sections["Tags"].FindName(tag)<0) + { + CString error; + error=GetLanguageStringACP("MV_TagMissing"); + error=TranslateStringVariables(1, error, tag); + error=TranslateStringVariables(2, error, "Teamtype"); + error=TranslateStringVariables(3, error, *ini.sections["TeamTypes"].GetValue(i)); + AddItemWithNewLine(m_MapProblemList, error, 1); + } + } + } + for(i=0;iGetCelltagCount();i++) + { + CString tag; + DWORD pos; + Map->GetCelltagData(i, &tag, &pos); + int x=pos%Map->GetIsoSize(); + int y=pos/Map->GetIsoSize(); + char cx[50]; + char cy[50]; + itoa(x, cx, 10); + itoa(y, cy, 10); + CString p=cx; + p+="/"; + p+=cy; + if(ini.sections["Tags"].FindName(tag)<0) + { + CString error; + error=GetLanguageStringACP("MV_TagMissing"); + error=TranslateStringVariables(1, error, tag); + error=TranslateStringVariables(2, error, "Celltag"); + error=TranslateStringVariables(3, error, p); + AddItemWithNewLine(m_MapProblemList, error, 1); + } + } + + } + + const auto& tubes = Map->GetTubes(); + for (auto& tube : tubes) + { + auto n_reverse = std::count_if(tubes.begin(), tubes.end(), [&tube](const auto& other) { return tube->isCounterpart(*other); }); + if (n_reverse == 0) + { + CString error = TranslateTubeString( + GetLanguageStringACP("MV_TubeCounterpartMissing"), + *tube, + n_reverse + ); + AddItemWithNewLine(m_MapProblemList, error, 0); + } + auto n_same_start = std::count_if(tubes.begin(), tubes.end(), [&tube](const auto& other) { return tube->getStartCoords() == other->getStartCoords() && *tube != *other; }); + if (n_same_start) + { + CString error = TranslateTubeString( + GetLanguageStringACP("MV_TubeStartNotUnique"), + *tube, + n_same_start + ); + AddItemWithNewLine(m_MapProblemList, error, 0); + } + auto n_same_end = std::count_if(tubes.begin(), tubes.end(), [&tube](const auto& other) { return tube->getEndCoords() == other->getEndCoords() && *tube != *other; }); + if (n_same_end) + { + CString error = TranslateTubeString( + GetLanguageStringACP("MV_TubeEndNotUnique"), + *tube, + n_same_end + ); + AddItemWithNewLine(m_MapProblemList, error, 0); + } + auto n_invalid_counterpart_end = std::count_if(tubes.begin(), tubes.end(), [&tube](const auto& other) { return tube->getEndCoords() == other->getStartCoords() && tube->getStartCoords() != other->getEndCoords(); }); + if (n_invalid_counterpart_end) + { + CString error = TranslateTubeString( + GetLanguageStringACP("MV_TubeInvalidCounterpartEnd"), + *tube, + n_invalid_counterpart_end + ); + AddItemWithNewLine(m_MapProblemList, error, 0); + } + auto n_invalid_counterpart_start = std::count_if(tubes.begin(), tubes.end(), [&tube](const auto& other) { return tube->getStartCoords() == other->getEndCoords() && tube->getEndCoords() != other->getStartCoords(); }); + if (n_invalid_counterpart_start) + { + CString error = TranslateTubeString( + GetLanguageStringACP("MV_TubeInvalidCounterpartStart"), + *tube, + n_invalid_counterpart_start + ); + AddItemWithNewLine(m_MapProblemList, error, 0); + } + } + + int i; + BOOL bWaypBig=FALSE; + for(i=0;iGetWaypointCount();i++) + { + DWORD pos; + CString id; + + Map->GetWaypointData(i, &id, &pos); + + if(atoi(id)>99) bWaypBig=TRUE; + } + + if(bWaypBig) + AddItemWithNewLine(m_MapProblemList, GetLanguageStringACP("MV_>100Waypoint"), 1); + + if(Map->IsYRMap()) + { + AddItemWithNewLine(m_MapProblemList, GetLanguageStringACP("NeedsYR"), 1); + } + + return bAllow; +} + +CString TranslateTubeString(const char* error_, const CTube& tube, int count) +{ + CString error = error_; + error = TranslateStringVariables(1, error, std::to_string(tube.getStartX()).c_str()); + error = TranslateStringVariables(2, error, std::to_string(tube.getStartY()).c_str()); + error = TranslateStringVariables(3, error, std::to_string(tube.getEndX()).c_str()); + error = TranslateStringVariables(4, error, std::to_string(tube.getEndY()).c_str()); + error = TranslateStringVariables(5, error, std::to_string(tube.getId()).c_str()); + error = TranslateStringVariables(6, error, std::to_string(count).c_str()); + return error; +} diff --git a/MissionEditor/MapValidator.h b/MissionEditor/MapValidator.h new file mode 100644 index 0000000..7097b27 --- /dev/null +++ b/MissionEditor/MapValidator.h @@ -0,0 +1,73 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_MAPVALIDATOR_H__B290D180_F761_11D3_B63B_00485453E8BA__INCLUDED_) +#define AFX_MAPVALIDATOR_H__B290D180_F761_11D3_B63B_00485453E8BA__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// MapValidator.h : Header file +// + +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +// dialog field CMapValidator + +class CMapValidator : public CDialog +{ +// construction +public: + CMapValidator(CWnd* pParent = NULL); // standard constructor + +// dialog field data + //{{AFX_DATA(CMapValidator) + enum { IDD = IDD_MAPVALIDATOR }; + + //}}AFX_DATA + + +// overwriteables + //{{AFX_VIRTUAL(CMapValidator) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// implementation +protected: + + // generated message maps + //{{AFX_MSG(CMapValidator) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + CImageList m_ProblemImages; + CListCtrl m_MapProblemList; + void UpdateStrings(); + BOOL CheckMap(); +}; + +//{{AFX_INSERT_LOCATION}} + +#endif // AFX_MAPVALIDATOR_H__B290D180_F761_11D3_B63B_00485453E8BA__INCLUDED_ + +CString TranslateTubeString(const char* error_, const CTube& tube, int count); diff --git a/MissionEditor/MiniMap.cpp b/MissionEditor/MiniMap.cpp new file mode 100644 index 0000000..69f5b01 --- /dev/null +++ b/MissionEditor/MiniMap.cpp @@ -0,0 +1,302 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// MiniMap.cpp: implementaion file +// + +#include "stdafx.h" +#include "finalsun.h" +#include "MiniMap.h" +#include "finalsundlg.h" +#include "macros.h" +#include "mapdata.h" +#include "variables.h" +#include "inlines.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMiniMap + +IMPLEMENT_DYNCREATE(CMiniMap, CView) + +CMiniMap::CMiniMap(): m_scale(theApp.m_Options.fMiniMapScale) +{ +} + +CMiniMap::~CMiniMap() +{ +} + + +BEGIN_MESSAGE_MAP(CMiniMap, CView) + //{{AFX_MSG_MAP(CMiniMap) + ON_WM_SYSCOMMAND() + ON_WM_MOUSEMOVE() + ON_WM_LBUTTONDOWN() + //}}AFX_MSG_MAP + ON_WM_SIZING() + ON_WM_SETCURSOR() +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// draw CMiniMap + +void CMiniMap::OnDraw(CDC* pDC) +{ + + BYTE* colors; + BITMAPINFO biinfo; + int pitch; + DrawMinimap(&colors, biinfo, pitch); + + if(!colors) return; + + // set the bits + //SetDIBitsToDevice(pDC->m_hDC, 0, 0, Map->GetWidth()*2, Map->GetHeight(),0,0,0, Map->GetHeight(), colors, &biinfo, DIB_RGB_COLORS); + RECT r; + GetClientRect(&r); + StretchDIBits(pDC->m_hDC, 0, 0, r.right, r.bottom, 0, 0, Map->GetWidth() * 2, Map->GetHeight(), colors, &biinfo, DIB_RGB_COLORS, SRCCOPY); + + + // now draw the current position + CFinalSunDlg& dlg=*(CFinalSunDlg*)theApp.GetMainWnd(); + CIsoView& isoview=*dlg.m_view.m_isoview; + RECT selRect; + auto isoRect = isoview.GetScaledDisplayRect(); + + int mapwidth=Map->GetWidth(); + int mapheight=Map->GetHeight(); + + + // Get iso view display rectangle + RECT cr; + isoview.GetClientRect(&cr); + auto topLeft = Map->GetMiniMapPos(isoview.GetMapCoordinatesFromClientCoordinates(CPoint(0, 0), false, true)); + auto topRight = Map->GetMiniMapPos(isoview.GetMapCoordinatesFromClientCoordinates(CPoint(cr.right, 0), false, true)); + auto bottomLeft = Map->GetMiniMapPos(isoview.GetMapCoordinatesFromClientCoordinates(CPoint(0, cr.bottom), false, true)); + auto bottomRight = Map->GetMiniMapPos(isoview.GetMapCoordinatesFromClientCoordinates(CPoint(cr.right, cr.bottom), false, true)); + auto left = min(topLeft.x, topRight.x); + auto top = min(topLeft.y, topRight.y); + auto right = max(bottomLeft.x, bottomRight.x); + auto bottom = max(bottomLeft.y, bottomRight.y); + + CPoint center(r.right / 2, r.bottom / 2); + selRect.left = left * m_scale; + selRect.top = top * m_scale; + selRect.right = right * m_scale; + selRect.bottom = bottom * m_scale; + + + pDC->Draw3dRect(&selRect, RGB(200,0,0), RGB(120,0,0)); + +} + +///////////////////////////////////////////////////////////////////////////// +// diagnose CMiniMap + +#ifdef _DEBUG +void CMiniMap::AssertValid() const +{ + CView::AssertValid(); +} + +void CMiniMap::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// handlers + +BOOL CMiniMap::PreCreateWindow(CREATESTRUCT& cs) +{ + // MW 07/17/2001: Style changed + + cs.style = WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU;// | WS_CHILD; + cs.cx=0; + cs.cy=0; + + CFinalSunDlg& dlg=*(CFinalSunDlg*)theApp.GetMainWnd(); + //CIsoView& isoview=*dlg.m_view.m_isoview; + RECT r; + dlg.GetWindowRect(&r); + + cs.x=0;//r.right-250 ; + cs.y=r.bottom-250; + if(cs.y<0) cs.y=0; + //cs.dwExStyle=WS_EX_TOOLWINDOW; + //cs.dwExStyle=WS_EX_PALETTEWINDOW; + + // this here will cause an assert in debug mode, ignore it (window must be a child window) + int res=CWnd::PreCreateWindow(cs); + + cs.style=WS_POPUPWINDOW | WS_CAPTION /*| WS_DLGFRAME */ | WS_THICKFRAME | WS_OVERLAPPED | DS_3DLOOK | WS_MINIMIZEBOX; //WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX; + + return res; + +} + +void CMiniMap::UpdateView() +{ + CRect r; + GetWindowRect(r); + + if(Map->GetIsoSize()==0) + { + ShowWindow(SW_HIDE); + } + else + { + // calculate the needed width=height + int axissizex=Map->GetWidth()*2; + int axissizey=Map->GetHeight(); + + SetIcon(theApp.m_pMainWnd->GetIcon(FALSE), FALSE); + SetIcon(theApp.m_pMainWnd->GetIcon(TRUE), TRUE); + SetWindowPos(&wndTopMost, r.left, r.top, axissizex * m_scale + 2 * (GetSystemMetrics(SM_CXFIXEDFRAME)), axissizey * m_scale + 2 * GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYCAPTION), SWP_SHOWWINDOW); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + + +} + + +BOOL bMiniMapClosedByUser=FALSE; + +void CMiniMap::OnSysCommand(UINT nID, LPARAM lParam) +{ + + if(nID==SC_CLOSE) + { + bMiniMapClosedByUser=TRUE; + ShowWindow(SW_HIDE); + return; + } + + CWnd::OnSysCommand(nID, lParam); +} + + +void CMiniMap::OnMouseMove(UINT nFlags, CPoint point) +{ + if(nFlags==MK_LBUTTON) + { + int x,y; + int xiso; + int yiso; + + //y=Map->GetIsoSize()-(point.y - point.x+ /*(float)Map->GetIsoSize()/2.0f*/+1); + //x=Map->GetIsoSize()-(point.x + point.y- /*(float)Map->GetIsoSize()/2.0f*/+1); + //y-=Map->GetHeight(); + + RECT cr; + GetClientRect(&cr); + float defaultXSize = (Map->GetWidth() * 2 * m_scale); + float defaultYSize = (Map->GetHeight() * m_scale); + float resizedXScale = cr.right / defaultXSize; + float resizedYScale = cr.bottom / defaultYSize; + + CFinalSunDlg& dlg = *(CFinalSunDlg*)theApp.GetMainWnd(); + CIsoView& isoview = *dlg.m_view.m_isoview; + + auto viewScale = isoview.GetViewScale(); + auto viewOffset = isoview.GetViewOffset(); + + x = (point.x / m_scale / resizedXScale) / 2 +Map->GetHeight() / 2; + y = (point.y / m_scale / resizedYScale) + Map->GetWidth() / 2; + + + RECT r = isoview.GetScaledDisplayRect(); + + + isoview.SetScroll((x-r.right/f_x/2)*f_x, (y-r.bottom/f_y/2)*f_y); + + + isoview.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } +} + +void CMiniMap::OnLButtonDown(UINT nFlags, CPoint point) +{ + + OnMouseMove(nFlags, point); +} + +void CMiniMap::DrawMinimap(BYTE **lpData, BITMAPINFO &biinfo, int& Pitch) +{ + Map->GetMinimap(lpData, &biinfo, &Pitch); + + // fix straw pixels + auto* data = *lpData; + if (data) + { + // fix bottom left and right top pixels in the bottom-up bitmap + memcpy(&data[0], &data[sizeof(RGBTRIPLE)], sizeof(RGBTRIPLE)); + auto firstLine = (biinfo.bmiHeader.biHeight - 1) * Pitch; + memcpy(&data[firstLine + (biinfo.bmiHeader.biWidth - 1) * sizeof(RGBTRIPLE)], &data[firstLine + (biinfo.bmiHeader.biWidth - 2) * sizeof(RGBTRIPLE)], sizeof(RGBTRIPLE)); + } +} + + + +void CMiniMap::OnSizing(UINT fwSide, LPRECT pRect) +{ + CView::OnSizing(fwSide, pRect); + + int axissizex = Map->GetWidth() * 2; + int axissizey = Map->GetHeight(); + float ratio = float(axissizex) / float(axissizey); + + if (pRect) + { + int heightAdd = 2 * GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYCAPTION); + int widthAdd = 2 * GetSystemMetrics(SM_CXFIXEDFRAME); + if (fwSide == WMSZ_LEFT || fwSide == WMSZ_TOPLEFT || fwSide == WMSZ_BOTTOMLEFT || + fwSide == WMSZ_RIGHT || fwSide == WMSZ_BOTTOMRIGHT) + { + pRect->bottom = pRect->top + (pRect->right - pRect->left - widthAdd) / ratio + heightAdd; + } + else + { + pRect->right = pRect->left + (pRect->bottom - pRect->top - heightAdd) * ratio + widthAdd; + } + } + + //width = axissizex* m_scale + 2 * (GetSystemMetrics(SM_CXFIXEDFRAME)) + + m_scale = ((pRect->right - pRect->left) - 2 * GetSystemMetrics(SM_CXFIXEDFRAME)) / (float)axissizex; + + RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); +} + + +BOOL CMiniMap::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) +{ + if (!CView::OnSetCursor(pWnd, nHitTest, message)) + SetCursor(m_hArrowCursor); + return TRUE; +} diff --git a/MissionEditor/MiniMap.h b/MissionEditor/MiniMap.h new file mode 100644 index 0000000..5893261 --- /dev/null +++ b/MissionEditor/MiniMap.h @@ -0,0 +1,84 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_MINIMAP_H__43F7CCE0_CC11_11D3_B63B_00485453E8BA__INCLUDED_) +#define AFX_MINIMAP_H__43F7CCE0_CC11_11D3_B63B_00485453E8BA__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// MiniMap.h : Header file +// + +///////////////////////////////////////////////////////////////////////////// +// View CMiniMap + +class CMiniMap : public CView +{ +public: + CMiniMap(); + virtual ~CMiniMap(); + DECLARE_DYNCREATE(CMiniMap) + +// attributes +public: + +// operations +public: + void DrawMinimap(BYTE** lpData, BITMAPINFO& biinfo, int& Pitch); + + void UpdateView(); + +// overwriteables + //{{AFX_VIRTUAL(CMiniMap) + protected: + virtual void OnDraw(CDC* pDC); + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + //}}AFX_VIRTUAL + +// Implementierung +protected: +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + + // generated message maps +protected: + //{{AFX_MSG(CMiniMap) + afx_msg void OnSysCommand(UINT nID, LPARAM lParam); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +private: + float m_scale; +public: + afx_msg void OnSizing(UINT fwSide, LPRECT pRect); + afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} + +#endif // AFX_MINIMAP_H__43F7CCE0_CC11_11D3_B63B_00485453E8BA__INCLUDED_ diff --git a/MissionEditor/MissionEditor.rc b/MissionEditor/MissionEditor.rc new file mode 100644 index 0000000..457be9a --- /dev/null +++ b/MissionEditor/MissionEditor.rc @@ -0,0 +1,3614 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) + +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(65001)\r\n" + "#endif //_WIN32\r\n" + "#include ""res\\FinalSun.rc2"" // Nicht mit Microsoft Visual C++ bearbeitete Ressourcen\r\n" + "#include ""afxres.rc"" // Standardkomponenten\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Englisch (USA) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +///////////////////////////////////////////////////////////////////////////// +// +// Cursor +// + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDC_EDITOR_ARROW$(TS_MODE) CURSOR "res\\ts_arrow.cur" + +#else +IDC_EDITOR_ARROW CURSOR "res\\ts_arrow.cur" + +#endif +#endif +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDC_EDITOR_ARROW$(RA2_MODE) CURSOR "res\\ra2_arrow.cur" + +#else +IDC_EDITOR_ARROW CURSOR "res\\ra2_arrow.cur" + +#endif +#endif + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDB_FLAG$(TS_MODE) BITMAP "res\\wp_ts.bmp" + +#else +IDB_FLAG BITMAP "res\\wp_ts.bmp" + +#endif +#endif +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDB_CELLTAG$(TS_MODE) BITMAP "res\\celltag_ts.bmp" + +#else +IDB_CELLTAG BITMAP "res\\celltag_ts.bmp" + +#endif +#endif +IDB_LIGHTBULB BITMAP "res\\litebulb.bmp" + +IDB_MV_ICONS BITMAP "res\\bmp00005.bmp" + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDB_SCROLLCURSOR$(TS_MODE) BITMAP "res\\scrollcursor_ts.bmp" + +#else +IDB_SCROLLCURSOR BITMAP "res\\scrollcursor_ts.bmp" + +#endif +#endif +IDR_MAINFRAME BITMAP "res\\Toolbar.bmp" + +IDR_TERRAINBAR BITMAP "res\\terrainb.bmp" + +IDR_CLIFFBAR BITMAP "res\\clifftoo.bmp" + +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDB_CELLTAG$(RA2_MODE) BITMAP "res\\celltag_ra2.bmp" + +#else +IDB_CELLTAG BITMAP "res\\celltag_ra2.bmp" + +#endif +#endif +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDB_FLAG$(RA2_MODE) BITMAP "res\\wp_ra2.bmp" + +#else +IDB_FLAG BITMAP "res\\wp_ra2.bmp" + +#endif +#endif +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDB_SCROLLCURSOR$(RA2_MODE) BITMAP "res\\scrollcursor_ra2.bmp" + +#else +IDB_SCROLLCURSOR BITMAP "res\\scrollcursor_ra2.bmp" + +#endif +#endif + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_NEWRA2HOUSE DIALOG 0, 0, 186, 52 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Create new house" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 + LTEXT "Choose parent country:",IDC_STATIC,7,7,98,12 + COMBOBOX IDC_COUNTRY,7,20,112,118,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP +END + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_SAVEOPTIONS$(TS_MODE) DIALOG 0, 0, 233, 125 +#else +IDD_SAVEOPTIONS DIALOG 0, 0, 233, 125 +#endif +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Save options" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "OK",IDOK,176,104,50,14 + PUSHBUTTON "Cancel",IDCANCEL,117,104,50,14 + CONTROL "Compress map",IDC_COMPRESS,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE | WS_GROUP,19,42,118,12 + CONTROL "Don't compress map (use this if any problems with the map occur in RA2/TS)",IDC_NOCOMPRESSION, + "Button",BS_AUTORADIOBUTTON | BS_MULTILINE | NOT WS_VISIBLE,19,52,192,21 + CONTROL "Create new preview using minimap",IDC_PREVIEWMODE, + "Button",BS_AUTORADIOBUTTON | WS_GROUP,19,40,150,13 + CONTROL "Use existing preview (if possible)",IDC_EXISTINGPREVIEW, + "Button",BS_AUTORADIOBUTTON,19,53,141,12 + CONTROL "Don't save any preview",IDC_NOPREVIEW,"Button",BS_AUTORADIOBUTTON,19,66,141,12 + GROUPBOX "Compression",IDC_STATIC,7,28,219,52,NOT WS_VISIBLE + GROUPBOX "Preview",IDC_STATIC,7,29,219,56 + LTEXT "If you want to play the map online, you should try to make the file size as low as possible. This includes turning off the preview. You should also try using compression.",IDC_STATIC,7,90,219,27,NOT WS_VISIBLE + LTEXT "Map name:",IDC_STATIC,7,7,63,13 + EDITTEXT IDC_MAPNAME,73,7,153,12,ES_AUTOHSCROLL +END +#endif + +IDD_MULTISAVEOPT DIALOG 0, 0, 281, 105 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Specify file type" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,224,84,50,14 + PUSHBUTTON "Cancel",IDCANCEL,161,84,50,14 + LTEXT "Please specify if you want to save your multiplayer map as *.mmx map or as *.mpr map. While *.mmx maps are the recommended method, as they are fully supported and do not slow down RA2 when loading, they are never transferred automatically to other players!",IDC_STATIC,7,7,267,38 + CONTROL "Save as *.mmx (no automatic map transfer)",IDC_MMX, + "Button",BS_AUTORADIOBUTTON | WS_GROUP,7,47,267,15 + CONTROL "Save as *.mpr (many mprs slow down RA2 while loading)",IDC_MMX2, + "Button",BS_AUTORADIOBUTTON,7,59,267,15 +END + +IDD_MMXOPTIONS DIALOG 0, 0, 268, 172 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "MMX options" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,211,151,50,14 + PUSHBUTTON "Cancel",IDCANCEL,141,151,50,14 + LTEXT "If description tag does not exist, RA2 will place MISSING: in front of the map name, this does not affect the game!",IDC_STATIC,7,7,254,21 + LTEXT "Description tag:",IDC_STATIC,7,37,80,12 + EDITTEXT IDC_DESCRIPTION,90,37,171,15,ES_AUTOHSCROLL + CONTROL "Standard",IDC_STANDARD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,89,80,14 + CONTROL "Meatgrind",IDC_MEATGRIND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,90,80,14 + CONTROL "Naval War",IDC_NAVALWAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,174,90,80,14 + CONTROL "Nuke War",IDC_NUKEWAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,105,80,14 + CONTROL "Air War",IDC_AIRWAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,105,80,14 + CONTROL "Mega Wealth",IDC_MEGAWEALTH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,174,105,80,14 + CONTROL "Duel",IDC_DUEL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,121,80,14 + CONTROL "Cooperative",IDC_COOPERATIVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,121,80,14 + LTEXT "Min players:",IDC_STATIC,7,63,54,12 + COMBOBOX IDC_MINPLAYERS,89,62,40,103,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Max players:",IDC_STATIC,148,63,54,12 + COMBOBOX IDC_MAXPLAYERS,221,61,40,104,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP +END + +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_SAVEOPTIONS$(RA2_MODE) DIALOG 0, 0, 233, 186 +#else +IDD_SAVEOPTIONS DIALOG 0, 0, 233, 186 +#endif +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Save options" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "OK",IDOK,176,165,50,14 + PUSHBUTTON "Cancel",IDCANCEL,117,165,50,14 + CONTROL "Compress map",IDC_COMPRESS,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE | WS_GROUP,201,46,25,8 + CONTROL "Don't compress map (use this if any problems with the map occur in RA2/TS)",IDC_NOCOMPRESSION, + "Button",BS_AUTORADIOBUTTON | BS_MULTILINE | NOT WS_VISIBLE,184,62,42,13 + CONTROL "Create new preview using minimap",IDC_PREVIEWMODE, + "Button",BS_AUTORADIOBUTTON | WS_GROUP,19,40,150,13 + CONTROL "Use existing preview (if possible)",IDC_EXISTINGPREVIEW, + "Button",BS_AUTORADIOBUTTON,19,53,141,12 + CONTROL "Don't save any preview",IDC_NOPREVIEW,"Button",BS_AUTORADIOBUTTON,19,66,141,12 + GROUPBOX "Compression",IDC_STATIC,119,52,107,15,NOT WS_VISIBLE + GROUPBOX "Preview",IDC_STATIC,7,29,219,56 + LTEXT "If you want to play the map online, you should try to make the file size as low as possible. This includes turning off the preview.",IDC_STATIC,7,143,219,21 + LTEXT "Map name:",IDC_STATIC,7,7,63,13 + EDITTEXT IDC_MAPNAME,73,7,153,12,ES_AUTOHSCROLL + CONTROL "Standard",IDC_STANDARD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,89,67,14 + CONTROL "Meatgrind",IDC_MEATGRIND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,83,90,65,14 + CONTROL "Naval War",IDC_NAVALWAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,161,90,65,14 + CONTROL "Nuke War",IDC_NUKEWAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,105,66,14 + CONTROL "Air War",IDC_AIRWAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,83,105,65,14 + CONTROL "Mega Wealth",IDC_MEGAWEALTH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,161,105,80,14 + CONTROL "Land Rush",IDC_DUEL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,121,59,14 + CONTROL "Cooperative",IDC_COOPERATIVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,83,121,70,14 + CONTROL "Team Alliance",IDC_TEAMGAME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,161,121,65,14 +END +#endif + +IDD_CHANGESIZE DIALOG 0, 0, 212, 194 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Change Map Size" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,155,173,50,14 + PUSHBUTTON "Cancel",IDCANCEL,97,173,50,14 + LTEXT "Please specify the new width and height of the map. Left and top will automatically be set so that the old area of the map is centered. You can change left and top to modify the left-top position (you may use negative numbers for left/top).",IDC_STATIC,7,7,198,36 + LTEXT "Width:",IDC_STATIC,7,54,71,13 + EDITTEXT IDC_WIDTH,86,52,62,15,ES_AUTOHSCROLL + LTEXT "Note: If there are any units, buildings, waypoints etc. outside of the new map area, they will be deleted.",IDC_STATIC,7,132,198,19 + LTEXT "Height:",IDC_STATIC,7,72,71,13 + EDITTEXT IDC_HEIGHT,86,70,62,15,ES_AUTOHSCROLL + LTEXT "Left:",IDC_STATIC,7,90,71,13 + EDITTEXT IDC_LEFT,86,88,62,15,ES_AUTOHSCROLL + LTEXT "Top:",IDC_STATIC,7,108,71,13 + EDITTEXT IDC_TOP,86,106,62,15,ES_AUTOHSCROLL + LTEXT "UNDO IS NOT AVAILABLE!",IDC_STATIC,7,152,198,16 +END + +IDD_AITRIGGERADD DIALOG 0, 0, 222, 97 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Enable AI Trigger" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,165,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,165,24,50,14 + LTEXT "Select AI Trigger that should be enabled:",IDC_STATIC,7,7,136,21 + LISTBOX IDC_AITRIGGERS,7,48,208,42,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP +END + +IDD_MYOPENDIALOG DIALOGEX 0, 0, 222, 30 +STYLE DS_LOCALEDIT | DS_SETFONT | DS_3DLOOK | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 8, "Tahoma", 0, 0, 0x1 +BEGIN + LTEXT "Map name:",IDC_STATIC,5,4,41,14 + EDITTEXT IDC_MAPNAME,54,4,155,14,ES_AUTOHSCROLL +END + +IDD_TIP DIALOGEX 0, 0, 275, 174 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Tip of the day" +FONT 8, "Tahoma", 0, 0, 0x0 +BEGIN + LTEXT "TIP",IDC_TIPSTRING,28,63,177,60 + CONTROL "&Show tips at program start",IDC_STARTUP,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,13,152,134,10 + PUSHBUTTON "&Next tip",IDC_NEXTTIP,157,152,52,14,WS_GROUP + DEFPUSHBUTTON "&Close",IDOK,216,152,50,14,WS_GROUP + CONTROL "",IDC_TOOLTIPCENTER,"Static",SS_BLACKFRAME,12,11,251,134 +END + +IDD_FINALSUN_DIALOG DIALOGEX 0, 0, 414, 287 +STYLE DS_SETFONT | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +EXSTYLE WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR | WS_EX_APPWINDOW +CAPTION "FinalAlert 2" +MENU IDR_MAIN +FONT 8, "Tahoma", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "just to prohibite enter to quit.",IDOK,0,124,21,12,NOT WS_VISIBLE + PUSHBUTTON "and that one to prevent cancelling",IDCANCEL,5,191,18,8,NOT WS_VISIBLE + LTEXT "As FinalAlert was dialog based in earlier versions, we need to have this.",IDC_STATIC,7,156,26,26 +END + +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_TSOPTIONS$(RA2_MODE) DIALOGEX 0, 0, 197, 183 +#else +IDD_TSOPTIONS DIALOGEX 0, 0, 197, 183 +#endif +STYLE DS_SETFONT | DS_MODALFRAME | DS_NOFAILCREATE | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Options" +FONT 8, "Tahoma", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,140,159,50,14 + PUSHBUTTON "Cancel",IDCANCEL,85,159,50,14 + LTEXT "Red Alert 2 EXE (make sure its in the correct path)",IDC_STATIC,5,5,130,20 + EDITTEXT IDC_EDIT1,5,25,130,15,ES_AUTOHSCROLL + PUSHBUTTON "Browse",IDC_CHOOSE,140,25,50,15 + LTEXT "Language / Sprache:",IDC_STATIC,7,51,128,11 + COMBOBOX IDC_LANGUAGE,7,63,183,94,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Support settings",IDC_STATIC,7,81,183,71 + CONTROL "Support mission disks and mods (recommended)",IDC_RULESLIKETS, + "Button",BS_AUTORADIOBUTTON | BS_MULTILINE | WS_GROUP,14,92,170,16 + CONTROL "Only support original Red Alert 2",IDC_ONLYORIGINAL, + "Button",BS_AUTORADIOBUTTON | BS_MULTILINE,14,108,168,16 + CONTROL "Prefer FinalAlert 2 theater INI files",IDC_PREFER_LOCAL_THEATER_FILES, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,131,164,12 +END +#endif + +IDD_ALL DIALOG 0, 0, 303, 204 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "INI Editor" +FONT 8, "Tahoma" +BEGIN + LTEXT "We highly recommend not to use this editor except you really know what you are doing.",IDC_STATIC,6,5,290,15 + LTEXT "Sections:",IDC_STATIC,5,25,55,10 + COMBOBOX IDC_SECTIONS,61,25,235,85,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Keys:",IDC_STATIC,15,80,40,10 + PUSHBUTTON "Add",IDC_ADDSECTION,60,40,55,15 + PUSHBUTTON "Delete",IDC_DELETESECTION,120,40,55,15 + GROUPBOX "Section content",IDC_STATIC,6,67,290,130 + LISTBOX IDC_KEYS,60,80,225,90,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LTEXT "Value:",IDC_STATIC,15,175,40,15 + EDITTEXT IDC_VALUE,60,175,225,12,ES_AUTOHSCROLL + PUSHBUTTON "Add",IDC_ADDKEY,15,95,40,15 + PUSHBUTTON "Delete",IDC_DELETEKEY,15,115,40,15 + PUSHBUTTON "Insert another INI file content",IDC_INISECTION,181,40,115,15 +END + +IDD_MAP DIALOG 0, 0, 303, 204 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Map Properties" +FONT 8, "Tahoma" +BEGIN + LTEXT "Except useable size just for information.",IDC_DESC,7,7,289,18 + GROUPBOX "Size of map data",IDC_SIZEFRAME,6,28,290,62 + GROUPBOX """Useable"" size",IDC_USEABLEFRAME,6,95,290,55 + LTEXT "The ""physical"" size of the map. Format: 0,0,Width,Height.",IDC_LSIZE,10,39,275,13 + EDITTEXT IDC__SIZEX,11,67,90,12,ES_AUTOHSCROLL | ES_READONLY + LTEXT "The ""useable"" size of the map. This specifies where you can place buildings etc. Has the following format: Left,Top,Right,Bottom",IDC_LUSEABLE,10,110,275,20 + EDITTEXT IDC_USESIZE,10,131,90,12,ES_AUTOHSCROLL + LTEXT "Theater:",IDC_LTHEATER,12,159,284,11 + COMBOBOX IDC_THEATER,10,170,90,45,CBS_DROPDOWN | CBS_SORT | WS_DISABLED | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Change",IDC_CHANGELOCAL,111,131,70,13 + PUSHBUTTON "Change",IDC_CHANGE,212,67,70,13 + LTEXT "Width:",IDC_STATIC,12,56,93,9 + EDITTEXT IDC__SIZEY,106,67,90,12,ES_AUTOHSCROLL | ES_READONLY + LTEXT "Height:",IDC_STATIC,107,56,93,9 +END + +IDD_INPUTBOX DIALOG 0, 0, 214, 70 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "OK",IDOK,160,5,50,14 + PUSHBUTTON "Cancel",IDCANCEL,160,25,50,14 + LTEXT "Static",IDC_SENTENCE,5,5,150,35 + EDITTEXT IDC_VAL,5,50,205,12,ES_AUTOHSCROLL +END + +IDD_IMPORTINI DIALOG 0, 0, 229, 150 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Insert INI file section" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "OK",IDOK,170,5,50,14 + PUSHBUTTON "Cancel",IDCANCEL,170,25,50,14 + LTEXT "Choose the sections you want to import in the map. Be careful! If you import a section that already exists, keys of the already existing section may be overwritten!",IDC_STATIC,5,5,155,35 + LISTBOX IDC_AVAILABLE,5,75,215,55,LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP + LTEXT "Available sections:",IDC_STATIC,5,65,100,10 + CONTROL "Import all sections",IDC_ALLSECTIONS,"Button",BS_AUTORADIOBUTTON,5,40,155,10 + CONTROL "Specify sections to be imported",IDC_SPECIFYSECTIONS, + "Button",BS_AUTORADIOBUTTON,5,50,150,10 + LTEXT "Select the sections you wish to import.",IDC_STATIC,5,135,215,10 +END + +IDD_LIGHTING DIALOG 0, 0, 303, 204 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Lighting Settings" +FONT 8, "Tahoma" +BEGIN + LTEXT "Lighting settings define the color of the terrain in the game, and you can specify a very dark or very bright map. Be careful, using wrong settings may cause the player to be unable to see his units.",IDC_DESC,6,5,290,25 + GROUPBOX "Normal",IDC_LNORMAL,6,35,290,65 + GROUPBOX "Ion storm settings",IDC_LIONSTORM,6,110,290,65 + LTEXT "Ambient:",IDC_LAMBIENT1,15,50,50,10 + EDITTEXT IDC_AMBIENT,65,50,75,12,ES_AUTOHSCROLL + LTEXT "Green:",IDC_LGREEN1,160,65,50,10 + EDITTEXT IDC_GREEN,210,65,75,12,ES_AUTOHSCROLL + LTEXT "Red:",IDC_LRED1,160,50,50,10 + EDITTEXT IDC_RED,210,50,75,12,ES_AUTOHSCROLL + LTEXT "Blue:",IDC_LBLUE1,160,80,50,10 + EDITTEXT IDC_BLUE,210,80,75,12,ES_AUTOHSCROLL + LTEXT "Level:",IDC_LLEVEL1,15,65,50,10 + EDITTEXT IDC_LEVEL,65,65,75,12,ES_AUTOHSCROLL + LTEXT "Ambient:",IDC_LAMBIENT2,15,125,50,10 + EDITTEXT IDC_AMBIENT2,65,125,75,12,ES_AUTOHSCROLL + LTEXT "Green:",IDC_LGREEN2,160,140,50,10 + EDITTEXT IDC_GREEN2,210,140,75,12,ES_AUTOHSCROLL + LTEXT "Red:",IDC_LRED2,160,125,50,10 + EDITTEXT IDC_RED2,210,125,75,12,ES_AUTOHSCROLL + LTEXT "Blue:",IDC_LBLUE2,160,155,50,10 + EDITTEXT IDC_BLUE2,210,155,75,12,ES_AUTOHSCROLL + LTEXT "Level:",IDC_LLEVEL2,15,140,50,10 + EDITTEXT IDC_LEVEL2,65,140,75,12,ES_AUTOHSCROLL +END + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_INFO$(TS_MODE) DIALOGEX 0, 0, 349, 250 +#else +IDD_INFO DIALOGEX 0, 0, 349, 250 +#endif +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Info" +FONT 8, "Tahoma", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,292,8,50,14 + LTEXT "© 1999-2024 ELECTRONIC ARTS INC. ALL RIGHTS RESERVED\nWestwood Studios(tm) is an Electronic Arts(tm) brand.",IDC_STATIC,7,189,334,18 + LTEXT "© 1999-2024 Electronic Arts Inc. Westwood Studios and Electronic Arts are trademarks or registered trademarks of Electronic Arts Inc. in the U.S. and/or other countries. All rights reserved.",IDC_STATIC,7,214,335,28 + EDITTEXT IDC_LICENSE_AND_COPYRIGHT,6,29,336,148,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL +END +#endif + +IDD_SPECIALFLAGS DIALOG 0, 0, 303, 137 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Special Flags" +FONT 8, "Tahoma" +BEGIN + LTEXT "Tiberium grows:",IDC_LTIBERIUMGROWS,5,22,75,10 + COMBOBOX IDC_TIBERIUMGROWS,85,22,45,45,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Tiberium spreads:",IDC_LTIBERIUMSPREADS,5,37,75,10 + COMBOBOX IDC_TIBERIUMSPREADS,85,37,45,45,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Tiberium explosive:",IDC_LTIBERIUMEXPLOSIVE,5,52,75,10 + COMBOBOX IDC_TIBERIUMEXPLOSIVE,85,52,45,45,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Destroyable bridges:",IDC_LDESTROYABLEBRIDGES,5,67,75,10 + COMBOBOX IDC_DESTROYABLEBRIDGES,85,67,45,45,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "MCV deploy:",IDC_LMCVDEPLOY,5,82,75,10 + COMBOBOX IDC_MCVDEPLOY,85,82,45,45,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Initial veteran: (initial troops have veteran status)",IDC_LINITIALVETERAN,5,97,75,25 + COMBOBOX IDC_INITIALVETERAN,85,97,45,45,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Fixed alliance:",IDC_LFIXEDALLIANCE,165,22,75,10 + COMBOBOX IDC_FIXEDALLIANCE,245,22,45,45,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Harvester immune:",IDC_LHARVESTERIMMUNE,165,37,75,10 + COMBOBOX IDC_HARVESTERIMMUNE,245,37,45,45,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Fog of war:",IDC_LFOGOFWAR,165,52,75,10 + COMBOBOX IDC_FOGOFWAR,245,52,45,45,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Inert:",IDC_LINERT,165,67,75,10 + COMBOBOX IDC_INERT,245,67,45,45,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Ion storms:",IDC_LIONSTORMS,165,82,75,10 + COMBOBOX IDC_IONSTORMS,245,82,45,45,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Meteorites:",IDC_LMETEORITES,165,97,75,10 + COMBOBOX IDC_METEORITES,245,97,45,45,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Visceroids:",IDC_LVISCEROIDS,165,112,75,10 + COMBOBOX IDC_VISCEROIDS,245,112,45,45,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Some settings only work under certain circumstances.",IDC_DESC,5,5,285,16 +END + +IDD_INFANTRY DIALOG 0, 0, 232, 142 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Infantry options" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "OK",IDOK,175,121,50,14 + PUSHBUTTON "Cancel",IDCANCEL,117,121,50,14 + LTEXT "House:",IDC_LHOUSE,7,6,33,11 + COMBOBOX IDC_HOUSE,47,6,65,45,CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Strength:",IDC_LSTRENGTH,7,24,29,10 + CONTROL "Slider1",IDC_STRENGTH,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,47,24,70,11 + LTEXT "State:",IDC_LSTATE,7,42,40,13 + COMBOBOX IDC_STATE,47,42,65,90,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Tag:",IDC_LTAG,7,100,68,19 + COMBOBOX IDC_TAG,79,102,142,69,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Param1:",IDC_LP1,120,6,35,15 + EDITTEXT IDC_P1,155,6,65,12,ES_AUTOHSCROLL + LTEXT "Param2:",IDC_LP2,120,24,32,16 + LTEXT "Param3:",IDC_LP3,120,42,32,16 + LTEXT "Param4:",IDC_LP4,120,60,36,17 + EDITTEXT IDC_P2,155,24,65,12,ES_AUTOHSCROLL + EDITTEXT IDC_P3,155,42,65,12,ES_AUTOHSCROLL + EDITTEXT IDC_P4,155,60,65,12,ES_AUTOHSCROLL + LTEXT "",IDC_LDESC,0,133,38,8 + LTEXT "Direction:",IDC_LDIRECTION,7,60,40,10 + COMBOBOX IDC_DIRECTION,47,60,65,69,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Param5:",IDC_LP5,120,78,34,19 + EDITTEXT IDC_P5,155,78,65,12,ES_AUTOHSCROLL +END + +IDD_HOUSES DIALOG 0, 0, 303, 207 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Houses" +FONT 8, "Tahoma" +BEGIN + LTEXT "DESC [quite long]",IDC_DESC,7,5,290,43 + COMBOBOX IDC_HOUSES,77,65,220,125,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "House:",IDC_LHOUSE,7,65,64,22 + PUSHBUTTON "Add house",IDC_ADDHOUSE,227,82,70,15 + PUSHBUTTON "Standard houses",IDC_PREPAREHOUSES,75,82,70,15 + PUSHBUTTON "Delete house",IDC_DELETEHOUSE,150,82,70,15 + LTEXT "IQ:",IDC_LIQ,10,105,40,10 + COMBOBOX IDC_IQ,55,105,70,70,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Edge:",IDC_LEDGE,10,120,40,10 + COMBOBOX IDC_EDGE,55,120,70,65,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Side",IDC_LSIDE,10,135,40,10 + COMBOBOX IDC_SIDE,55,135,70,65,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Color",IDC_LCOLOR,10,150,40,10 + COMBOBOX IDC_COLOR,55,150,70,150,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Allies:",IDC_LALLIES,10,165,40,10 + EDITTEXT IDC_ALLIES,55,165,70,12,ES_AUTOHSCROLL + LTEXT "Credits (x100):",IDC_LCREDITS,10,181,40,17 + EDITTEXT IDC_CREDITS,55,179,70,12,ES_AUTOHSCROLL + LTEXT "Acts like:",IDC_LACTSLIKE,150,105,69,14 + COMBOBOX IDC_ACTSLIKE,227,105,70,50,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Nodecount:",IDC_LNODECOUNT,150,119,68,15 + COMBOBOX IDC_NODECOUNT,227,120,70,50,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Techlevel:",IDC_LTECHLEVEL,150,134,63,10 + COMBOBOX IDC_TECHLEVEL,227,135,70,135,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + LTEXT "Build activity (%):",IDC_LBUILDACTIVITY,150,150,66,17 + COMBOBOX IDC_PERCENTBUILT,227,150,70,50,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Player control:",IDC_LPLAYERCONTROL,150,166,70,20 + COMBOBOX IDC_PLAYERCONTROL,227,166,70,50,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Human Player:",IDC_LPLAYER,7,48,65,16 + COMBOBOX IDC_HUMANPLAYER,77,49,220,70,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + GROUPBOX "",IDC_STATIC,6,98,293,102 +END + +IDD_AIRCRAFT DIALOG 0, 0, 232, 130 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Aircraft Options" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,170,110,50,14 + PUSHBUTTON "Cancel",IDCANCEL,110,110,50,14 + CONTROL "House:",IDC_LHOUSE,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,5,7,33,11 + COMBOBOX IDC_HOUSE,45,7,65,45,CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Strength:",IDC_LSTRENGTH,5,25,29,10 + CONTROL "Slider1",IDC_STRENGTH,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,45,25,70,11 + LTEXT "State:",IDC_LSTATE,5,62,40,10 + COMBOBOX IDC_STATE,45,62,65,90,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Tag:",IDC_LTAG,5,90,66,14 + COMBOBOX IDC_TAG,77,90,144,69,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Param1:",IDC_LP1,116,7,40,17 + EDITTEXT IDC_P1,155,7,65,12,ES_AUTOHSCROLL + LTEXT "Param2:",IDC_LP2,116,25,37,12 + LTEXT "Recruitable:",IDC_LP3,116,43,39,15 + LTEXT "Param4:",IDC_LP4,116,62,39,18 + EDITTEXT IDC_P2,155,25,65,12,ES_AUTOHSCROLL + EDITTEXT IDC_P4,155,62,65,12,ES_AUTOHSCROLL + LTEXT "Params are unknown (integers?).",IDC_LDESC,5,120,19,10 + LTEXT "Direction:",IDC_LDIRECTION,5,43,40,10 + COMBOBOX IDC_DIRECTION,45,43,65,63,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_P3,155,43,66,62,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP +END + +IDD_BUILDING DIALOG 0, 0, 247, 190 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_CAPTION | WS_SYSMENU +CAPTION "Building options" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "OK",IDOK,190,170,50,14 + PUSHBUTTON "Cancel",IDCANCEL,131,170,50,14 + LTEXT "House:",IDC_LHOUSE,7,41,33,11 + COMBOBOX IDC_HOUSE,47,41,65,45,CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Strength:",IDC_LSTRENGTH,7,57,29,10 + CONTROL "Slider1",IDC_STRENGTH,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,47,56,69,11 + LTEXT "Tag:",IDC_LTAG,7,149,39,15 + COMBOBOX IDC_TAG,47,149,193,69,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Param1:",IDC_LP1,7,87,35,13 + EDITTEXT IDC_P1,47,87,65,12,ES_AUTOHSCROLL + LTEXT "AI repairs:",IDC_LAIREPAIRS,7,102,40,14 + LTEXT "Energy:",IDC_LENERGY,7,117,38,18 + LTEXT "Upgrade count:",IDC_LUPGRADECOUNT,119,40,30,17 + LTEXT "Params are unknown (some integers, some strings?). Note: 0 means no, 1 means yes",IDC_LDESC,5,5,235,36 + LTEXT "Direction:",IDC_LDIRECTION,7,71,40,14 + COMBOBOX IDC_DIRECTION,47,71,65,58,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Spotlight:",IDC_LSPOTLIGHT,119,57,39,15 + LTEXT "Upgrade 1:",IDC_LUPGRADE1,119,72,40,14 + COMBOBOX IDC_P6,164,71,77,71,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Upgrade 2:",IDC_LUPGRADE2,119,87,40,16 + COMBOBOX IDC_P7,164,86,77,84,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Upgrade 3:",IDC_LUPGRADE3,119,102,38,15 + COMBOBOX IDC_P8,164,101,77,89,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Param 2:",IDC_LP2,120,117,35,10 + LTEXT "Show name:",IDC_LP3,120,132,40,10 + COMBOBOX IDC_P3,47,118,65,69,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_P2,47,102,65,41,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_P4,164,41,77,53,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_P5,164,56,77,79,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_P9,164,116,77,41,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_P10,164,132,77,41,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP +END + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_LOADING$(TS_MODE) DIALOGEX 0, 0, 235, 165 +#else +IDD_LOADING DIALOGEX 0, 0, 235, 165 +#endif +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP +FONT 8, "Tahoma", 0, 0, 0x1 +BEGIN + LTEXT "Loading...",IDC_CAP,7,7,221,9 + CONTROL "",IDC_PROGRESS1,"msctls_progress32",PBS_SMOOTH,7,18,221,13,WS_EX_DLGMODALFRAME + LTEXT "Homepage: http://www.ea.com",IDC_STATIC,7,78,221,11,WS_BORDER + CTEXT "",IDC_VERSION,74,37,154,13,SS_CENTERIMAGE | SS_SUNKEN + LTEXT "Version:",IDC_LVERSION,7,37,61,9 + CTEXT "",IDC_BUILTBY,74,52,154,13,SS_CENTERIMAGE | SS_SUNKEN + LTEXT "Built by:",IDC_LBUILTBY,7,52,61,9 + LTEXT "© 1999-2024 ELECTRONIC ARTS INC. ALL RIGHTS RESERVED\nAuthored by Matthias Wagner\nWestwood Studios(tm) is an Electronic Arts(tm) brand.",IDC_STATIC,7,97,221,33 + LTEXT "This software comes with ABSOLUTELY NO WARRANTY.\nThis is free software, and you are welcome to redistribute it.\nFor details open Help->Info",IDC_STATIC,6,129,221,26 +END +#endif + +IDD_WAYPOINT DIALOG 0, 0, 186, 93 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Create waypoint" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "OK",IDOK,129,72,50,14 + PUSHBUTTON "Cancel",IDCANCEL,70,72,50,14 + LTEXT "Enter the waypoint number (note that it may already exist and be overwritten!). Or use ""Get free number"".",IDC_DESC,7,7,172,27 + EDITTEXT IDC_ID,7,45,67,16,ES_AUTOHSCROLL + LTEXT "ID:",IDC_LID,7,34,78,10 + PUSHBUTTON "Get first free number",IDC_FREE,86,45,93,16 +END + +IDD_CELLTAG DIALOG 0, 0, 212, 77 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Cell-Tag" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "OK",IDOK,155,56,50,14 + PUSHBUTTON "Cancel",IDCANCEL,95,56,50,14 + LTEXT "Tag:",IDC_LTAG,7,29,82,8 + COMBOBOX IDC_TAG,7,37,198,114,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + LTEXT "Associate a tag with a specific cell.",IDC_LDESC,7,7,198,19 +END + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_TEAMTYPES$(TS_MODE) DIALOG 0, 0, 303, 206 +#else +IDD_TEAMTYPES DIALOG 0, 0, 303, 206 +#endif +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Teamtypes" +FONT 8, "Tahoma" +BEGIN + LTEXT "Team types connect a trigger with task forces",IDC_STATIC,6,5,290,10 + LTEXT "Team types:",IDC_STATIC,5,20,50,10 + COMBOBOX IDC_TEAMTYPES,55,20,155,174,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "New",IDC_NEWTEAMTYPE,261,20,35,15 + PUSHBUTTON "Delete",IDC_DELETETEAMTYPE,220,20,35,15 + LTEXT "Name:",IDC_STATIC,10,51,30,10 + EDITTEXT IDC_NAME,56,51,90,12,ES_AUTOHSCROLL + LTEXT "Veteran level:",IDC_STATIC,10,66,45,15 + CONTROL "Loadable",IDC_LOADABLE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,10,145,55,8 + CONTROL "Full",IDC_FULL,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,10,155,55,8 + CONTROL "Annoyance",IDC_ANNOYANCE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,10,164,55,10 + CONTROL "Guard slower",IDC_GUARDSLOWER,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,10,175,55,8 + CONTROL "Recruiter",IDC_RECRUITER,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,10,185,55,8 + LTEXT "House:",IDC_STATIC,10,81,35,10 + COMBOBOX IDC_HOUSE,56,81,90,62,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + CONTROL "Autocreate",IDC_AUTOCREATE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,125,145,55,8 + CONTROL "Prebuild",IDC_PREBUILD,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,125,155,55,8 + CONTROL "Reinforce",IDC_REINFORCE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,125,165,55,8 + CONTROL "Droppod",IDC_DROPPOD,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,65,145,55,8 + CONTROL "Whiner",IDC_WHINER,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,65,155,55,8 + CONTROL "Loose recruit",IDC_LOOSERECRUIT,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,65,165,55,8 + CONTROL "Aggressive",IDC_AGGRESSIVE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,65,175,55,8 + CONTROL "Suicide",IDC_SUICIDE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,65,185,55,8 + CONTROL "OnTransOnly",IDC_ONTRANSONLY,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,125,175,55,8 + CONTROL "AvoidThreats",IDC_AVOIDTHREATS,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,125,185,55,8 + CONTROL "Ion immune",IDC_IONIMMUNE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,185,145,60,8 + CONTROL "TransportsReturnOnUnload",IDC_TRANSPORTRETURNSONUNLOAD, + "Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,185,155,100,8 + CONTROL "AreTeamMembersRecruitable",IDC_ARETEAMMEMBERSRECRUITABLE, + "Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,185,165,105,8 + CONTROL "IsBaseDefense",IDC_ISBASEDEFENSE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,185,175,80,8 + CONTROL "OnlyTargetHouseEnemy",IDC_ONLYTARGETHOUSEENEMY,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,185,185,100,8 + LTEXT "Priority:",IDC_STATIC,10,96,40,10 + EDITTEXT IDC_PRIORITY,56,96,90,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Max:",IDC_STATIC,10,111,30,10 + EDITTEXT IDC_MAX,56,111,90,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Techlevel:",IDC_STATIC,10,125,40,10 + COMBOBOX IDC_TECHLEVEL,56,125,91,72,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Group:",IDC_STATIC,156,51,30,10 + GROUPBOX "Selected team type",IDC_STATIC,6,37,290,161 + COMBOBOX IDC_GROUP,200,51,90,78,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Waypoint:",IDC_STATIC,156,66,40,10 + COMBOBOX IDC_WAYPOINT,200,66,90,80,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Script:",IDC_STATIC,156,81,40,10 + COMBOBOX IDC_SCRIPT,200,81,90,205,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Task force:",IDC_STATIC,156,96,40,10 + COMBOBOX IDC_TASKFORCE,200,96,90,205,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_VETERANLEVEL,56,66,90,60,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Tag:",IDC_STATIC,156,111,40,13 + COMBOBOX IDC_TAG,200,111,90,186,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + LTEXT "",IDC_LTRANSPORTWAYPOINT,156,126,40,17 + COMBOBOX IDC_TRANSPORTWAYPOINT,200,126,90,80,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Mind Control Decision:",IDC_STATIC,164,4,43,16,NOT WS_VISIBLE + COMBOBOX IDC_MINDCONTROLDECISION,209,6,92,205,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP + LTEXT "Mind Control Decision:",IDC_MCD_L,10,139,43,16,NOT WS_VISIBLE +END +#endif + +IDD_TASKFORCES DIALOG 0, 0, 303, 205 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Taskforces" +FONT 8, "Tahoma" +BEGIN + LTEXT "Task forces:",IDC_STATIC,7,7,71,10 + COMBOBOX IDC_TASKFORCES,87,7,199,130,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Units in task force:",IDC_STATIC,17,88,61,13 + LISTBOX IDC_UNITS,87,88,199,68,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Add",IDC_ADDUNIT,17,102,61,14 + PUSHBUTTON "Delete",IDC_DELETEUNIT,17,121,61,15 + LTEXT "Group:",IDC_STATIC,17,69,61,13 + EDITTEXT IDC_GROUP,87,69,199,13,ES_AUTOHSCROLL + LTEXT "Number of units:",IDC_STATIC,16,160,62,12 + EDITTEXT IDC_NUMBERUNITS,87,160,199,14,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Unit type:",IDC_STATIC,17,179,62,12 + COMBOBOX IDC_UNITTYPE,87,179,199,183,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Selected task force",IDC_STATIC,7,45,290,153 + PUSHBUTTON "Delete",IDC_DELETETASKFORCE,222,23,64,15 + PUSHBUTTON "Add",IDC_ADDTASKFORCE,153,23,64,15 + LTEXT "Name:",IDC_STATIC,17,56,61,12 + EDITTEXT IDC_NAME,87,54,199,13,ES_AUTOHSCROLL +END + +IDD_TAGS DIALOG 0, 0, 303, 204 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Tags" +FONT 8, "Tahoma" +BEGIN + LTEXT "Tags make Triggers work. Without a tag, a trigger is usually useless, because it won't be executed (except if another triggers fires it directly).",IDC_STATIC,7,7,290,20 + LTEXT "Tag:",IDC_STATIC,7,36,54,12 + COMBOBOX IDC_TAG,61,37,236,196,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Add",IDC_ADD,169,53,59,14 + PUSHBUTTON "Delete",IDC_DELETE,238,53,59,14 + LTEXT "Name:",IDC_STATIC,7,90,54,12 + EDITTEXT IDC_NAME,61,89,236,13,ES_AUTOHSCROLL + LTEXT "Repeat:",IDC_STATIC,7,110,54,13 + COMBOBOX IDC_REPEAT,61,110,236,59,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Trigger:",IDC_STATIC,7,131,54,13 + COMBOBOX IDC_TRIGGER,61,131,236,135,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + LTEXT "For every trigger you create, you should create a tag to make the trigger work. A trigger consists of some general properties, an event and an action, which can all be defined in the ""trigger"" section.",IDC_STATIC,7,167,290,30 +END + +IDD_TRIGGERS DIALOG 0, 0, 303, 204 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Old Trigger Editor - UNUSED" +FONT 8, "Tahoma" +BEGIN + LTEXT "Trigger:",IDC_STATIC,7,7,26,11 + COMBOBOX IDC_TRIGGER,37,7,120,122,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "House:",IDC_STATIC,7,25,28,12 + COMBOBOX IDC_HOUSE,38,25,60,100,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "New trigger",IDC_ADDTRIGGER,165,7,61,14 + PUSHBUTTON "Delete trigger",IDC_DELETETRIGGER,234,7,63,14 + LTEXT "Name:",IDC_STATIC,109,26,24,12 + EDITTEXT IDC_NAME,135,25,162,13,ES_AUTOHSCROLL + LTEXT "Flags:",IDC_STATIC,7,41,19,13 + EDITTEXT IDC_FLAG1,37,41,24,13,ES_AUTOHSCROLL + EDITTEXT IDC_FLAG2,65,41,23,13,ES_AUTOHSCROLL + EDITTEXT IDC_FLAG3,92,41,23,13,ES_AUTOHSCROLL + EDITTEXT IDC_FLAG4,119,41,23,13,ES_AUTOHSCROLL + EDITTEXT IDC_FLAG5,146,41,23,13,ES_AUTOHSCROLL + GROUPBOX "Events which let the trigger start",IDC_STATIC,7,56,290,59 + GROUPBOX "Actions - What the trigger will do",IDC_STATIC,7,120,290,77 + LTEXT "Event:",IDC_STATIC,13,65,29,11 + COMBOBOX IDC_EVENT,57,66,123,68,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Add",IDC_ADDEVENT,185,65,49,15 + PUSHBUTTON "Delete",IDC_DELETEEVENT,239,65,49,15 + LTEXT "Parameter 1:",IDC_LABEL_E1,13,97,44,16 + COMBOBOX IDC_EVENTPARAM1,57,97,86,160,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Parameter 2:",IDC_LABEL_E2,149,97,44,16 + COMBOBOX IDC_EVENTPARAM2,198,98,90,172,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_ACTION,45,131,134,68,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Add",IDC_ADDACTION,185,130,49,15 + PUSHBUTTON "Delete",IDC_DELETEACTION,239,130,49,15 + LTEXT "Action:",IDC_STATIC,14,131,24,13 + LTEXT "Type:",IDC_STATIC,13,82,44,12 + COMBOBOX IDC_EVENTTYPE,57,82,230,98,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Param1:",IDC_LABEL_A1,13,163,30,14 + COMBOBOX IDC_ACTIONPARAM1,45,163,48,219,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Type:",IDC_STATIC,13,148,23,12 + COMBOBOX IDC_ACTIONTYPE,45,148,172,133,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Param2:",IDC_LABEL_A2,96,163,30,15 + COMBOBOX IDC_ACTIONPARAM2,127,163,74,289,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Param3:",IDC_LABEL_A3,203,162,30,14 + COMBOBOX IDC_ACTIONPARAM3,234,163,56,243,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Param4:",IDC_LABEL_A4,13,177,30,15 + COMBOBOX IDC_ACTIONPARAM4,45,176,48,204,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Param5:",IDC_LABEL_A5,96,178,30,14 + COMBOBOX IDC_ACTIONPARAM5,127,176,74,221,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Param6:",IDC_LABEL_A6,203,176,30,16 + COMBOBOX IDC_ACTIONPARAM6,234,176,56,239,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Waypoint:",IDC_WAYPOINT,221,148,33,11 + COMBOBOX IDC_ACTIONWAYPOINT,257,148,32,133,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + LTEXT "Trigger??? :",IDC_STATIC,177,42,37,12 + COMBOBOX IDC_TRIGGER2,221,42,76,152,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP +END + +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_AITRIGGERTYPES$(RA2_MODE) DIALOG 0, 0, 303, 234 +#else +IDD_AITRIGGERTYPES DIALOG 0, 0, 303, 234 +#endif +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "AI Trigger Types" +FONT 8, "Tahoma" +BEGIN + LTEXT "AI Trigger:",IDC_STATIC,7,7,43,11 + COMBOBOX IDC_AITRIGGERTYPE,60,7,236,307,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Name:",IDC_STATIC,7,63,43,11 + EDITTEXT IDC_NAME,60,64,94,13,ES_AUTOHSCROLL + LTEXT "Teamtype #1:",IDC_STATIC,7,80,43,17 + COMBOBOX IDC_TEAMTYPE1,60,81,236,81,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "House:",IDC_STATIC,165,64,50,16 + COMBOBOX IDC_OWNER,220,64,76,207,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + LTEXT "Teamtype #2:",IDC_STATIC,7,98,43,17 + COMBOBOX IDC_TEAMTYPE2,60,98,235,81,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Techlevel:",IDC_STATIC,280,206,8,11,NOT WS_VISIBLE + COMBOBOX IDC_FLAG1,288,222,16,56,CBS_DROPDOWN | NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP + LTEXT "Type:",IDC_STATIC,6,44,53,17 + COMBOBOX IDC_FLAG2,60,45,235,71,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Data:",IDC_DATALABEL,265,204,8,13,NOT WS_VISIBLE + COMBOBOX IDC_DATA,287,222,16,128,CBS_DROPDOWN | CBS_AUTOHSCROLL | NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP + LTEXT "Weight:",IDC_STATIC,6,150,33,11 + EDITTEXT IDC_FLOAT1,59,148,56,13,ES_AUTOHSCROLL + LTEXT "MinWeight:",IDC_STATIC,6,165,38,11 + EDITTEXT IDC_FLOAT2,59,164,56,13,ES_AUTOHSCROLL + LTEXT "MaxWeight:",IDC_STATIC,125,165,40,11 + EDITTEXT IDC_FLOAT3,180,164,54,13,ES_AUTOHSCROLL + LTEXT "MinDiff:",IDC_STATIC,279,222,8,12,NOT WS_VISIBLE + EDITTEXT IDC_FLAG4,291,222,8,12,ES_AUTOHSCROLL | NOT WS_VISIBLE + LTEXT "Multi-Side:",IDC_STATIC,7,115,33,12 + PUSHBUTTON "Delete",IDC_DELETE,220,23,76,13 + PUSHBUTTON "Add",IDC_ADD,140,23,74,13 + CONTROL "Enabled",IDC_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,60,23,76,11 + CONTROL "Easy",IDC_EASY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,133,42,13 + CONTROL "Medium",IDC_MEDIUM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,124,132,42,13 + CONTROL "Hard",IDC_HARD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,199,132,42,13 + CONTROL "Base defense",IDC_BASEDEFENSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,124,116,67,13 + CONTROL "Available in Skirmish",IDC_SKIRMISH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,199,116,85,14 + COMBOBOX IDC_MULTISIDE,60,116,56,63,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + LTEXT "Unittype (X):",IDC_STATIC,171,200,51,10 + COMBOBOX IDC_UNITTYPE,171,212,125,255,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + LTEXT "Condition:",IDC_STATIC,8,200,50,11 + COMBOBOX IDC_CONDITION,8,212,95,82,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + EDITTEXT IDC_NUMBER,109,212,54,13,ES_AUTOHSCROLL + LTEXT "Number (N):",IDC_STATIC,110,200,56,11 + LTEXT "Additional parameters for the appropiate AI Trigger Types:",IDC_STATIC,6,188,295,12 +END +#endif + +IDD_NEWMAP DIALOG 0, 0, 248, 226 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "New map assistant" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "OK",IDOK,191,205,50,14 + PUSHBUTTON "Cancel",IDCANCEL,134,205,50,14 + PUSHBUTTON "Browse",IDC_BROWSE,189,106,44,12 + GROUPBOX "Import options",IDC_LIMPORTOPTIONS,7,93,234,64 + CONTROL "Import Trees",IDC_IMPORTTREES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,125,91,12 + CONTROL "Import Overlay",IDC_IMPORTOVERLAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,138,103,13 + CONTROL "Import Units/Buildings",IDC_IMPORTUNITS,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,128,122,94,19 + CONTROL "Multiplayer",IDC_MULTIPLAYER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,167,85,12 + COMBOBOX IDC_IMPORTFILE,15,106,161,206,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + CONTROL "Prepare standard houses",IDC_PREPAREHOUSES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,120,167,113,13 + COMBOBOX IDC_HOUSE,177,183,56,99,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Player house:",IDC_LPLAYERHOUSE,119,183,52,15 + CONTROL "Set Auto-Production triggers",IDC_AUTOPROD,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,7,178,102,19 + CONTROL "Import existing map",IDC_IMPORT,"Button",BS_AUTORADIOBUTTON | WS_GROUP,7,81,234,11 + CONTROL "Create new map",IDC_NEW,"Button",BS_AUTORADIOBUTTON,7,8,234,15 + GROUPBOX "New map options",IDC_STATIC,7,21,234,51 + EDITTEXT IDC_WIDTH,51,31,51,14,ES_AUTOHSCROLL + LTEXT "Width:",IDC_STATIC,13,31,33,14 + EDITTEXT IDC_HEIGHT,178,31,51,14,ES_AUTOHSCROLL + LTEXT "Height:",IDC_STATIC,130,31,41,14 + LTEXT "Theater:",IDC_STATIC,13,49,38,12 + COMBOBOX IDC_THEATER,51,49,68,71,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Ground height:",IDC_STATIC,130,50,47,16 + COMBOBOX IDC_GROUNDHEIGHT,178,50,52,71,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP +END + +IDD_BASIC DIALOG 0, 0, 303, 208 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Basic Settings" +FONT 8, "Tahoma" +BEGIN + LTEXT "Note: some of the settings are probably just ignored",IDC_LDESC,5,7,290,10 + LTEXT "Next scenario:",IDC_LNEXTSCENARIO,5,35,60,15 + LTEXT "Alt. next scenario:",IDC_LALTNEXTSCENARIO,5,51,60,15 + LTEXT "Name:",IDC_LNAME,5,20,60,15 + EDITTEXT IDC_NAME,70,20,70,12,ES_AUTOHSCROLL + LTEXT "New INI format:",IDC_LNEWINIFORMAT,5,67,60,15 + EDITTEXT IDC_NEWINIFORMAT,70,67,70,12,ES_AUTOHSCROLL | ES_READONLY + LTEXT "CarryOverCap:",IDC_LCARRYOVERCAP,5,83,60,15 + EDITTEXT IDC_CARRYOVERCAP,70,83,70,12,ES_AUTOHSCROLL + LTEXT "EndOfGame",IDC_LENDOFGAME,5,100,60,15 + COMBOBOX IDC_ENDOFGAME,70,99,70,45,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_NEXTSCENARIO,70,35,70,40,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_ALTNEXTSCENARIO,70,51,70,40,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Skip Score:",IDC_LSKIPSCORE,5,115,60,15 + COMBOBOX IDC_SKIPSCORE,70,115,70,45,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "One Time Only:",IDC_LONETIMEONLY,5,130,60,15 + COMBOBOX IDC_ONETIMEONLY,70,131,70,40,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Skip map select:",IDC_LSKIPMAPSELECT,5,146,60,15 + COMBOBOX IDC_SKIPMAPSELECT,70,147,70,40,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Official",IDC_LOFFICIAL,5,163,60,15 + COMBOBOX IDC_OFFICIAL,70,163,70,40,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Ignore global AI triggers",IDC_LIGNOREGLOBALAITRIGGERS,6,178,60,19 + COMBOBOX IDC_IGNOREGLOBALAITRIGGERS,70,179,70,40,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Truck crate:",IDC_LTRUCKCRATE,150,20,70,17 + COMBOBOX IDC_TRUCKCRATE,226,20,70,40,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Train crate:",IDC_LTRAINCRATE,150,35,70,16 + COMBOBOX IDC_TRAINCRATE,226,36,70,40,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Percent: (?)",IDC_LPERCENT,150,52,70,16 + EDITTEXT IDC_PERCENT,226,52,70,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Multiplayer Only:",IDC_LMULTIPLAYERONLY,150,67,70,16 + EDITTEXT IDC_MULTIPLAYERONLY,226,68,70,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Tiberium growth enabled:",IDC_LTIBERIUMGROWTHENABLED,150,83,70,15 + COMBOBOX IDC_TIBERIUMGROWTHENABLED,226,84,70,40,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Vein growth enabled:",IDC_LVEINGROWTHENABLED,150,99,70,15 + COMBOBOX IDC_VEINGROWTHENABLED,226,100,70,40,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Ice growth enabled:",IDC_LICEGROWTHENABLED,150,115,70,15 + COMBOBOX IDC_ICEGROWTHENABLED,226,116,70,40,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Tiberium death to visceroid:",IDC_LTIBERIUMDEATHTOVISCEROID,150,131,70,15 + COMBOBOX IDC_TIBERIUMDEATHTOVISCEROID,226,132,70,40,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Free radar:",IDC_LFREERADAR,150,147,70,10 + COMBOBOX IDC_FREERADAR,226,148,70,40,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Init time:",IDC_LINITIME,150,164,70,10 + EDITTEXT IDC_INITTIME,226,164,70,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Required add on:",IDC_LADDONNEEDED,150,179,68,20 + COMBOBOX IDC_REQUIREDADDON,226,179,70,40,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP +END + +IDD_SINGLEPLAYER DIALOG 0, 0, 303, 207 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Singleplayer Map Settings" +FONT 8, "Tahoma" +BEGIN + LTEXT "Movies && other singleplayer stuff.",IDC_DESC,7,7,289,16 + GROUPBOX "Movies",IDC_LMOVIES,7,117,289,81 + LTEXT "Intro:",IDC_LINTRO,15,128,59,18 + COMBOBOX IDC_INTRO,75,128,68,161,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Brief:",IDC_LBRIEF,15,144,59,18 + COMBOBOX IDC_BRIEF,75,144,68,202,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Win:",IDC_LWIN,15,160,59,18 + COMBOBOX IDC_WIN,75,160,68,185,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Lose:",IDC_LLOSE,14,177,59,15 + COMBOBOX IDC_LOSE,75,176,68,203,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Action:",IDC_LACTION,154,128,59,18 + COMBOBOX IDC_ACTION,216,128,68,160,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "PostScore:",IDC_LPOSTSCORE,153,144,59,18 + COMBOBOX IDC_POSTSCORE,216,144,68,196,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "PreMapSelect:",IDC_LPREMAPSELECT,153,160,59,18 + COMBOBOX IDC_PREMAPSELECT,216,160,68,225,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Starting dropships:",IDC_LSTARTINGDROPSHIPS,7,23,67,16 + COMBOBOX IDC_STARTINGDROPSHIPS,75,23,68,161,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Carry over money (percent):",IDC_LCARRYOVERMONEY,7,40,67,16 + EDITTEXT IDC_CARRYOVERMONEY,75,41,67,14,ES_AUTOHSCROLL + LTEXT "Inherit timer:",IDC_LINHERITTIMER,7,61,67,16 + COMBOBOX IDC_TIMERINHERIT,75,61,68,161,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Fill silos:",IDC_LFILLSILOS,7,79,67,16 + COMBOBOX IDC_FILLSILOS,75,79,68,161,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP +END + +IDD_MAPVALIDATOR DIALOGEX 0, 0, 440, 225 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION +CAPTION "Map-Validator" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,383,205,50,14 + PUSHBUTTON "Cancel",IDCANCEL,322,205,50,14 + LTEXT "These possible problems were found:",IDC_LPROBLEMSFOUND,7,7,225,14 + CONTROL "List1",IDC_MAPPROBLEMS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,6,21,427,144 +END + +IDD_SCRIPTTYPES DIALOG 0, 0, 302, 230 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Scripts" +FONT 8, "Tahoma" +BEGIN + LTEXT "Scripttypes let you, for example, define that a team moves from one point to another. A scripttype is attached to a TeamType (not a TaskForce!)",IDC_STATIC,7,7,288,20 + LTEXT "Scripttype",IDC_STATIC,7,31,65,12 + COMBOBOX IDC_SCRIPTTYPE,72,32,223,196,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Add",IDC_ADD,169,49,59,14 + PUSHBUTTON "Delete",IDC_DELETE,236,49,59,14 + LTEXT "Name:",IDC_STATIC,7,74,65,12 + EDITTEXT IDC_NAME,72,74,223,13,ES_AUTOHSCROLL + LTEXT "Actions:",IDC_STATIC,7,92,65,11 + LISTBOX IDC_ACTION,72,92,223,45,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LTEXT "Type of action:",IDC_STATIC,7,160,65,12 + LTEXT "Parameter of action:",IDC_PDESC,7,180,65,17 + COMBOBOX IDC_TYPE,72,161,223,192,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_PARAM,72,180,223,111,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Delete",IDC_DELETEACTION,235,140,60,14 + PUSHBUTTON "Add",IDC_ADDACTION,168,140,60,14 + LTEXT "Description:",IDC_STATIC,7,201,62,13 + EDITTEXT IDC_DESCRIPTION,72,201,221,24,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | WS_VSCROLL +END + +IDD_AITRIGGERTYPESENABLE DIALOG 0, 0, 303, 204 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "AI Trigger Types Enable" +FONT 8, "Tahoma" +BEGIN + LTEXT "This allows the AI for example to create teams automatically. You simply specify which AITriggerTypes are enabled.",IDC_STATIC,7,7,287,23 + LTEXT "AITriggerType:",IDC_STATIC,7,62,60,13 + COMBOBOX IDC_AITRIGGERTYPE,71,62,223,281,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Enable all standard AI triggers (recommended)",IDC_ENABLEALL,7,30,160,14 + PUSHBUTTON "Delete = Disable AITrigger",IDC_DELETE,192,81,102,15 + PUSHBUTTON "Add = Enable AITrigger",IDC_ADD,85,81,102,15 +END + +IDD_TERRAINBAR DIALOG 0, 0, 387, 29 +STYLE DS_SETFONT | WS_CHILD +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Terrain / Ground:",IDC_STATIC,7,7,32,20 + COMBOBOX IDC_TILESET,42,7,141,169,CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Overlay && Special:",IDC_STATIC,204,7,32,20 + COMBOBOX IDC_OVERLAY,239,7,141,169,CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP +END + +IDD_TOOLSETTINGS DIALOGEX 0, 0, 116, 17 +STYLE DS_SETFONT | WS_CHILD +EXSTYLE WS_EX_TRANSPARENT +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + LTEXT "Brush size:",IDC_STATIC,7,3,46,11,SS_CENTERIMAGE,WS_EX_TRANSPARENT + COMBOBOX IDC_BRUSHSIZE,58,1,51,79,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP +END + +IDD_SHUTDOWN DIALOG 0, 0, 186, 35 +STYLE DS_SETFONT | DS_CENTER | WS_POPUP | WS_CAPTION +CAPTION "Shutdown" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Shutting down, please wait a few seconds",IDC_STATIC,7,14,172,13 +END + +IDD_DYNAMICLOAD DIALOG 0, 0, 220, 44 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_CAPTION +CAPTION "Loading" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Loading graphics, please wait a few seconds.",IDC_STATIC,7,7,206,15 + CONTROL "Progress4",IDC_PROGRESS,"msctls_progress32",PBS_SMOOTH | WS_BORDER,7,22,206,15 +END + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_SAVING$(TS_MODE) DIALOG 0, 0, 263, 46 +#else +IDD_SAVING DIALOG 0, 0, 263, 46 +#endif +STYLE DS_SETFONT | DS_CENTER | WS_POPUP | WS_CAPTION +CAPTION "Saving" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Please wait a few seconds while FinalSun is saving. On very large maps this may even take some minutes, please do not cancel! More information is available in the status bar, most time will be needed for packing.",IDC_STATIC,7,7,249,32 +END +#endif + +IDD_TRIGGEREDITOR DIALOGEX 0, 0, 389, 263 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_TOOLWINDOW +CAPTION "Trigger editor" +FONT 8, "Tahoma", 0, 0, 0x1 +BEGIN + LTEXT "Select current trigger:",IDC_STATIC,7,7,80,10 + PUSHBUTTON "New trigger",IDC_NEWTRIGGER,180,7,60,14 + PUSHBUTTON "Delete trigger",IDC_DELETETRIGGER,254,7,60,14 + COMBOBOX IDC_TRIGGER,7,26,307,165,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + CONTROL "Tab3",IDC_TRIGGERTAB,"SysTabControl32",TCS_HOTTRACK | TCS_TOOLTIPS,7,44,377,214,WS_EX_TRANSPARENT + PUSHBUTTON "Place on map",IDC_PLACEONMAP,324,7,60,14 + PUSHBUTTON "Clone trigger",IDC_CLONE,324,24,60,14 +END + +IDD_TRIGGEROPTIONS DIALOGEX 0, 0, 365, 204 +STYLE DS_SETFONT | WS_CHILD +FONT 8, "Tahoma", 0, 0, 0x0 +BEGIN + LTEXT "Type (modifies all attached Tags!):",IDC_STATIC,231,30,125,9 + COMBOBOX IDC_TRIGGERTYPE,231,41,125,71,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Name",IDC_STATIC,7,2,264,10 + EDITTEXT IDC_NAME,6,12,350,13,ES_AUTOHSCROLL + LTEXT "House:",IDC_STATIC,4,31,125,9 + COMBOBOX IDC_HOUSE,4,41,186,78,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Attached trigger:",IDC_STATIC,4,59,125,8 + COMBOBOX IDC_ATTACHEDTRIGGER,4,68,352,133,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + CONTROL "Disabled",IDC_DISABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,90,124,9 + LTEXT "Disabled triggers must be enabled using other triggers before they fire.",IDC_STATIC,4,102,260,9 + CONTROL "Easy",IDC_EASY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,115,58,13 + CONTROL "Medium",IDC_MEDIUM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,68,115,58,13 + CONTROL "Hard",IDC_HARD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,140,115,58,13 +END + +IDD_TRIGGEREVENTS DIALOGEX 0, 0, 365, 204 +STYLE DS_SETFONT | WS_CHILD +FONT 8, "Tahoma", 0, 0, 0x0 +BEGIN + LTEXT "Current event:",IDC_STATIC,6,6,64,11 + COMBOBOX IDC_EVENT,72,6,150,79,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "New event",IDC_NEWEVENT,233,6,61,14 + PUSHBUTTON "Delete event",IDC_DELETEEVENT,300,6,61,14 + GROUPBOX "Event options",IDC_STATIC,6,19,355,178 + LTEXT "Event type:",IDC_STATIC,14,32,57,12 + COMBOBOX IDC_EVENTTYPE,72,30,282,184,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + EDITTEXT IDC_EVENTDESCRIPTION,14,48,340,26,ES_MULTILINE | ES_READONLY | WS_VSCROLL + LTEXT "Event parameters:",IDC_STATIC,14,79,74,10 + LISTBOX IDC_PARAMETER,14,93,159,96,LBS_SORT | LBS_USETABSTOPS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP + LTEXT "Parameter value:",IDC_STATIC,185,79,118,10 + COMBOBOX IDC_PARAMVALUE,185,93,169,125,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_NOINTEGRALHEIGHT | CBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Select the event type first, then set all parameters.",IDC_STATIC,185,110,169,25 +END + +IDD_TRIGGERACTIONS DIALOGEX 0, 0, 365, 202 +STYLE DS_SETFONT | WS_CHILD +FONT 8, "Tahoma", 0, 0, 0x0 +BEGIN + LTEXT "Current action:",IDC_STATIC,6,6,58,11 + COMBOBOX IDC_ACTION,72,6,149,79,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "New action",IDC_NEWACTION,233,6,60,14 + PUSHBUTTON "Delete action",IDC_DELETEACTION,301,6,59,14 + GROUPBOX "Action options",IDC_STATIC,6,20,354,174 + LTEXT "Action type:",IDC_STATIC,14,32,57,12 + COMBOBOX IDC_ACTIONTYPE,72,30,282,184,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + EDITTEXT IDC_ACTIONDESCRIPTION,14,48,340,26,ES_MULTILINE | ES_READONLY | WS_VSCROLL + LTEXT "Action parameters:",IDC_STATIC,14,79,74,10 + LISTBOX IDC_PARAMETER,14,93,160,94,LBS_SORT | LBS_USETABSTOPS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP + LTEXT "Parameter value:",IDC_STATIC,186,79,118,10 + COMBOBOX IDC_PARAMVALUE,186,92,168,125,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_NOINTEGRALHEIGHT | CBS_DISABLENOSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Select the event type first, then set all parameters.",IDC_STATIC,186,110,168,25 +END + +IDD_GLOBALS DIALOG 0, 0, 186, 79 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Local Variables" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Select variable:",IDC_STATIC,7,7,60,12 + COMBOBOX IDC_GLOBAL,7,19,172,92,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Description:",IDC_STATIC,7,41,44,12 + EDITTEXT IDC_DESCRIPTION,56,41,123,13,ES_AUTOHSCROLL + LTEXT "Preset value:",IDC_STATIC,7,60,45,11 + COMBOBOX IDC_VALUE,57,59,122,55,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP +END + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_TSOPTIONS$(TS_MODE) DIALOGEX 0, 0, 197, 183 +#else +IDD_TSOPTIONS DIALOGEX 0, 0, 197, 183 +#endif +STYLE DS_SETFONT | DS_MODALFRAME | DS_NOFAILCREATE | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Options" +FONT 8, "Tahoma", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,140,160,50,14 + PUSHBUTTON "Cancel",IDCANCEL,85,160,50,14 + LTEXT "Tiberian Sun EXE (make sure its in the correct path)",IDC_STATIC,5,5,130,20 + EDITTEXT IDC_EDIT1,5,25,130,15,ES_AUTOHSCROLL + PUSHBUTTON "Browse",IDC_CHOOSE,140,25,50,15 + LTEXT "Language / Sprache:",IDC_STATIC,7,51,128,11 + COMBOBOX IDC_LANGUAGE,7,63,183,94,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Rules, Art && AI ini files",IDC_STATIC,7,81,183,71 + CONTROL "Act like Tiberian Sun when searching for files (recommended)",IDC_RULESLIKETS, + "Button",BS_AUTORADIOBUTTON | BS_MULTILINE | WS_GROUP,14,92,170,16 + CONTROL "Only use the files inside tibsun.mix (do not use Firestorm or any mods)",IDC_ONLYORIGINAL, + "Button",BS_AUTORADIOBUTTON | BS_MULTILINE,14,110,168,16 + CONTROL "Prefer FinalSun theater INI files",IDC_PREFER_LOCAL_THEATER_FILES, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,131,164,12 +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_INFO$(RA2_MODE) DIALOGEX 0, 0, 349, 250 +#else +IDD_INFO DIALOGEX 0, 0, 349, 250 +#endif +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Info" +FONT 8, "Tahoma", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,292,8,50,14 + LTEXT "© 1999-2024 ELECTRONIC ARTS INC. ALL RIGHTS RESERVED\nWestwood Studios(tm) is an Electronic Arts(tm) brand.",IDC_STATIC,7,189,334,18 + LTEXT "© 1999-2024 Electronic Arts Inc. Westwood Studios and Electronic Arts are trademarks or registered trademarks of Electronic Arts Inc. in the U.S. and/or other countries. All rights reserved.",IDC_STATIC,7,214,335,28 + EDITTEXT IDC_LICENSE_AND_COPYRIGHT,6,29,336,148,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_LOADING$(RA2_MODE) DIALOGEX 0, 0, 235, 165 +#else +IDD_LOADING DIALOGEX 0, 0, 235, 165 +#endif +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP +FONT 8, "Tahoma", 0, 0, 0x1 +BEGIN + LTEXT "Loading...",IDC_CAP,7,7,221,9 + CONTROL "Progress1",IDC_PROGRESS1,"msctls_progress32",PBS_SMOOTH,7,18,221,13,WS_EX_DLGMODALFRAME + LTEXT "Homepage: http://www.ea.com",IDC_STATIC,7,78,221,11,WS_BORDER + CTEXT "",IDC_VERSION,74,37,154,13,SS_CENTERIMAGE | SS_SUNKEN + LTEXT "Version:",IDC_LVERSION,7,37,61,9 + CTEXT "",IDC_BUILTBY,74,52,154,13,SS_CENTERIMAGE | SS_SUNKEN + LTEXT "Built by:",IDC_LBUILTBY,7,52,61,9 + LTEXT "© 1999-2024 ELECTRONIC ARTS INC. ALL RIGHTS RESERVED\nAuthored by Matthias Wagner\nWestwood Studios(tm) is an Electronic Arts(tm) brand.",IDC_STATIC,7,97,221,33 + LTEXT "This software comes with ABSOLUTELY NO WARRANTY.\nThis is free software, and you are welcome to redistribute it.\nFor details open Help->Info",IDC_STATIC,6,129,221,26 +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_TEAMTYPES$(RA2_MODE) DIALOG 0, 0, 303, 215 +#else +IDD_TEAMTYPES DIALOG 0, 0, 303, 215 +#endif +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Teams" +FONT 8, "Tahoma" +BEGIN + LTEXT "Team types connect a trigger with task forces",IDC_STATIC,6,5,290,10 + LTEXT "Team types:",IDC_STATIC,5,20,50,10 + COMBOBOX IDC_TEAMTYPES,55,20,155,174,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "New",IDC_NEWTEAMTYPE,261,20,35,15 + PUSHBUTTON "Delete",IDC_DELETETEAMTYPE,220,20,35,15 + LTEXT "Name:",IDC_STATIC,10,51,30,10 + EDITTEXT IDC_NAME,56,51,90,12,ES_AUTOHSCROLL + LTEXT "Veteran level:",IDC_STATIC,10,66,45,15 + CONTROL "Loadable",IDC_LOADABLE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,10,157,55,8 + CONTROL "Full",IDC_FULL,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,10,167,55,8 + CONTROL "Annoyance",IDC_ANNOYANCE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,10,176,55,10 + CONTROL "Guard slower",IDC_GUARDSLOWER,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,10,187,55,8 + CONTROL "Recruiter",IDC_RECRUITER,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,10,197,55,8 + LTEXT "House:",IDC_STATIC,10,81,35,10 + COMBOBOX IDC_HOUSE,56,81,90,62,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + CONTROL "Autocreate",IDC_AUTOCREATE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,125,157,55,8 + CONTROL "Prebuild",IDC_PREBUILD,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,125,167,55,8 + CONTROL "Reinforce",IDC_REINFORCE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,125,177,55,8 + CONTROL "Cargo plane",IDC_DROPPOD,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,65,157,55,8 + CONTROL "Whiner",IDC_WHINER,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,65,167,55,8 + CONTROL "Loose recruit",IDC_LOOSERECRUIT,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,65,177,55,8 + CONTROL "Aggressive",IDC_AGGRESSIVE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,65,187,55,8 + CONTROL "Suicide",IDC_SUICIDE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,65,197,55,8 + CONTROL "OnTransOnly",IDC_ONTRANSONLY,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,125,187,55,8 + CONTROL "AvoidThreats",IDC_AVOIDTHREATS,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,125,197,55,8 + CONTROL "Ion immune",IDC_IONIMMUNE,"Button",BS_AUTOCHECKBOX | BS_LEFT | NOT WS_VISIBLE | WS_TABSTOP,185,157,60,8 + CONTROL "TransportsReturnOnUnload",IDC_TRANSPORTRETURNSONUNLOAD, + "Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,185,177,100,8 + CONTROL "AreTeamMembersRecruitable",IDC_ARETEAMMEMBERSRECRUITABLE, + "Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,185,167,105,8 + CONTROL "IsBaseDefense",IDC_ISBASEDEFENSE,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,185,187,80,8 + CONTROL "OnlyTargetHouseEnemy",IDC_ONLYTARGETHOUSEENEMY,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,185,197,100,8 + LTEXT "Priority:",IDC_STATIC,10,96,40,10 + EDITTEXT IDC_PRIORITY,56,96,90,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Max:",IDC_STATIC,10,111,30,10 + EDITTEXT IDC_MAX,56,111,90,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Techlevel:",IDC_STATIC,10,125,40,10 + COMBOBOX IDC_TECHLEVEL,56,125,91,72,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Group:",IDC_STATIC,156,51,30,10 + GROUPBOX "Selected team type",IDC_STATIC,6,37,290,173 + COMBOBOX IDC_GROUP,200,51,90,78,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Waypoint:",IDC_STATIC,156,66,40,10 + COMBOBOX IDC_WAYPOINT,200,66,90,80,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Script:",IDC_STATIC,156,81,40,10 + COMBOBOX IDC_SCRIPT,200,81,90,205,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Task force:",IDC_STATIC,156,96,40,10 + COMBOBOX IDC_TASKFORCE,200,96,90,205,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_VETERANLEVEL,56,66,90,60,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Tag:",IDC_STATIC,156,111,40,13 + COMBOBOX IDC_TAG,200,111,90,186,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + LTEXT "Transport waypoint:",IDC_LTRANSPORTWAYPOINT,156,126,40,17 + COMBOBOX IDC_TRANSPORTWAYPOINT,200,126,90,80,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Mind Control Decision:",IDC_MCD_L,10,139,43,16 + COMBOBOX IDC_MINDCONTROLDECISION,55,140,92,205,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP +END +#endif + +IDD_NEWMAPTYPE DIALOG 0, 0, 222, 129 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Create new map - Step 1" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "Next",IDOK,165,108,50,14 + PUSHBUTTON "Cancel",IDCANCEL,7,108,50,14 + LTEXT "Please select if you want to create a new singleplayer map or multiplayer map. Multiplayer maps are maps used in both skirmish and multiplayer games.",IDC_STATIC,7,7,208,33 + CONTROL "Singleplayer map (only for experienced users that can handle advanced mode)",IDC_SINGLE, + "Button",BS_AUTORADIOBUTTON | BS_MULTILINE | WS_GROUP,7,55,208,20 + CONTROL "Multiplayer map",IDC_MULTI,"Button",BS_AUTORADIOBUTTON,7,76,208,11 +END + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_NEWMAPCREATE$(TS_MODE) DIALOG 0, 0, 222, 129 +#else +IDD_NEWMAPCREATE DIALOG 0, 0, 222, 129 +#endif +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Create new map - Step 2" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "Next",IDOK,165,108,50,14 + PUSHBUTTON "Cancel",IDCANCEL,7,108,50,14 + LTEXT "Please select here if you want to create a completely new map from scratch or if you want to import an already existing map (Note: You cannot import maps created by the random map generator of RA2 or of TS version 1.15 or higher)",IDC_STATIC,7,7,208,37 + CONTROL "Create a completely new map",IDC_CREATE,"Button",BS_AUTORADIOBUTTON | WS_GROUP,7,55,208,11 + CONTROL "Import an existing map or bitmap (BMP)",IDC_IMPORT, + "Button",BS_AUTORADIOBUTTON,7,67,208,11 + CONTROL "Activate AI Triggers (results in better AI)",IDC_AITRIGGERS, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,83,208,14 +END +#endif + +IDD_NEWMAPSPOPTIONS DIALOG 0, 0, 222, 129 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Create new map - Step 4" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "Next",IDOK,165,108,50,14 + PUSHBUTTON "Cancel",IDCANCEL,7,108,50,14 + CONTROL "Prepare standard houses (recommended)",IDC_PREPAREHOUSES, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,39,159,13 + COMBOBOX IDC_HOUSE,87,63,115,99,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Player house:",IDC_LPLAYERHOUSE,15,63,52,15 + CONTROL "Set Auto-Production triggers",IDC_AUTOPROD,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,14,78,192,14 + LTEXT "Please select the human player. It is recommended to leave the other options as they are.",IDC_STATIC,7,7,208,26 + GROUPBOX "",IDC_STATIC,7,52,208,46 +END + +IDD_NEWMAPCREATENEW DIALOG 0, 0, 222, 129 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Create new map - Step 3" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "Next",IDOK,165,108,50,14 + PUSHBUTTON "Cancel",IDCANCEL,7,108,50,14 + LTEXT "Please select size, theater and starting height here. The size should be below 100x100 for best results.",IDC_STATIC,7,7,208,32 + LTEXT "Width:",IDC_STATIC,7,39,35,11 + EDITTEXT IDC_WIDTH,130,39,85,13,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Height:",IDC_STATIC,7,55,35,11 + EDITTEXT IDC_HEIGHT,130,55,85,13,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Theater:",IDC_STATIC,7,71,53,12 + COMBOBOX IDC_THEATER,130,71,85,58,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Starting height:",IDC_STATIC,7,87,64,12 + COMBOBOX IDC_STARTINGHEIGHT,130,87,85,93,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP +END + +IDD_NEWMAPIMPORT DIALOG 0, 0, 222, 129 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Create new map - Step 3" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "Next",IDOK,165,108,50,14 + PUSHBUTTON "Cancel",IDCANCEL,7,108,50,14 + PUSHBUTTON "Browse",IDC_BROWSE,155,51,60,12 + CONTROL "Import Trees",IDC_IMPORTTREES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,69,91,12 + CONTROL "Import Overlay",IDC_IMPORTOVERLAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,82,103,13 + CONTROL "Import Units/Buildings",IDC_IMPORTUNITS,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,120,66,94,19 + COMBOBOX IDC_IMPORTFILE,7,51,131,206,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Please select the map you want to import. No triggers or houses will be imported. Bitmaps will be scaled down to appropiate size. Currently bitmaps will always be converted to temperate theater maps.",IDC_STATIC,7,7,208,43 +END + +IDD_MAPLOAD DIALOG 0, 0, 220, 50 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_CAPTION +CAPTION "Loading" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Loading map, please wait. This may take several minutes on big maps.",IDC_STATIC,7,7,206,18 + CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",PBS_SMOOTH | WS_BORDER,7,29,206,14 +END + +IDD_NEWMAPBITMAP DIALOG 0, 0, 222, 129 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Create new map - Step 3" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "Next",IDOK,165,108,50,14 + PUSHBUTTON "Cancel",IDCANCEL,7,108,50,14 + LTEXT "Please select size, theater and starting height here. The size should be below 150x150.",IDC_STATIC,7,7,208,32 + LTEXT "Width:",IDC_STATIC,7,39,35,11 + EDITTEXT IDC_WIDTH,130,39,85,13,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Height:",IDC_STATIC,7,55,35,11 + EDITTEXT IDC_HEIGHT,130,55,85,13,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Theater:",IDC_STATIC,7,71,53,12 + COMBOBOX IDC_THEATER,130,71,85,58,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Starting height:",IDC_STATIC,7,87,64,12 + COMBOBOX IDC_STARTINGHEIGHT,130,87,85,93,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP +END + +IDD_PROGRESS DIALOG 0, 0, 208, 89 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Progress" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "Cancel",IDCANCEL,67,68,50,14 + LTEXT "Progress:",IDC_LABEL,7,7,194,22 + CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",PBS_SMOOTH | WS_BORDER,7,47,194,13 + LTEXT "Progress: ",IDC_PROGLABEL,7,31,194,13 +END + +IDD_AUTOUPDATE DIALOG 0, 0, 290, 177 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Auto Update" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "Download",IDOK,223,156,60,14 + PUSHBUTTON "Cancel",IDCANCEL,152,156,60,14 + LTEXT "Updates available:",IDC_STATIC,7,7,184,16 + LISTBOX IDC_UPDATELIST,7,23,276,36,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LTEXT "Description:",IDC_STATIC,7,66,80,14 + EDITTEXT IDC_DESCRIPTION,92,66,191,42,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL + LTEXT "Download locations:",IDC_STATIC,7,118,69,14 + LISTBOX IDC_DOWNLOADLIST,91,117,192,29,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP +END + +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_NEWMAPCREATE$(RA2_MODE) DIALOG 0, 0, 222, 129 +#else +IDD_NEWMAPCREATE DIALOG 0, 0, 222, 129 +#endif +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Create new map - Step 2" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "Next",IDOK,165,108,50,14 + PUSHBUTTON "Cancel",IDCANCEL,7,108,50,14 + LTEXT "Please select here if you want to create a completely new map from scratch or if you want to import an already existing map (Note: You cannot import maps created by the random map generator of RA2)",IDC_STATIC,7,7,208,37 + CONTROL "Create a completely new map",IDC_CREATE,"Button",BS_AUTORADIOBUTTON | WS_GROUP,7,55,208,11 + CONTROL "Import an existing map or bitmap (BMP)",IDC_IMPORT, + "Button",BS_AUTORADIOBUTTON,7,67,208,11 + CONTROL "Activate AI Triggers (results in better AI)",IDC_AITRIGGERS, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,83,208,14 +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_SAVING$(RA2_MODE) DIALOG 0, 0, 263, 46 +#else +IDD_SAVING DIALOG 0, 0, 263, 46 +#endif +STYLE DS_SETFONT | DS_CENTER | WS_POPUP | WS_CAPTION +CAPTION "Saving" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Please wait a few seconds while FinalAlert 2 is saving. On very large maps this may even take some minutes, please do not cancel! More information is available in the status bar, most time will be needed for packing.",IDC_STATIC,7,7,249,32 +END +#endif + +IDD_UNIT DIALOG 0, 0, 232, 145 +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Unit Options" +FONT 8, "Tahoma" +BEGIN + DEFPUSHBUTTON "OK",IDOK,170,124,50,14 + PUSHBUTTON "Cancel",IDCANCEL,110,124,50,14 + LTEXT "House:",IDC_LHOUSE,5,8,33,11 + COMBOBOX IDC_HOUSE,45,8,65,45,CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Strength:",IDC_LSTRENGTH,5,26,29,10 + CONTROL "Slider1",IDC_STRENGTH,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,45,26,70,11 + LTEXT "State:",IDC_LSTATE,5,43,40,10 + COMBOBOX IDC_STATE,45,43,65,90,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Tag:",IDC_LTAG,6,105,63,14 + COMBOBOX IDC_TAG,74,106,153,69,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Param1:",IDC_LP1,5,80,37,17 + EDITTEXT IDC_P1,45,80,65,12,ES_AUTOHSCROLL + LTEXT "Param2:",IDC_LP2,125,8,30,16 + LTEXT "Param3:",IDC_LP3,125,25,30,16 + LTEXT "Param4:",IDC_LP4,125,43,30,16 + EDITTEXT IDC_P2,161,8,65,12,ES_AUTOHSCROLL + EDITTEXT IDC_P3,161,25,65,12,ES_AUTOHSCROLL + EDITTEXT IDC_P4,161,43,65,12,ES_AUTOHSCROLL + LTEXT "Params are unknown (integers?).",IDC_DESC,4,137,53,8 + LTEXT "Direction:",IDC_LDIRECTION,5,61,40,10 + COMBOBOX IDC_DIRECTION,45,61,65,75,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP + LTEXT "Param5:",IDC_LP5,125,61,34,17 + EDITTEXT IDC_P6,161,79,65,12,ES_AUTOHSCROLL + LTEXT "Param6:",IDC_LP6,125,79,35,16 + EDITTEXT IDC_P5,161,61,65,12,ES_AUTOHSCROLL +END + +IDD_TERRAINPLACING DIALOG 0, 0, 193, 234 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Random Tree Placing" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,136,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,136,24,50,14 + LTEXT "Please select the trees that shall be placed",IDC_STATIC,7,7,104,22 + LISTBOX IDC_AVAIL,7,58,73,77,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LTEXT "Available:",IDC_STATIC,7,45,86,11 + LISTBOX IDC_USED,113,58,73,77,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LTEXT "Used:",IDC_STATIC,114,45,74,11 + PUSHBUTTON "<-",IDC_REMOVE,87,75,20,11 + PUSHBUTTON "->",IDC_ADD,87,58,20,11 + GROUPBOX "Preview",IDC_PREVIEW,7,140,179,86 +END + +IDD_SEARCHWAYPOINT DIALOG 0, 0, 186, 95 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Search Waypoint" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "Search",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 + LTEXT "Waypoints:",IDC_STATIC,7,7,96,12 + LISTBOX IDC_WAYPOINTS,7,21,97,67,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP +END + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_AITRIGGERTYPES$(TS_MODE) DIALOG 0, 0, 303, 234 +#else +IDD_AITRIGGERTYPES DIALOG 0, 0, 303, 234 +#endif +STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "AI Trigger Types" +FONT 8, "Tahoma" +BEGIN + LTEXT "AI Trigger:",IDC_STATIC,7,7,43,11 + COMBOBOX IDC_AITRIGGERTYPE,60,7,236,307,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Name:",IDC_STATIC,7,63,43,11 + EDITTEXT IDC_NAME,60,64,94,13,ES_AUTOHSCROLL + LTEXT "Teamtype #1:",IDC_STATIC,7,80,43,17 + COMBOBOX IDC_TEAMTYPE1,60,81,236,81,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "House:",IDC_STATIC,165,64,50,16 + COMBOBOX IDC_OWNER,220,64,76,207,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + LTEXT "Teamtype #2:",IDC_STATIC,7,98,43,17 + COMBOBOX IDC_TEAMTYPE2,60,98,235,81,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Techlevel:",IDC_STATIC,280,206,8,11,NOT WS_VISIBLE + COMBOBOX IDC_FLAG1,288,222,16,56,CBS_DROPDOWN | NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP + LTEXT "Type:",IDC_STATIC,6,44,53,17 + COMBOBOX IDC_FLAG2,60,45,235,71,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Data:",IDC_DATALABEL,265,204,8,13,NOT WS_VISIBLE + COMBOBOX IDC_DATA,287,222,16,128,CBS_DROPDOWN | CBS_AUTOHSCROLL | NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP + LTEXT "Weight:",IDC_STATIC,6,150,33,11 + EDITTEXT IDC_FLOAT1,59,148,56,13,ES_AUTOHSCROLL + LTEXT "MinWeight:",IDC_STATIC,6,165,38,11 + EDITTEXT IDC_FLOAT2,59,164,56,13,ES_AUTOHSCROLL + LTEXT "MaxWeight:",IDC_STATIC,125,165,40,11 + EDITTEXT IDC_FLOAT3,180,164,54,13,ES_AUTOHSCROLL + LTEXT "MinDiff:",IDC_STATIC,279,222,8,12,NOT WS_VISIBLE + EDITTEXT IDC_FLAG4,291,222,8,12,ES_AUTOHSCROLL | NOT WS_VISIBLE + LTEXT "Multi-Side:",IDC_STATIC,7,115,33,12 + PUSHBUTTON "Delete",IDC_DELETE,220,23,76,13 + PUSHBUTTON "Add",IDC_ADD,140,23,74,13 + CONTROL "Enabled",IDC_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,60,23,76,11 + CONTROL "Easy",IDC_EASY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,59,133,42,13 + CONTROL "Medium",IDC_MEDIUM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,124,132,42,13 + CONTROL "Hard",IDC_HARD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,199,132,42,13 + CONTROL "Base defense",IDC_BASEDEFENSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,124,116,67,13 + CONTROL "Available in Skirmish",IDC_SKIRMISH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,199,116,85,14 + COMBOBOX IDC_MULTISIDE,60,116,56,63,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + LTEXT "Unittype (X):",IDC_STATIC,171,200,51,10 + COMBOBOX IDC_UNITTYPE,171,212,125,255,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + LTEXT "Condition:",IDC_STATIC,8,200,50,11 + COMBOBOX IDC_CONDITION,8,212,95,82,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + EDITTEXT IDC_NUMBER,109,212,54,13,ES_AUTOHSCROLL + LTEXT "Number (N):",IDC_STATIC,110,200,56,11 + LTEXT "Additional parameters for the appropiate AI Trigger Types:",IDC_STATIC,6,188,295,12 +END +#endif + +IDD_USERSCRIPTS DIALOG 0, 0, 301, 193 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Map Scripts" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "Run",IDOK,244,40,50,14 + PUSHBUTTON "Quit",IDCANCEL,244,57,50,14 + LTEXT "Scripts available:",IDC_STATIC,7,24,109,12 + LISTBOX IDC_SCRIPTS,7,39,230,74,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LTEXT "Report:",IDC_STATIC,7,124,117,15 + EDITTEXT IDC_REPORT,7,145,287,41,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL + LTEXT "For safety reasons, you should save your map before running scripts. Undo is not available.",IDC_STATIC,7,7,287,17 +END + +IDD_COMBO_UINPUT DIALOG 0, 0, 238, 63 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Please select" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,181,42,50,14 + PUSHBUTTON "Cancel",IDCANCEL,124,42,50,14,NOT WS_VISIBLE + LTEXT "CAPTION",IDC_CAPTION,7,7,224,12 + COMBOBOX IDC_COMBO1,7,23,224,160,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_NEWRA2HOUSE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 45 + END + + "IDD_SAVEOPTIONS$(TS_MODE)", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 226 + TOPMARGIN, 7 + BOTTOMMARGIN, 118 + END + + IDD_MULTISAVEOPT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 274 + TOPMARGIN, 7 + BOTTOMMARGIN, 98 + END + + IDD_MMXOPTIONS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 261 + TOPMARGIN, 7 + BOTTOMMARGIN, 165 + END + + "IDD_SAVEOPTIONS$(RA2_MODE)", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 226 + TOPMARGIN, 7 + BOTTOMMARGIN, 179 + END + + IDD_CHANGESIZE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 205 + TOPMARGIN, 7 + BOTTOMMARGIN, 187 + END + + IDD_AITRIGGERADD, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 215 + TOPMARGIN, 7 + BOTTOMMARGIN, 90 + END + + IDD_MYOPENDIALOG, DIALOG + BEGIN + END + + IDD_TIP, DIALOG + BEGIN + RIGHTMARGIN, 274 + END + + IDD_FINALSUN_DIALOG, DIALOG + BEGIN + END + + "IDD_TSOPTIONS$(RA2_MODE)", DIALOG + BEGIN + BOTTOMMARGIN, 165 + END + + IDD_ALL, DIALOG + BEGIN + END + + IDD_MAP, DIALOG + BEGIN + END + + IDD_INPUTBOX, DIALOG + BEGIN + END + + IDD_IMPORTINI, DIALOG + BEGIN + END + + IDD_LIGHTING, DIALOG + BEGIN + END + + "IDD_INFO$(TS_MODE)", DIALOG + BEGIN + RIGHTMARGIN, 343 + BOTTOMMARGIN, 243 + END + + IDD_SPECIALFLAGS, DIALOG + BEGIN + END + + IDD_INFANTRY, DIALOG + BEGIN + END + + IDD_HOUSES, DIALOG + BEGIN + END + + IDD_AIRCRAFT, DIALOG + BEGIN + END + + IDD_BUILDING, DIALOG + BEGIN + END + + "IDD_LOADING$(TS_MODE)", DIALOG + BEGIN + BOTTOMMARGIN, 159 + END + + IDD_WAYPOINT, DIALOG + BEGIN + END + + IDD_CELLTAG, DIALOG + BEGIN + END + + "IDD_TEAMTYPES$(TS_MODE)", DIALOG + BEGIN + END + + IDD_TASKFORCES, DIALOG + BEGIN + END + + IDD_TAGS, DIALOG + BEGIN + END + + IDD_TRIGGERS, DIALOG + BEGIN + END + + "IDD_AITRIGGERTYPES$(RA2_MODE)", DIALOG + BEGIN + END + + IDD_NEWMAP, DIALOG + BEGIN + END + + IDD_BASIC, DIALOG + BEGIN + END + + IDD_SINGLEPLAYER, DIALOG + BEGIN + END + + IDD_MAPVALIDATOR, DIALOG + BEGIN + RIGHTMARGIN, 433 + VERTGUIDE, 6 + VERTGUIDE, 372 + BOTTOMMARGIN, 219 + HORZGUIDE, 165 + END + + IDD_SCRIPTTYPES, DIALOG + BEGIN + END + + IDD_TERRAINBAR, DIALOG + BEGIN + END + + IDD_TOOLSETTINGS, DIALOG + BEGIN + END + + IDD_SHUTDOWN, DIALOG + BEGIN + END + + IDD_DYNAMICLOAD, DIALOG + BEGIN + END + + "IDD_SAVING$(TS_MODE)", DIALOG + BEGIN + END + + IDD_TRIGGEREDITOR, DIALOG + BEGIN + RIGHTMARGIN, 384 + VERTGUIDE, 228 + BOTTOMMARGIN, 258 + END + + IDD_TRIGGEROPTIONS, DIALOG + BEGIN + VERTGUIDE, 4 + VERTGUIDE, 356 + END + + IDD_TRIGGEREVENTS, DIALOG + BEGIN + RIGHTMARGIN, 361 + VERTGUIDE, 6 + VERTGUIDE, 14 + VERTGUIDE, 72 + VERTGUIDE, 173 + VERTGUIDE, 185 + VERTGUIDE, 222 + VERTGUIDE, 233 + VERTGUIDE, 294 + VERTGUIDE, 300 + VERTGUIDE, 354 + HORZGUIDE, 6 + HORZGUIDE, 79 + END + + IDD_TRIGGERACTIONS, DIALOG + BEGIN + RIGHTMARGIN, 360 + VERTGUIDE, 6 + VERTGUIDE, 14 + VERTGUIDE, 72 + VERTGUIDE, 174 + VERTGUIDE, 186 + VERTGUIDE, 221 + VERTGUIDE, 233 + VERTGUIDE, 293 + VERTGUIDE, 301 + VERTGUIDE, 354 + BOTTOMMARGIN, 194 + HORZGUIDE, 6 + HORZGUIDE, 74 + HORZGUIDE, 79 + END + + "IDD_TSOPTIONS$(TS_MODE)", DIALOG + BEGIN + BOTTOMMARGIN, 165 + END + + "IDD_INFO$(RA2_MODE)", DIALOG + BEGIN + RIGHTMARGIN, 342 + TOPMARGIN, 8 + BOTTOMMARGIN, 242 + END + + "IDD_LOADING$(RA2_MODE)", DIALOG + BEGIN + BOTTOMMARGIN, 159 + END + + "IDD_TEAMTYPES$(RA2_MODE)", DIALOG + BEGIN + END + + IDD_NEWMAPTYPE, DIALOG + BEGIN + END + + "IDD_NEWMAPCREATE$(TS_MODE)", DIALOG + BEGIN + END + + IDD_NEWMAPSPOPTIONS, DIALOG + BEGIN + END + + IDD_NEWMAPCREATENEW, DIALOG + BEGIN + END + + IDD_NEWMAPIMPORT, DIALOG + BEGIN + END + + IDD_MAPLOAD, DIALOG + BEGIN + END + + IDD_NEWMAPBITMAP, DIALOG + BEGIN + END + + IDD_PROGRESS, DIALOG + BEGIN + END + + IDD_AUTOUPDATE, DIALOG + BEGIN + END + + "IDD_NEWMAPCREATE$(RA2_MODE)", DIALOG + BEGIN + END + + "IDD_SAVING$(RA2_MODE)", DIALOG + BEGIN + END + + IDD_UNIT, DIALOG + BEGIN + END + + IDD_TERRAINPLACING, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 186 + TOPMARGIN, 7 + BOTTOMMARGIN, 226 + END + + IDD_SEARCHWAYPOINT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END + + "IDD_AITRIGGERTYPES$(TS_MODE)", DIALOG + BEGIN + END + + IDD_USERSCRIPTS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 294 + TOPMARGIN, 7 + BOTTOMMARGIN, 186 + END + + IDD_COMBO_UINPUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 231 + TOPMARGIN, 7 + BOTTOMMARGIN, 56 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog Info +// + +IDD_MMXOPTIONS DLGINIT +BEGIN + IDC_MINPLAYERS, 0x403, 2, 0 +0x0032, + IDC_MINPLAYERS, 0x403, 2, 0 +0x0033, + IDC_MINPLAYERS, 0x403, 2, 0 +0x0034, + IDC_MINPLAYERS, 0x403, 2, 0 +0x0035, + IDC_MINPLAYERS, 0x403, 2, 0 +0x0036, + IDC_MINPLAYERS, 0x403, 2, 0 +0x0037, + IDC_MINPLAYERS, 0x403, 2, 0 +0x0038, + IDC_MAXPLAYERS, 0x403, 2, 0 +0x0032, + IDC_MAXPLAYERS, 0x403, 2, 0 +0x0033, + IDC_MAXPLAYERS, 0x403, 2, 0 +0x0034, + IDC_MAXPLAYERS, 0x403, 2, 0 +0x0035, + IDC_MAXPLAYERS, 0x403, 2, 0 +0x0036, + IDC_MAXPLAYERS, 0x403, 2, 0 +0x0037, + IDC_MAXPLAYERS, 0x403, 2, 0 +0x0038, + 0 +END + +IDD_MAP DLGINIT +BEGIN + IDC_THEATER, 0x403, 5, 0 +0x4e53, 0x574f, "\000" + IDC_THEATER, 0x403, 10, 0 +0x4554, 0x504d, 0x5245, 0x5441, 0x0045, + 0 +END + +IDD_SPECIALFLAGS DLGINIT +BEGIN + IDC_TIBERIUMGROWS, 0x403, 4, 0 +0x6579, 0x0073, + IDC_TIBERIUMGROWS, 0x403, 3, 0 +0x6f6e, "\000" + IDC_TIBERIUMSPREADS, 0x403, 4, 0 +0x6579, 0x0073, + IDC_TIBERIUMSPREADS, 0x403, 3, 0 +0x6f6e, "\000" + IDC_TIBERIUMEXPLOSIVE, 0x403, 4, 0 +0x6579, 0x0073, + IDC_TIBERIUMEXPLOSIVE, 0x403, 3, 0 +0x6f6e, "\000" + IDC_DESTROYABLEBRIDGES, 0x403, 4, 0 +0x6579, 0x0073, + IDC_DESTROYABLEBRIDGES, 0x403, 3, 0 +0x6f6e, "\000" + IDC_MCVDEPLOY, 0x403, 4, 0 +0x6579, 0x0073, + IDC_MCVDEPLOY, 0x403, 3, 0 +0x6f6e, "\000" + IDC_INITIALVETERAN, 0x403, 4, 0 +0x6579, 0x0073, + IDC_INITIALVETERAN, 0x403, 3, 0 +0x6f6e, "\000" + IDC_FIXEDALLIANCE, 0x403, 4, 0 +0x6579, 0x0073, + IDC_FIXEDALLIANCE, 0x403, 3, 0 +0x6f6e, "\000" + IDC_HARVESTERIMMUNE, 0x403, 4, 0 +0x6579, 0x0073, + IDC_HARVESTERIMMUNE, 0x403, 3, 0 +0x6f6e, "\000" + IDC_FOGOFWAR, 0x403, 4, 0 +0x6579, 0x0073, + IDC_FOGOFWAR, 0x403, 3, 0 +0x6f6e, "\000" + IDC_INERT, 0x403, 4, 0 +0x6579, 0x0073, + IDC_INERT, 0x403, 3, 0 +0x6f6e, "\000" + IDC_IONSTORMS, 0x403, 4, 0 +0x6579, 0x0073, + IDC_IONSTORMS, 0x403, 3, 0 +0x6f6e, "\000" + IDC_METEORITES, 0x403, 4, 0 +0x6579, 0x0073, + IDC_METEORITES, 0x403, 3, 0 +0x6f6e, "\000" + IDC_VISCEROIDS, 0x403, 4, 0 +0x6579, 0x0073, + IDC_VISCEROIDS, 0x403, 3, 0 +0x6f6e, "\000" + 0 +END + +IDD_INFANTRY DLGINIT +BEGIN + IDC_STATE, 0x403, 6, 0 +0x6c53, 0x6565, 0x0070, + IDC_STATE, 0x403, 9, 0 +0x6148, 0x6d72, 0x656c, 0x7373, "\000" + IDC_STATE, 0x403, 7, 0 +0x7453, 0x6369, 0x796b, "\000" + IDC_STATE, 0x403, 7, 0 +0x7441, 0x6174, 0x6b63, "\000" + IDC_STATE, 0x403, 5, 0 +0x6f4d, 0x6576, "\000" + IDC_STATE, 0x403, 7, 0 +0x6150, 0x7274, 0x6c6f, "\000" + IDC_STATE, 0x403, 6, 0 +0x4d51, 0x766f, 0x0065, + IDC_STATE, 0x403, 8, 0 +0x6552, 0x7274, 0x6165, 0x0074, + IDC_STATE, 0x403, 6, 0 +0x7547, 0x7261, 0x0064, + IDC_STATE, 0x403, 6, 0 +0x6e45, 0x6574, 0x0072, + IDC_STATE, 0x403, 8, 0 +0x6143, 0x7470, 0x7275, 0x0065, + IDC_STATE, 0x403, 8, 0 +0x6148, 0x7672, 0x7365, 0x0074, + IDC_STATE, 0x403, 11, 0 +0x7241, 0x6165, 0x4720, 0x6175, 0x6472, "\000" + IDC_STATE, 0x403, 17, 0 +0x6552, 0x7574, 0x6e72, 0x3c20, 0x6e75, 0x7375, 0x6465, 0x3e21, "\000" + IDC_STATE, 0x403, 5, 0 +0x7453, 0x706f, "\000" + IDC_STATE, 0x403, 17, 0 +0x6d41, 0x7562, 0x6873, 0x3c20, 0x6e75, 0x7375, 0x6465, 0x3e21, "\000" + IDC_STATE, 0x403, 5, 0 +0x7548, 0x746e, "\000" + IDC_STATE, 0x403, 7, 0 +0x6e55, 0x6f6c, 0x6461, "\000" + IDC_STATE, 0x403, 9, 0 +0x6153, 0x6f62, 0x6174, 0x6567, "\000" + IDC_STATE, 0x403, 13, 0 +0x6f43, 0x736e, 0x7274, 0x6375, 0x6974, 0x6e6f, "\000" + IDC_STATE, 0x403, 8, 0 +0x6553, 0x6c6c, 0x6e69, 0x0067, + IDC_STATE, 0x403, 7, 0 +0x6552, 0x6170, 0x7269, "\000" + IDC_STATE, 0x403, 7, 0 +0x6552, 0x6373, 0x6575, "\000" + IDC_STATE, 0x403, 8, 0 +0x694d, 0x7373, 0x6c69, 0x0065, + IDC_STATE, 0x403, 5, 0 +0x704f, 0x6e65, "\000" + IDC_TAG, 0x403, 5, 0 +0x6f4e, 0x656e, "\000" + IDC_DIRECTION, 0x403, 2, 0 +0x0030, + IDC_DIRECTION, 0x403, 3, 0 +0x3233, "\000" + IDC_DIRECTION, 0x403, 3, 0 +0x3436, "\000" + IDC_DIRECTION, 0x403, 3, 0 +0x3639, "\000" + IDC_DIRECTION, 0x403, 4, 0 +0x3231, 0x0038, + IDC_DIRECTION, 0x403, 4, 0 +0x3631, 0x0030, + IDC_DIRECTION, 0x403, 4, 0 +0x3931, 0x0032, + IDC_DIRECTION, 0x403, 4, 0 +0x3232, 0x0034, + 0 +END + +IDD_HOUSES DLGINIT +BEGIN + IDC_IQ, 0x403, 2, 0 +0x0030, + IDC_IQ, 0x403, 2, 0 +0x0031, + IDC_IQ, 0x403, 2, 0 +0x0032, + IDC_IQ, 0x403, 2, 0 +0x0033, + IDC_IQ, 0x403, 2, 0 +0x0034, + IDC_IQ, 0x403, 2, 0 +0x0035, + IDC_EDGE, 0x403, 5, 0 +0x6557, 0x7473, "\000" + IDC_EDGE, 0x403, 5, 0 +0x6145, 0x7473, "\000" + IDC_EDGE, 0x403, 6, 0 +0x6f4e, 0x7472, 0x0068, + IDC_EDGE, 0x403, 6, 0 +0x6f53, 0x7475, 0x0068, + IDC_SIDE, 0x403, 4, 0 +0x4447, 0x0049, + IDC_SIDE, 0x403, 4, 0 +0x6f4e, 0x0064, + IDC_SIDE, 0x403, 9, 0 +0x6943, 0x6976, 0x696c, 0x6e61, "\000" + IDC_SIDE, 0x403, 7, 0 +0x754d, 0x6174, 0x746e, "\000" + IDC_ACTSLIKE, 0x403, 6, 0 +0x2030, 0x4447, 0x0049, + IDC_ACTSLIKE, 0x403, 6, 0 +0x2031, 0x6f4e, 0x0064, + IDC_NODECOUNT, 0x403, 2, 0 +0x0030, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0030, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0031, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0032, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0033, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0034, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0035, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0036, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0037, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0038, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0039, + IDC_TECHLEVEL, 0x403, 3, 0 +0x3031, "\000" + IDC_PERCENTBUILT, 0x403, 2, 0 +0x0030, + IDC_PERCENTBUILT, 0x403, 3, 0 +0x3035, "\000" + IDC_PERCENTBUILT, 0x403, 4, 0 +0x3031, 0x0030, + IDC_PLAYERCONTROL, 0x403, 3, 0 +0x6f6e, "\000" + IDC_PLAYERCONTROL, 0x403, 4, 0 +0x6579, 0x0073, + 0 +END + +IDD_AIRCRAFT DLGINIT +BEGIN + IDC_STATE, 0x403, 6, 0 +0x6c53, 0x6565, 0x0070, + IDC_STATE, 0x403, 9, 0 +0x6148, 0x6d72, 0x656c, 0x7373, "\000" + IDC_STATE, 0x403, 7, 0 +0x7453, 0x6369, 0x796b, "\000" + IDC_STATE, 0x403, 7, 0 +0x7441, 0x6174, 0x6b63, "\000" + IDC_STATE, 0x403, 5, 0 +0x6f4d, 0x6576, "\000" + IDC_STATE, 0x403, 7, 0 +0x6150, 0x7274, 0x6c6f, "\000" + IDC_STATE, 0x403, 6, 0 +0x4d51, 0x766f, 0x0065, + IDC_STATE, 0x403, 8, 0 +0x6552, 0x7274, 0x6165, 0x0074, + IDC_STATE, 0x403, 6, 0 +0x7547, 0x7261, 0x0064, + IDC_STATE, 0x403, 6, 0 +0x6e45, 0x6574, 0x0072, + IDC_STATE, 0x403, 8, 0 +0x6143, 0x7470, 0x7275, 0x0065, + IDC_STATE, 0x403, 8, 0 +0x6148, 0x7672, 0x7365, 0x0074, + IDC_STATE, 0x403, 11, 0 +0x7241, 0x6165, 0x4720, 0x6175, 0x6472, "\000" + IDC_STATE, 0x403, 17, 0 +0x6552, 0x7574, 0x6e72, 0x3c20, 0x6e75, 0x7375, 0x6465, 0x3e21, "\000" + IDC_STATE, 0x403, 5, 0 +0x7453, 0x706f, "\000" + IDC_STATE, 0x403, 17, 0 +0x6d41, 0x7562, 0x6873, 0x3c20, 0x6e75, 0x7375, 0x6465, 0x3e21, "\000" + IDC_STATE, 0x403, 5, 0 +0x7548, 0x746e, "\000" + IDC_STATE, 0x403, 7, 0 +0x6e55, 0x6f6c, 0x6461, "\000" + IDC_STATE, 0x403, 9, 0 +0x6153, 0x6f62, 0x6174, 0x6567, "\000" + IDC_STATE, 0x403, 13, 0 +0x6f43, 0x736e, 0x7274, 0x6375, 0x6974, 0x6e6f, "\000" + IDC_STATE, 0x403, 8, 0 +0x6553, 0x6c6c, 0x6e69, 0x0067, + IDC_STATE, 0x403, 7, 0 +0x6552, 0x6170, 0x7269, "\000" + IDC_STATE, 0x403, 7, 0 +0x6552, 0x6373, 0x6575, "\000" + IDC_STATE, 0x403, 8, 0 +0x694d, 0x7373, 0x6c69, 0x0065, + IDC_STATE, 0x403, 5, 0 +0x704f, 0x6e65, "\000" + IDC_TAG, 0x403, 5, 0 +0x6f4e, 0x656e, "\000" + IDC_DIRECTION, 0x403, 2, 0 +0x0030, + IDC_DIRECTION, 0x403, 3, 0 +0x3233, "\000" + IDC_DIRECTION, 0x403, 3, 0 +0x3436, "\000" + IDC_DIRECTION, 0x403, 3, 0 +0x3639, "\000" + IDC_DIRECTION, 0x403, 4, 0 +0x3231, 0x0038, + IDC_DIRECTION, 0x403, 4, 0 +0x3631, 0x0030, + IDC_DIRECTION, 0x403, 4, 0 +0x3931, 0x0032, + IDC_DIRECTION, 0x403, 4, 0 +0x3232, 0x0034, + 0 +END + +IDD_BUILDING DLGINIT +BEGIN + IDC_TAG, 0x403, 5, 0 +0x6f4e, 0x656e, "\000" + IDC_DIRECTION, 0x403, 2, 0 +0x0030, + IDC_DIRECTION, 0x403, 3, 0 +0x3233, "\000" + IDC_DIRECTION, 0x403, 3, 0 +0x3436, "\000" + IDC_DIRECTION, 0x403, 3, 0 +0x3639, "\000" + IDC_DIRECTION, 0x403, 4, 0 +0x3231, 0x0038, + IDC_DIRECTION, 0x403, 4, 0 +0x3631, 0x0030, + IDC_DIRECTION, 0x403, 4, 0 +0x3931, 0x0032, + IDC_DIRECTION, 0x403, 4, 0 +0x3232, 0x0034, + IDC_P6, 0x403, 5, 0 +0x6f4e, 0x656e, "\000" + IDC_P7, 0x403, 5, 0 +0x6f4e, 0x656e, "\000" + IDC_P8, 0x403, 5, 0 +0x6f4e, 0x656e, "\000" + IDC_P3, 0x403, 2, 0 +0x0030, + IDC_P3, 0x403, 2, 0 +0x0031, + IDC_P2, 0x403, 2, 0 +0x0030, + IDC_P2, 0x403, 2, 0 +0x0031, + IDC_P4, 0x403, 2, 0 +0x0030, + IDC_P4, 0x403, 2, 0 +0x0031, + IDC_P4, 0x403, 2, 0 +0x0032, + IDC_P4, 0x403, 2, 0 +0x0033, + IDC_P5, 0x403, 17, 0 +0x2030, 0x202d, 0x6f4e, 0x7320, 0x6f70, 0x6c74, 0x6769, 0x7468, "\000" + IDC_P5, 0x403, 22, 0 +0x2031, 0x202d, 0x7552, 0x656c, 0x2e73, 0x6e49, 0x2069, 0x6573, 0x7474, +0x6e69, 0x0067, + IDC_P5, 0x403, 23, 0 +0x2032, 0x202d, 0x6943, 0x6372, 0x656c, 0x2f20, 0x4420, 0x7269, 0x6365, +0x6974, 0x6e6f, "\000" + IDC_P9, 0x403, 2, 0 +0x0030, + IDC_P9, 0x403, 2, 0 +0x0031, + IDC_P10, 0x403, 2, 0 +0x0030, + IDC_P10, 0x403, 2, 0 +0x0031, + 0 +END + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_TEAMTYPES$(TS_MODE) DLGINIT +#else +IDD_TEAMTYPES DLGINIT +#endif +BEGIN + IDC_TECHLEVEL, 0x403, 2, 0 +0x0030, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0031, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0032, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0033, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0034, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0035, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0036, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0037, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0038, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0039, + IDC_TECHLEVEL, 0x403, 3, 0 +0x3031, "\000" + IDC_GROUP, 0x403, 3, 0 +0x312d, "\000" + IDC_VETERANLEVEL, 0x403, 2, 0 +0x0031, + IDC_VETERANLEVEL, 0x403, 2, 0 +0x0032, + IDC_VETERANLEVEL, 0x403, 2, 0 +0x0033, + IDC_MINDCONTROLDECISION, 0x403, 17, 0 +0x2030, 0x202d, 0x443c, 0x6e6f, 0x7427, 0x6320, 0x7261, 0x3e65, "\000" + IDC_MINDCONTROLDECISION, 0x403, 16, 0 +0x2031, 0x202d, 0x6441, 0x2064, 0x6f54, 0x5420, 0x6165, 0x006d, + IDC_MINDCONTROLDECISION, 0x403, 19, 0 +0x2032, 0x202d, 0x7550, 0x2074, 0x6e69, 0x4720, 0x6972, 0x646e, 0x7265, +"\000" + IDC_MINDCONTROLDECISION, 0x403, 23, 0 +0x2033, 0x202d, 0x7550, 0x2074, 0x6e69, 0x4220, 0x6f69, 0x5220, 0x6165, +0x7463, 0x726f, "\000" + IDC_MINDCONTROLDECISION, 0x403, 15, 0 +0x2034, 0x202d, 0x6f47, 0x7420, 0x206f, 0x7548, 0x746e, "\000" + IDC_MINDCONTROLDECISION, 0x403, 15, 0 +0x2035, 0x202d, 0x6f44, 0x4e20, 0x746f, 0x6968, 0x676e, "\000" + 0 +END +#endif + +IDD_TAGS DLGINIT +BEGIN + IDC_REPEAT, 0x403, 36, 0 +0x2030, 0x202d, 0x614d, 0x656b, 0x7420, 0x6568, 0x7420, 0x6972, 0x6767, +0x7265, 0x7720, 0x726f, 0x206b, 0x6e6f, 0x796c, 0x6f20, 0x636e, 0x0065, + + IDC_REPEAT, 0x403, 12, 0 +0x2031, 0x202d, 0x6e55, 0x6e6b, 0x776f, 0x006e, + IDC_REPEAT, 0x403, 32, 0 +0x2032, 0x202d, 0x614d, 0x656b, 0x7420, 0x6568, 0x7420, 0x6972, 0x6767, +0x7265, 0x7220, 0x7065, 0x6165, 0x6974, 0x676e, 0x0020, + 0 +END + +IDD_TRIGGERS DLGINIT +BEGIN + IDC_TRIGGER2, 0x403, 7, 0 +0x6e3c, 0x6e6f, 0x3e65, "\000" + 0 +END + +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_AITRIGGERTYPES$(RA2_MODE) DLGINIT +#else +IDD_AITRIGGERTYPES DLGINIT +#endif +BEGIN + IDC_FLAG2, 0x403, 8, 0 +0x312d, 0x4e20, 0x6e6f, 0x0065, + IDC_FLAG2, 0x403, 37, 0 +0x2030, 0x6e45, 0x6d65, 0x2079, 0x776f, 0x736e, 0x2820, 0x4f43, 0x444e, +0x5449, 0x4f49, 0x294e, 0x4e20, 0x6f20, 0x2066, 0x7974, 0x6570, 0x5820, +"\000" + IDC_FLAG2, 0x403, 37, 0 +0x2031, 0x6f48, 0x7375, 0x2065, 0x776f, 0x736e, 0x2820, 0x4f43, 0x444e, +0x5449, 0x4f49, 0x294e, 0x4e20, 0x6f20, 0x2066, 0x7974, 0x6570, 0x5820, +"\000" + IDC_FLAG2, 0x403, 22, 0 +0x2032, 0x6e45, 0x6d65, 0x3a79, 0x5920, 0x6c65, 0x6f6c, 0x2077, 0x6f70, +0x6577, 0x0072, + IDC_FLAG2, 0x403, 19, 0 +0x2033, 0x6e45, 0x6d65, 0x3a79, 0x5220, 0x6465, 0x7020, 0x776f, 0x7265, +"\000" + IDC_FLAG2, 0x403, 33, 0 +0x2034, 0x6e45, 0x6d65, 0x2079, 0x776f, 0x736e, 0x2820, 0x4f43, 0x444e, +0x5449, 0x4f49, 0x294e, 0x4e20, 0x6d20, 0x6e6f, 0x7965, "\000" + IDC_FLAG2, 0x403, 26, 0 +0x2035, 0x7249, 0x6e6f, 0x6320, 0x7275, 0x6174, 0x6e69, 0x6e20, 0x6165, +0x2072, 0x6572, 0x6461, 0x0079, + IDC_FLAG2, 0x403, 26, 0 +0x2036, 0x6843, 0x6f72, 0x6f6e, 0x7073, 0x6568, 0x6572, 0x6e20, 0x6165, +0x2072, 0x6572, 0x6461, 0x0079, + IDC_FLAG2, 0x403, 39, 0 +0x2037, 0x654e, 0x7475, 0x6172, 0x206c, 0x776f, 0x736e, 0x2820, 0x4f43, +0x444e, 0x5449, 0x4f49, 0x294e, 0x4e20, 0x6f20, 0x2066, 0x7974, 0x6570, +0x5820, "\000" + IDC_DATA, 0x403, 65, 0 +0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, +0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, +0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, +0x3030, 0x3030, 0x3030, 0x3030, 0x3030, "\000" + IDC_MULTISIDE, 0x403, 7, 0 +0x2030, 0x6f4e, 0x656e, "\000" + IDC_MULTISIDE, 0x403, 9, 0 +0x2031, 0x6c41, 0x696c, 0x6465, "\000" + IDC_MULTISIDE, 0x403, 9, 0 +0x2032, 0x6f53, 0x6976, 0x7465, "\000" + IDC_MULTISIDE, 0x403, 8, 0 +0x2033, 0x6854, 0x7269, 0x0064, + IDC_CONDITION, 0x403, 10, 0 +0x656c, 0x7373, 0x7420, 0x6168, 0x006e, + IDC_CONDITION, 0x403, 22, 0 +0x656c, 0x7373, 0x7420, 0x6168, 0x206e, 0x726f, 0x6520, 0x7571, 0x6c61, +0x7420, 0x006f, + IDC_CONDITION, 0x403, 9, 0 +0x7165, 0x6175, 0x206c, 0x6f74, "\000" + IDC_CONDITION, 0x403, 25, 0 +0x7267, 0x6165, 0x6574, 0x2072, 0x6874, 0x6e61, 0x6f20, 0x2072, 0x7165, +0x6175, 0x206c, 0x6f74, "\000" + IDC_CONDITION, 0x403, 13, 0 +0x7267, 0x6165, 0x6574, 0x2072, 0x6874, 0x6e61, "\000" + IDC_CONDITION, 0x403, 13, 0 +0x6f6e, 0x2074, 0x7165, 0x6175, 0x206c, 0x6f74, "\000" + 0 +END +#endif + +IDD_BASIC DLGINIT +BEGIN + IDC_ENDOFGAME, 0x403, 3, 0 +0x6f6e, "\000" + IDC_ENDOFGAME, 0x403, 4, 0 +0x6579, 0x0073, + IDC_SKIPSCORE, 0x403, 3, 0 +0x6f6e, "\000" + IDC_SKIPSCORE, 0x403, 4, 0 +0x6579, 0x0073, + IDC_ONETIMEONLY, 0x403, 3, 0 +0x6f6e, "\000" + IDC_ONETIMEONLY, 0x403, 4, 0 +0x6579, 0x0073, + IDC_SKIPMAPSELECT, 0x403, 3, 0 +0x6f6e, "\000" + IDC_SKIPMAPSELECT, 0x403, 4, 0 +0x6579, 0x0073, + IDC_OFFICIAL, 0x403, 3, 0 +0x6f6e, "\000" + IDC_OFFICIAL, 0x403, 4, 0 +0x6579, 0x0073, + IDC_IGNOREGLOBALAITRIGGERS, 0x403, 3, 0 +0x6f6e, "\000" + IDC_IGNOREGLOBALAITRIGGERS, 0x403, 4, 0 +0x6579, 0x0073, + IDC_TRUCKCRATE, 0x403, 3, 0 +0x6f6e, "\000" + IDC_TRUCKCRATE, 0x403, 4, 0 +0x6579, 0x0073, + IDC_TRAINCRATE, 0x403, 3, 0 +0x6f6e, "\000" + IDC_TRAINCRATE, 0x403, 4, 0 +0x6579, 0x0073, + IDC_TIBERIUMGROWTHENABLED, 0x403, 3, 0 +0x6f6e, "\000" + IDC_TIBERIUMGROWTHENABLED, 0x403, 4, 0 +0x6579, 0x0073, + IDC_VEINGROWTHENABLED, 0x403, 3, 0 +0x6f6e, "\000" + IDC_VEINGROWTHENABLED, 0x403, 4, 0 +0x6579, 0x0073, + IDC_ICEGROWTHENABLED, 0x403, 3, 0 +0x6f6e, "\000" + IDC_ICEGROWTHENABLED, 0x403, 4, 0 +0x6579, 0x0073, + IDC_TIBERIUMDEATHTOVISCEROID, 0x403, 3, 0 +0x6f6e, "\000" + IDC_TIBERIUMDEATHTOVISCEROID, 0x403, 4, 0 +0x6579, 0x0073, + IDC_FREERADAR, 0x403, 3, 0 +0x6f6e, "\000" + IDC_FREERADAR, 0x403, 4, 0 +0x6579, 0x0073, + IDC_REQUIREDADDON, 0x403, 2, 0 +0x0030, + IDC_REQUIREDADDON, 0x403, 2, 0 +0x0031, + 0 +END + +IDD_SINGLEPLAYER DLGINIT +BEGIN + IDC_STARTINGDROPSHIPS, 0x403, 2, 0 +0x0030, + IDC_STARTINGDROPSHIPS, 0x403, 2, 0 +0x0031, + IDC_TIMERINHERIT, 0x403, 4, 0 +0x6579, 0x0073, + IDC_TIMERINHERIT, 0x403, 3, 0 +0x6f6e, "\000" + IDC_FILLSILOS, 0x403, 4, 0 +0x6579, 0x0073, + IDC_FILLSILOS, 0x403, 3, 0 +0x6f6e, "\000" + 0 +END + +IDD_SCRIPTTYPES DLGINIT +BEGIN + IDC_TYPE, 0x403, 32, 0 +0x2030, 0x202d, 0x7441, 0x6174, 0x6b63, 0x7420, 0x7261, 0x6567, 0x2074, +0x7428, 0x7261, 0x6567, 0x2074, 0x7974, 0x6570, 0x0029, + IDC_TYPE, 0x403, 38, 0 +0x2031, 0x202d, 0x7441, 0x6174, 0x6b63, 0x7720, 0x7961, 0x6f70, 0x6e69, +0x2074, 0x7728, 0x7961, 0x6f70, 0x6e69, 0x2074, 0x756e, 0x626d, 0x7265, +0x0029, + IDC_TYPE, 0x403, 39, 0 +0x2033, 0x202d, 0x6f4d, 0x6576, 0x7420, 0x206f, 0x6177, 0x7079, 0x696f, +0x746e, 0x2820, 0x6177, 0x7079, 0x696f, 0x746e, 0x6e20, 0x6d75, 0x6562, +0x2972, "\000" + IDC_TYPE, 0x403, 58, 0 +0x2034, 0x202d, 0x6f4d, 0x6576, 0x7420, 0x206f, 0x6563, 0x6c6c, 0x2820, +0x6177, 0x7079, 0x696f, 0x746e, 0x7620, 0x6c61, 0x6575, 0x2820, 0x5820, +0x5858, 0x5959, 0x2c59, 0x6120, 0x2074, 0x656c, 0x7361, 0x2074, 0x5958, +0x5959, 0x0029, + IDC_TYPE, 0x403, 37, 0 +0x2035, 0x202d, 0x7547, 0x7261, 0x2064, 0x7261, 0x6165, 0x2820, 0x6974, +0x656d, 0x7520, 0x696e, 0x7374, 0x7420, 0x206f, 0x7567, 0x7261, 0x2964, +"\000" + IDC_TYPE, 0x403, 36, 0 +0x2036, 0x202d, 0x754a, 0x706d, 0x7420, 0x206f, 0x6361, 0x6974, 0x6e6f, +0x2320, 0x2820, 0x6361, 0x6974, 0x6e6f, 0x7420, 0x206f, 0x6f67, 0x0029, + + IDC_TYPE, 0x403, 18, 0 +0x2037, 0x202d, 0x7441, 0x6174, 0x6b63, 0x7420, 0x7261, 0x6f63, 0x006d, + + IDC_TYPE, 0x403, 46, 0 +0x2038, 0x202d, 0x6e55, 0x6f6c, 0x6461, 0x6320, 0x7261, 0x6f67, 0x2820, +0x7073, 0x696c, 0x2074, 0x7274, 0x6e61, 0x7073, 0x726f, 0x2074, 0x6e61, +0x2064, 0x7274, 0x6f6f, 0x7370, 0x0029, + IDC_TYPE, 0x403, 24, 0 +0x2039, 0x202d, 0x6544, 0x6c70, 0x796f, 0x2820, 0x6170, 0x6172, 0x206d, +0x7369, 0x3020, 0x0029, + IDC_TYPE, 0x403, 30, 0 +0x3131, 0x2d20, 0x4420, 0x206f, 0x6562, 0x6168, 0x6976, 0x756f, 0x2072, +0x6228, 0x6865, 0x7661, 0x6f69, 0x7275, 0x0029, + IDC_TYPE, 0x403, 32, 0 +0x3431, 0x2d20, 0x4c20, 0x616f, 0x2064, 0x6e6f, 0x7420, 0x6172, 0x736e, +0x6f70, 0x7472, 0x2073, 0x7528, 0x6573, 0x3020, 0x0029, + IDC_TYPE, 0x403, 42, 0 +0x3631, 0x2d20, 0x5020, 0x7461, 0x6f72, 0x206c, 0x6f74, 0x7720, 0x7961, +0x6f70, 0x6e69, 0x2074, 0x7728, 0x7961, 0x6f70, 0x6e69, 0x2074, 0x756e, +0x626d, 0x7265, 0x0029, + IDC_TYPE, 0x403, 46, 0 +0x3032, 0x2d20, 0x4320, 0x6168, 0x676e, 0x2065, 0x6f68, 0x7375, 0x2065, +0x6e28, 0x6d75, 0x6562, 0x2072, 0x666f, 0x6e20, 0x7765, 0x6f20, 0x6e77, +0x7265, 0x6820, 0x756f, 0x6573, 0x0029, + IDC_TYPE, 0x403, 23, 0 +0x3733, 0x2d20, 0x4c20, 0x6165, 0x6576, 0x6d20, 0x7061, 0x2820, 0x7375, +0x2065, 0x2930, "\000" + IDC_TYPE, 0x403, 25, 0 +0x3933, 0x2d20, 0x5320, 0x7465, 0x6720, 0x6f6c, 0x6162, 0x206c, 0x6728, +0x6f6c, 0x6162, 0x296c, "\000" + IDC_TYPE, 0x403, 19, 0 +0x3034, 0x2d20, 0x4320, 0x656c, 0x7261, 0x6720, 0x6f6c, 0x6162, 0x3f6c, +"\000" + IDC_TYPE, 0x403, 25, 0 +0x3234, 0x2d20, 0x5420, 0x7275, 0x206e, 0x6e69, 0x6f74, 0x6420, 0x7269, +0x6365, 0x6974, 0x6e6f, "\000" + IDC_TYPE, 0x403, 16, 0 +0x3434, 0x2d20, 0x4c20, 0x616f, 0x2064, 0x6163, 0x6772, 0x006f, + IDC_TYPE, 0x403, 18, 0 +0x3534, 0x2d20, 0x5520, 0x6c6e, 0x616f, 0x2064, 0x6163, 0x6772, 0x006f, + + IDC_TYPE, 0x403, 29, 0 +0x3634, 0x2d20, 0x4120, 0x7474, 0x6361, 0x206b, 0x6174, 0x6772, 0x7465, +0x7320, 0x7274, 0x6375, 0x7574, 0x6572, "\000" + IDC_TYPE, 0x403, 30, 0 +0x3734, 0x2d20, 0x4d20, 0x766f, 0x2065, 0x6f74, 0x7420, 0x7261, 0x6567, +0x2074, 0x7473, 0x7572, 0x7463, 0x7275, 0x0065, + 0 +END + +IDD_NEWMAP DLGINIT +BEGIN + IDC_GROUNDHEIGHT, 0x403, 2, 0 +0x0030, + IDC_GROUNDHEIGHT, 0x403, 2, 0 +0x0031, + IDC_GROUNDHEIGHT, 0x403, 2, 0 +0x0032, + IDC_GROUNDHEIGHT, 0x403, 2, 0 +0x0033, + IDC_GROUNDHEIGHT, 0x403, 2, 0 +0x0034, + IDC_GROUNDHEIGHT, 0x403, 2, 0 +0x0035, + IDC_GROUNDHEIGHT, 0x403, 2, 0 +0x0036, + IDC_GROUNDHEIGHT, 0x403, 2, 0 +0x0037, + IDC_GROUNDHEIGHT, 0x403, 2, 0 +0x0038, + IDC_GROUNDHEIGHT, 0x403, 2, 0 +0x0039, + IDC_GROUNDHEIGHT, 0x403, 3, 0 +0x3031, "\000" + 0 +END + +IDD_TOOLSETTINGS DLGINIT +BEGIN + IDC_BRUSHSIZE, 0x403, 4, 0 +0x7831, 0x0031, + IDC_BRUSHSIZE, 0x403, 4, 0 +0x7832, 0x0032, + IDC_BRUSHSIZE, 0x403, 4, 0 +0x7833, 0x0033, + IDC_BRUSHSIZE, 0x403, 4, 0 +0x7834, 0x0034, + IDC_BRUSHSIZE, 0x403, 4, 0 +0x7835, 0x0035, + IDC_BRUSHSIZE, 0x403, 6, 0 +0x3031, 0x3178, 0x0030, + IDC_BRUSHSIZE, 0x403, 4, 0 +0x7831, 0x0032, + IDC_BRUSHSIZE, 0x403, 4, 0 +0x7832, 0x0031, + IDC_BRUSHSIZE, 0x403, 4, 0 +0x7831, 0x0033, + IDC_BRUSHSIZE, 0x403, 4, 0 +0x7833, 0x0031, + 0 +END + +IDD_TRIGGEROPTIONS DLGINIT +BEGIN + IDC_TRIGGERTYPE, 0x403, 13, 0 +0x2030, 0x202d, 0x7453, 0x6e61, 0x6164, 0x6472, "\000" + IDC_TRIGGERTYPE, 0x403, 14, 0 +0x2032, 0x202d, 0x6552, 0x6570, 0x7461, 0x6e69, 0x0067, + IDC_HOUSE, 0x403, 13, 0 +0x2030, 0x202d, 0x7453, 0x6e61, 0x6164, 0x6472, "\000" + IDC_HOUSE, 0x403, 14, 0 +0x2032, 0x202d, 0x6552, 0x6570, 0x7461, 0x6e69, 0x0067, + 0 +END + +IDD_GLOBALS DLGINIT +BEGIN + IDC_VALUE, 0x403, 10, 0 +0x2030, 0x202d, 0x6c43, 0x6165, 0x0072, + IDC_VALUE, 0x403, 8, 0 +0x2031, 0x202d, 0x6553, 0x0074, + 0 +END + +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_TEAMTYPES$(RA2_MODE) DLGINIT +#else +IDD_TEAMTYPES DLGINIT +#endif +BEGIN + IDC_TECHLEVEL, 0x403, 2, 0 +0x0030, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0031, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0032, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0033, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0034, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0035, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0036, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0037, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0038, + IDC_TECHLEVEL, 0x403, 2, 0 +0x0039, + IDC_TECHLEVEL, 0x403, 3, 0 +0x3031, "\000" + IDC_GROUP, 0x403, 3, 0 +0x312d, "\000" + IDC_VETERANLEVEL, 0x403, 2, 0 +0x0031, + IDC_VETERANLEVEL, 0x403, 2, 0 +0x0032, + IDC_VETERANLEVEL, 0x403, 2, 0 +0x0033, + IDC_MINDCONTROLDECISION, 0x403, 17, 0 +0x2030, 0x202d, 0x443c, 0x6e6f, 0x7427, 0x6320, 0x7261, 0x3e65, "\000" + IDC_MINDCONTROLDECISION, 0x403, 16, 0 +0x2031, 0x202d, 0x6441, 0x2064, 0x6f54, 0x5420, 0x6165, 0x006d, + IDC_MINDCONTROLDECISION, 0x403, 19, 0 +0x2032, 0x202d, 0x7550, 0x2074, 0x6e69, 0x4720, 0x6972, 0x646e, 0x7265, +"\000" + IDC_MINDCONTROLDECISION, 0x403, 23, 0 +0x2033, 0x202d, 0x7550, 0x2074, 0x6e69, 0x4220, 0x6f69, 0x5220, 0x6165, +0x7463, 0x726f, "\000" + IDC_MINDCONTROLDECISION, 0x403, 15, 0 +0x2034, 0x202d, 0x6f47, 0x7420, 0x206f, 0x7548, 0x746e, "\000" + IDC_MINDCONTROLDECISION, 0x403, 15, 0 +0x2035, 0x202d, 0x6f44, 0x4e20, 0x746f, 0x6968, 0x676e, "\000" + 0 +END +#endif + +IDD_NEWMAPCREATENEW DLGINIT +BEGIN + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0030, + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0031, + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0032, + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0033, + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0034, + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0035, + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0036, + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0037, + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0038, + 0 +END + +IDD_NEWMAPBITMAP DLGINIT +BEGIN + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0030, + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0031, + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0032, + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0033, + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0034, + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0035, + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0036, + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0037, + IDC_STARTINGHEIGHT, 0x403, 2, 0 +0x0038, + 0 +END + +IDD_UNIT DLGINIT +BEGIN + IDC_STATE, 0x403, 6, 0 +0x6c53, 0x6565, 0x0070, + IDC_STATE, 0x403, 9, 0 +0x6148, 0x6d72, 0x656c, 0x7373, "\000" + IDC_STATE, 0x403, 7, 0 +0x7453, 0x6369, 0x796b, "\000" + IDC_STATE, 0x403, 7, 0 +0x7441, 0x6174, 0x6b63, "\000" + IDC_STATE, 0x403, 5, 0 +0x6f4d, 0x6576, "\000" + IDC_STATE, 0x403, 7, 0 +0x6150, 0x7274, 0x6c6f, "\000" + IDC_STATE, 0x403, 6, 0 +0x4d51, 0x766f, 0x0065, + IDC_STATE, 0x403, 8, 0 +0x6552, 0x7274, 0x6165, 0x0074, + IDC_STATE, 0x403, 6, 0 +0x7547, 0x7261, 0x0064, + IDC_STATE, 0x403, 6, 0 +0x6e45, 0x6574, 0x0072, + IDC_STATE, 0x403, 8, 0 +0x6143, 0x7470, 0x7275, 0x0065, + IDC_STATE, 0x403, 8, 0 +0x6148, 0x7672, 0x7365, 0x0074, + IDC_STATE, 0x403, 11, 0 +0x7241, 0x6165, 0x4720, 0x6175, 0x6472, "\000" + IDC_STATE, 0x403, 17, 0 +0x6552, 0x7574, 0x6e72, 0x3c20, 0x6e75, 0x7375, 0x6465, 0x3e21, "\000" + IDC_STATE, 0x403, 5, 0 +0x7453, 0x706f, "\000" + IDC_STATE, 0x403, 17, 0 +0x6d41, 0x7562, 0x6873, 0x3c20, 0x6e75, 0x7375, 0x6465, 0x3e21, "\000" + IDC_STATE, 0x403, 5, 0 +0x7548, 0x746e, "\000" + IDC_STATE, 0x403, 7, 0 +0x6e55, 0x6f6c, 0x6461, "\000" + IDC_STATE, 0x403, 9, 0 +0x6153, 0x6f62, 0x6174, 0x6567, "\000" + IDC_STATE, 0x403, 13, 0 +0x6f43, 0x736e, 0x7274, 0x6375, 0x6974, 0x6e6f, "\000" + IDC_STATE, 0x403, 8, 0 +0x6553, 0x6c6c, 0x6e69, 0x0067, + IDC_STATE, 0x403, 7, 0 +0x6552, 0x6170, 0x7269, "\000" + IDC_STATE, 0x403, 7, 0 +0x6552, 0x6373, 0x6575, "\000" + IDC_STATE, 0x403, 8, 0 +0x694d, 0x7373, 0x6c69, 0x0065, + IDC_STATE, 0x403, 5, 0 +0x704f, 0x6e65, "\000" + IDC_TAG, 0x403, 5, 0 +0x6f4e, 0x656e, "\000" + IDC_DIRECTION, 0x403, 2, 0 +0x0030, + IDC_DIRECTION, 0x403, 3, 0 +0x3233, "\000" + IDC_DIRECTION, 0x403, 3, 0 +0x3436, "\000" + IDC_DIRECTION, 0x403, 3, 0 +0x3639, "\000" + IDC_DIRECTION, 0x403, 4, 0 +0x3231, 0x0038, + IDC_DIRECTION, 0x403, 4, 0 +0x3631, 0x0030, + IDC_DIRECTION, 0x403, 4, 0 +0x3931, 0x0032, + IDC_DIRECTION, 0x403, 4, 0 +0x3232, 0x0034, + 0 +END + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_AITRIGGERTYPES$(TS_MODE) DLGINIT +#else +IDD_AITRIGGERTYPES DLGINIT +#endif +BEGIN + IDC_FLAG2, 0x403, 8, 0 +0x312d, 0x4e20, 0x6e6f, 0x0065, + IDC_FLAG2, 0x403, 37, 0 +0x2030, 0x6e45, 0x6d65, 0x2079, 0x776f, 0x736e, 0x2820, 0x4f43, 0x444e, +0x5449, 0x4f49, 0x294e, 0x4e20, 0x6f20, 0x2066, 0x7974, 0x6570, 0x5820, +"\000" + IDC_FLAG2, 0x403, 37, 0 +0x2031, 0x6f48, 0x7375, 0x2065, 0x776f, 0x736e, 0x2820, 0x4f43, 0x444e, +0x5449, 0x4f49, 0x294e, 0x4e20, 0x6f20, 0x2066, 0x7974, 0x6570, 0x5820, +"\000" + IDC_FLAG2, 0x403, 22, 0 +0x2032, 0x6e45, 0x6d65, 0x3a79, 0x5920, 0x6c65, 0x6f6c, 0x2077, 0x6f70, +0x6577, 0x0072, + IDC_FLAG2, 0x403, 19, 0 +0x2033, 0x6e45, 0x6d65, 0x3a79, 0x5220, 0x6465, 0x7020, 0x776f, 0x7265, +"\000" + IDC_FLAG2, 0x403, 33, 0 +0x2034, 0x6e45, 0x6d65, 0x2079, 0x776f, 0x736e, 0x2820, 0x4f43, 0x444e, +0x5449, 0x4f49, 0x294e, 0x4e20, 0x6d20, 0x6e6f, 0x7965, "\000" + IDC_DATA, 0x403, 65, 0 +0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, +0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, +0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, +0x3030, 0x3030, 0x3030, 0x3030, 0x3030, "\000" + IDC_MULTISIDE, 0x403, 7, 0 +0x2030, 0x6f4e, 0x656e, "\000" + IDC_MULTISIDE, 0x403, 6, 0 +0x2031, 0x4447, 0x0049, + IDC_MULTISIDE, 0x403, 6, 0 +0x2032, 0x6f4e, 0x0064, + IDC_CONDITION, 0x403, 10, 0 +0x656c, 0x7373, 0x7420, 0x6168, 0x006e, + IDC_CONDITION, 0x403, 22, 0 +0x656c, 0x7373, 0x7420, 0x6168, 0x206e, 0x726f, 0x6520, 0x7571, 0x6c61, +0x7420, 0x006f, + IDC_CONDITION, 0x403, 9, 0 +0x7165, 0x6175, 0x206c, 0x6f74, "\000" + IDC_CONDITION, 0x403, 25, 0 +0x7267, 0x6165, 0x6574, 0x2072, 0x6874, 0x6e61, 0x6f20, 0x2072, 0x7165, +0x6175, 0x206c, 0x6f74, "\000" + IDC_CONDITION, 0x403, 13, 0 +0x7267, 0x6165, 0x6574, 0x2072, 0x6874, 0x6e61, "\000" + IDC_CONDITION, 0x403, 13, 0 +0x6f6e, 0x2074, 0x7165, 0x6175, 0x206c, 0x6f74, "\000" + 0 +END +#endif + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +#if defined(APSTUDIO_INVOKED) || defined(YR_MODE) +#if defined(APSTUDIO_INVOKED) +IDR_MAINFRAME$(YR_MODE) ICON "res\\FinalAlert2YR.ico" + +#else +IDR_MAINFRAME ICON "res\\FinalAlert2YR.ico" + +#endif +#endif +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE_ICON) +#if defined(APSTUDIO_INVOKED) +IDR_MAINFRAME$(RA2_MODE_ICON) ICON "res\\FinalAlert2.ico" + +#else +IDR_MAINFRAME ICON "res\\FinalAlert2.ico" + +#endif +#endif +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDR_MAINFRAME$(TS_MODE) ICON "res\\FinalSun.ico" + +#else +IDR_MAINFRAME ICON "res\\FinalSun.ico" + +#endif +#endif + +///////////////////////////////////////////////////////////////////////////// +// +// WAVE +// + +IDR_WAVE1 WAVE "RES\\uacbopen.wav" + +IDR_WAVE2 WAVE "RES\\ugamclos.wav" + +IDR_WAVE3 WAVE "RES\\umenscol.wav" + +IDR_WAVE4 WAVE "RES\\uqeue.wav" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +VS_VERSION_INFO$(RA2_MODE) VERSIONINFO +#else +VS_VERSION_INFO VERSIONINFO +#endif + FILEVERSION 1,0,0,2 + PRODUCTVERSION 1,0,0,2 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x2bL +#else + FILEFLAGS 0x2aL +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "FinalAlert 2: Yuri's Revenge Mission Editor" + VALUE "CompanyName", "Electronic Arts, Inc." + VALUE "FileDescription", "FinalAlert 2: Yuri's Revenge" + VALUE "FileVersion", "2.00" + VALUE "InternalName", "FinalAlert 2: Yuri's Revenge Mission Editor" + VALUE "LegalCopyright", "Copyright (C) 1999-2024 Electronic Arts, Inc." + VALUE "LegalTrademarks", "FinalAlert 2: Yuri's Revenge" + VALUE "OriginalFilename", "FinalAlert2YR.EXE" + VALUE "ProductName", "FinalAlert 2: Yuri's Revenge" + VALUE "ProductVersion", "2.00" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +VS_VERSION_INFO$(TS_MODE) VERSIONINFO +#else +VS_VERSION_INFO VERSIONINFO +#endif + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x23L +#else + FILEFLAGS 0x22L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "FinalSun Mission Editor" + VALUE "CompanyName", "Electronic Arts, Inc." + VALUE "FileDescription", "FinalSun" + VALUE "FileVersion", "2.00" + VALUE "InternalName", "FinalSun Mission Editor" + VALUE "LegalCopyright", "Copyright (C) 1999-2024 Electronic Arts, Inc." + VALUE "LegalTrademarks", "FinalSun" + VALUE "OriginalFilename", "FinalSun.EXE" + VALUE "ProductName", "FinalSun" + VALUE "ProductVersion", "2.00" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END +#endif + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDR_MAIN$(TS_MODE) MENU +#else +IDR_MAIN MENU +#endif +BEGIN + POPUP "File" + BEGIN + MENUITEM "New", ID_FILE_NEW + MENUITEM SEPARATOR + MENUITEM "Open", ID_FILE_OPENMAP + MENUITEM SEPARATOR + MENUITEM "Save", ID_FILE_SAVE + MENUITEM "Save as", ID_FILE_SAVEAS + MENUITEM SEPARATOR + MENUITEM "Check map", ID_FILE_VALIDATEMAP + MENUITEM SEPARATOR + MENUITEM "Quit", ID_FILE_QUIT + END + POPUP "Edit" + BEGIN + MENUITEM "Undo\tCtrl+Z", ID_EDIT_UNDO + MENUITEM "Redo\tCtrl+Y", ID_EDIT_REDO + MENUITEM SEPARATOR + MENUITEM "Copy\tCtrl+C", ID_EDIT_COPY + MENUITEM "Copy whole map", ID_EDIT_COPYWHOLEMAP + MENUITEM "Paste\tCtrl+V", ID_EDIT_PASTE + MENUITEM "Paste centered", ID_EDIT_PASTEWHOLEMAP + MENUITEM SEPARATOR + MENUITEM "Map", ID_EDIT_MAP + MENUITEM "Basic", ID_EDIT_BASICSETTINGS + MENUITEM "Special flags", ID_EDIT_SPECIALFLAGS + MENUITEM "Lighting", ID_EDIT_LIGHTING + MENUITEM SEPARATOR + MENUITEM "Singleplayer settings", ID_EDIT_SINGLEPLAYERSETTINGS + MENUITEM SEPARATOR + MENUITEM "Houses", ID_EDIT_HOUSES + MENUITEM SEPARATOR + MENUITEM "Local variables (Locals)", ID_EDIT_GLOBALVARIABLES + MENUITEM SEPARATOR + MENUITEM "Trigger editor", ID_EDIT_TRIGGEREDITOR + MENUITEM "Tag editor", ID_EDIT_TAGS + MENUITEM SEPARATOR + MENUITEM "Scripts", ID_EDIT_SCRIPTS + MENUITEM SEPARATOR + MENUITEM "Taskforces", ID_EDIT_TASKFORCES + MENUITEM "Teams", ID_EDIT_TEAMS + MENUITEM SEPARATOR + MENUITEM "AI Triggers", ID_EDIT_AITRIGGERS + MENUITEM "AI Trigger enabling", ID_EDIT_AITRIGGERENABLING + MENUITEM SEPARATOR + MENUITEM "INI editing", ID_EDIT_INIEDITING + END + POPUP "Terrain" + BEGIN + MENUITEM "Raise ground", ID_TERRAIN_HEIGHTENGROUND + MENUITEM "Lower ground", ID_TERRAIN_LOWERGROUND + MENUITEM "Flatten ground", ID_TERRAIN_FLATTEN + MENUITEM SEPARATOR + MENUITEM "Hide tileset", ID_TERRAIN_CLOAK + MENUITEM "Show every tileset", ID_TERRAIN_SHOWEVERYTILE + MENUITEM "Hide single field", ID_TERRAIN_HIDEFIELD + MENUITEM "Show all fields", ID_TERRAIN_SHOWALLFIELDS + MENUITEM SEPARATOR + MENUITEM "Raise single tile (Be careful!)", ID_TERRAIN_RAISETILE + MENUITEM "Lower single tile (Be careful!)", ID_TERRAIN_LOWERTILE + END + POPUP "Map tools" + BEGIN + MENUITEM "Change map height", ID_MAPTOOLS_CHANGEMAPHEIGHT + MENUITEM SEPARATOR + MENUITEM "Autocreate shores", ID_MAPTOOLS_AUTOCREATESHORES + MENUITEM "Auto level using cliffs", ID_MAPTOOLS_AUTOLEVEL + MENUITEM SEPARATOR + MENUITEM "Paint cliff front", ID_MAPTOOLS_FRONTCLIFF + MENUITEM "Paint cliff back", ID_MAPTOOLS_BACKCLIFF + MENUITEM SEPARATOR + MENUITEM "Search Waypoint", ID_MAPTOOLS_SEARCHWAYPOINT + MENUITEM SEPARATOR + MENUITEM "Tool Scripts", ID_MAPTOOLS_TOOLSCRIPTS + END + POPUP "Options" + BEGIN + MENUITEM "Settings", ID_OPTIONS_TIBERIANSUNOPTIONS + MENUITEM "Show minimap", ID_OPTIONS_SHOWMINIMAP + MENUITEM "Easy mode", ID_OPTIONS_SIMPLEVIEW + MENUITEM "Sounds", ID_OPTIONS_SOUNDS + MENUITEM "Show Building Outline", ID_OPTIONS_SHOWBUILDINGOUTLINE + MENUITEM "Disable AutoShore\tCTRL-A", ID_OPTIONS_DISABLEAUTOSHORE + MENUITEM "Disable AutoLat\tCTRL-L", ID_OPTIONS_DISABLEAUTOLAT + MENUITEM "Disable Slope Correction", ID_OPTIONS_DISABLESLOPECORRECTION + MENUITEM "Smooth zoom", ID_OPTIONS_SMOOTHZOOM + MENUITEM "Use default mouse cursor", ID_OPTIONS_USEDEFAULTMOUSECURSOR + END + POPUP "Help" + BEGIN + MENUITEM "Manual\tF1", ID_HELP + MENUITEM SEPARATOR + MENUITEM "Info", ID_HELP_INFO + MENUITEM "Tip of the day", ID_HELP_TIPOFTHEDAY + MENUITEM SEPARATOR + MENUITEM "Show logs", ID_HELP_SHOWLOGS + END +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDR_MAIN$(RA2_MODE) MENU +#else +IDR_MAIN MENU +#endif +BEGIN + POPUP "File" + BEGIN + MENUITEM "New", ID_FILE_NEW + MENUITEM SEPARATOR + MENUITEM "Open", ID_FILE_OPENMAP + MENUITEM SEPARATOR + MENUITEM "Save", ID_FILE_SAVE + MENUITEM "Save as", ID_FILE_SAVEAS + MENUITEM SEPARATOR + MENUITEM "Check map", ID_FILE_VALIDATEMAP + MENUITEM SEPARATOR + MENUITEM "Quit", ID_FILE_QUIT + END + POPUP "Edit" + BEGIN + MENUITEM "Undo\tCtrl+Z", ID_EDIT_UNDO + MENUITEM "Redo\tCtrl+Y", ID_EDIT_REDO + MENUITEM SEPARATOR + MENUITEM "Copy\tCtrl+C", ID_EDIT_COPY + MENUITEM "Copy whole map", ID_EDIT_COPYWHOLEMAP + MENUITEM "Paste\tCtrl+V", ID_EDIT_PASTE + MENUITEM "Paste centered", ID_EDIT_PASTEWHOLEMAP + MENUITEM SEPARATOR + MENUITEM "Map", ID_EDIT_MAP + MENUITEM "Basic", ID_EDIT_BASICSETTINGS + MENUITEM "Special flags", ID_EDIT_SPECIALFLAGS + MENUITEM "Lighting", ID_EDIT_LIGHTING + MENUITEM SEPARATOR + MENUITEM "Singleplayer settings", ID_EDIT_SINGLEPLAYERSETTINGS + MENUITEM SEPARATOR + MENUITEM "Houses", ID_EDIT_HOUSES + MENUITEM SEPARATOR + MENUITEM "Local variables (Locals)", ID_EDIT_GLOBALVARIABLES + MENUITEM SEPARATOR + MENUITEM "Trigger editor", ID_EDIT_TRIGGEREDITOR + MENUITEM "Tag editor", ID_EDIT_TAGS + MENUITEM SEPARATOR + MENUITEM "Scripts", ID_EDIT_SCRIPTS + MENUITEM SEPARATOR + MENUITEM "Taskforces", ID_EDIT_TASKFORCES + MENUITEM "Teams", ID_EDIT_TEAMS + MENUITEM SEPARATOR + MENUITEM "AI Triggers", ID_EDIT_AITRIGGERS + MENUITEM "AI Trigger enabling", ID_EDIT_AITRIGGERENABLING + MENUITEM SEPARATOR + MENUITEM "INI editing", ID_EDIT_INIEDITING + END + POPUP "Terrain" + BEGIN + MENUITEM "Raise ground", ID_TERRAIN_HEIGHTENGROUND + MENUITEM "Lower ground", ID_TERRAIN_LOWERGROUND + MENUITEM "Flatten ground", ID_TERRAIN_FLATTEN + MENUITEM SEPARATOR + MENUITEM "Hide tileset", ID_TERRAIN_CLOAK + MENUITEM "Show every tileset", ID_TERRAIN_SHOWEVERYTILE + MENUITEM "Hide single field", ID_TERRAIN_HIDEFIELD + MENUITEM "Show all fields", ID_TERRAIN_SHOWALLFIELDS + MENUITEM SEPARATOR + MENUITEM "Raise single tile (Be careful!)", ID_TERRAIN_RAISETILE + MENUITEM "Lower single tile (Be careful!)", ID_TERRAIN_LOWERTILE + END + POPUP "Map tools" + BEGIN + MENUITEM "Change map height", ID_MAPTOOLS_CHANGEMAPHEIGHT + MENUITEM SEPARATOR + MENUITEM "Autocreate shores", ID_MAPTOOLS_AUTOCREATESHORES + MENUITEM "Auto level using cliffs", ID_MAPTOOLS_AUTOLEVEL + MENUITEM SEPARATOR + MENUITEM "Paint cliff front", ID_MAPTOOLS_FRONTCLIFF + MENUITEM "Paint cliff back", ID_MAPTOOLS_BACKCLIFF + MENUITEM SEPARATOR + MENUITEM "Search Waypoint", ID_MAPTOOLS_SEARCHWAYPOINT + MENUITEM SEPARATOR + MENUITEM "Tool Scripts", ID_MAPTOOLS_TOOLSCRIPTS + END + POPUP "Options" + BEGIN + MENUITEM "Settings", ID_OPTIONS_TIBERIANSUNOPTIONS + MENUITEM "Show minimap", ID_OPTIONS_SHOWMINIMAP + MENUITEM "Easy mode", ID_OPTIONS_SIMPLEVIEW + MENUITEM "Sounds", ID_OPTIONS_SOUNDS + MENUITEM "Show Building Outline", ID_OPTIONS_SHOWBUILDINGOUTLINE + MENUITEM "Disable AutoShore\tCTRL-A", ID_OPTIONS_DISABLEAUTOSHORE + MENUITEM "Disable AutoLat\tCTRL-L", ID_OPTIONS_DISABLEAUTOLAT + MENUITEM "Disable Slope Correction", ID_OPTIONS_DISABLESLOPECORRECTION + MENUITEM "Smooth zoom", ID_OPTIONS_SMOOTHZOOM + MENUITEM "Use default mouse cursor", ID_OPTIONS_USEDEFAULTMOUSECURSOR + END + POPUP "Help" + BEGIN + MENUITEM "Manual\tF1", ID_HELP + MENUITEM SEPARATOR + MENUITEM "Info", ID_HELP_INFO + MENUITEM "Tip of the day", ID_HELP_TIPOFTHEDAY + MENUITEM SEPARATOR + MENUITEM "Show logs", ID_HELP_SHOWLOGS + END +END +#endif + + +///////////////////////////////////////////////////////////////////////////// +// +// Toolbar +// + +IDR_MAINFRAME TOOLBAR 16, 15 +BEGIN + BUTTON ID_FILE_NEW + BUTTON ID_FILE_OPENMAP + BUTTON ID_FILE_SAVE +END + +IDR_TERRAINBAR TOOLBAR 16, 15 +BEGIN + BUTTON ID_TERRAIN_HEIGHTENGROUND + BUTTON ID_TERRAIN_LOWERGROUND + BUTTON ID_TERRAIN_FLATTEN + BUTTON ID_TERRAIN_CLOAK + BUTTON ID_TERRAIN_SHOWEVERYTILE + BUTTON ID_TERRAIN_HIDEFIELD + BUTTON ID_TERRAIN_SHOWALLFIELDS + BUTTON ID_TERRAIN_RAISETILE + BUTTON ID_TERRAIN_LOWERTILE + SEPARATOR + BUTTON ID_MARBLEMADNESS +END + +IDR_CLIFFBAR TOOLBAR 16, 15 +BEGIN + BUTTON ID_MAPTOOLS_FRONTCLIFF + BUTTON ID_MAPTOOLS_BACKCLIFF + SEPARATOR + BUTTON ID_MAPTOOLS_AUTOLEVEL + BUTTON ID_MAPTOOLS_AUTOCREATESHORES +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_MAIN ACCELERATORS +BEGIN + "A", ID_OPTIONS_DISABLEAUTOSHORE, VIRTKEY, CONTROL, NOINVERT + "C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT + "F", ID_MARBLEMADNESS, VIRTKEY, CONTROL, NOINVERT + "L", ID_OPTIONS_DISABLEAUTOLAT, VIRTKEY, CONTROL, NOINVERT + "V", ID_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT + "Y", ID_EDIT_REDO, VIRTKEY, CONTROL, NOINVERT + "Z", ID_EDIT_UNDO, VIRTKEY, CONTROL, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// AFX_DIALOG_LAYOUT +// + +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_INFO$(RA2_MODE) AFX_DIALOG_LAYOUT +#else +IDD_INFO AFX_DIALOG_LAYOUT +#endif +BEGIN + 0 +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_INFO$(TS_MODE) AFX_DIALOG_LAYOUT +#else +IDD_INFO AFX_DIALOG_LAYOUT +#endif +BEGIN + 0 +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_LOADING$(RA2_MODE) AFX_DIALOG_LAYOUT +#else +IDD_LOADING AFX_DIALOG_LAYOUT +#endif +BEGIN + 0 +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_LOADING$(TS_MODE) AFX_DIALOG_LAYOUT +#else +IDD_LOADING AFX_DIALOG_LAYOUT +#endif +BEGIN + 0 +END +#endif + +IDD_FINALSUN_DIALOG AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +IDD_TIP AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +#if defined(APSTUDIO_INVOKED) || defined(TS_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_TSOPTIONS$(TS_MODE) AFX_DIALOG_LAYOUT +#else +IDD_TSOPTIONS AFX_DIALOG_LAYOUT +#endif +BEGIN + 0 +END +#endif + +#if defined(APSTUDIO_INVOKED) || defined(RA2_MODE) +#if defined(APSTUDIO_INVOKED) +IDD_TSOPTIONS$(RA2_MODE) AFX_DIALOG_LAYOUT +#else +IDD_TSOPTIONS AFX_DIALOG_LAYOUT +#endif +BEGIN + 0 +END +#endif + +IDD_TRIGGEREDITOR AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +IDD_TRIGGERACTIONS AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +IDD_TRIGGEREVENTS AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +IDD_TRIGGEROPTIONS AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +IDD_MAPVALIDATOR AFX_DIALOG_LAYOUT +BEGIN + 0 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_BUILTBY "Matthias Wagner" + IDS_VERSIONTEXT "Version 2.00" + IDS_VERSION "2.00" + IDS_VERSIONTEXTTS "Version 2.00" +END + +STRINGTABLE +BEGIN + ID_TERRAIN_HEIGHTENGROUND "Heighten ground (slope logic)" + ID_TERRAIN_LOWERGROUND "Lower ground (slope logic)" + ID_TERRAIN_PAINT "Paint terrain types" + ID_TERRAIN_RISETILE "Raise a single tile" + ID_TERRAIN_RAISETILE "Raise a single tile" + ID_TERRAIN_LOWERTILE "Lower a single tile" +END + +STRINGTABLE +BEGIN + ID_TERRAIN_FLATTEN "Make terrain flat" + ID_TERRAIN_CLOAK "Hide tileset" + ID_TERRAIN_SHOWEVERYTILE "Show all tilesets" + ID_TERRAIN_SHOWALLFIELDS "Show all fields" + ID_TERRAIN_HIDEFIELD "Hide single field" +END + +STRINGTABLE +BEGIN + ID_FILE_NEW "New map" + ID_FILE_SAVE "Save map" + IDS_LINEARVERSION "3" +END + +STRINGTABLE +BEGIN + ID_FILE_OPENMAP "Open map" +END + +STRINGTABLE +BEGIN + ID_MAPTOOLS_AUTOLEVEL "AutoLevel terrain height using cliffs" + ID_MAPTOOLS_FRONTCLIFF "Paint cliff front" + ID_MAPTOOLS_BACKCLIFF "Paint cliff back" +END + +STRINGTABLE +BEGIN + ID_MAPTOOLS_AUTOCREATESHORES "AutoCreate shores" +END + +STRINGTABLE +BEGIN + ID_MARBLEMADNESS "Switch Framework Mode" +END + +#endif // Englisch (USA) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(65001) +#endif //_WIN32 +#include "res\FinalSun.rc2" // Nicht mit Microsoft Visual C++ bearbeitete Ressourcen +#include "afxres.rc" // Standardkomponenten +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/MissionEditor/MultiSaveOptionsDlg.cpp b/MissionEditor/MultiSaveOptionsDlg.cpp new file mode 100644 index 0000000..dc9d3bb --- /dev/null +++ b/MissionEditor/MultiSaveOptionsDlg.cpp @@ -0,0 +1,63 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// MultiSaveOptionsDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "MultiSaveOptionsDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CMultiSaveOptionsDlg + + +CMultiSaveOptionsDlg::CMultiSaveOptionsDlg(CWnd* pParent /*=NULL*/) + : CDialog(CMultiSaveOptionsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CMultiSaveOptionsDlg) + m_mmx = 0; + //}}AFX_DATA_INIT +} + + +void CMultiSaveOptionsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMultiSaveOptionsDlg) + DDX_Radio(pDX, IDC_MMX, m_mmx); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CMultiSaveOptionsDlg, CDialog) + //{{AFX_MSG_MAP(CMultiSaveOptionsDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Zuordnungsmakros fĂ¼r Nachrichten ein + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CMultiSaveOptionsDlg diff --git a/MissionEditor/MultiSaveOptionsDlg.h b/MissionEditor/MultiSaveOptionsDlg.h new file mode 100644 index 0000000..0e0bcd4 --- /dev/null +++ b/MissionEditor/MultiSaveOptionsDlg.h @@ -0,0 +1,66 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_MULTISAVEOPTIONSDLG_H__72E7BEC1_E8B2_11D4_9C88_444553540000__INCLUDED_) +#define AFX_MULTISAVEOPTIONSDLG_H__72E7BEC1_E8B2_11D4_9C88_444553540000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// MultiSaveOptionsDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CMultiSaveOptionsDlg + +class CMultiSaveOptionsDlg : public CDialog +{ +// Konstruktion +public: + CMultiSaveOptionsDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CMultiSaveOptionsDlg) + enum { IDD = IDD_MULTISAVEOPT }; + int m_mmx; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CMultiSaveOptionsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CMultiSaveOptionsDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Member-Funktionen ein + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_MULTISAVEOPTIONSDLG_H__72E7BEC1_E8B2_11D4_9C88_444553540000__INCLUDED_ diff --git a/MissionEditor/MyComboBox.cpp b/MissionEditor/MyComboBox.cpp new file mode 100644 index 0000000..a3efe6e --- /dev/null +++ b/MissionEditor/MyComboBox.cpp @@ -0,0 +1,75 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// MyComboBox.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "MyComboBox.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMyComboBox + +CMyComboBox::CMyComboBox() +{ +} + +CMyComboBox::~CMyComboBox() +{ +} + + +BEGIN_MESSAGE_MAP(CMyComboBox, CComboBox) + //{{AFX_MSG_MAP(CMyComboBox) + ON_CONTROL_REFLECT(CBN_SELCHANGE, OnSelchange) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CMyComboBox + + +/* +This will automatically send a CBN_EDITCHANGE command. +Also it will set the window text to the selected item +*/ +void CMyComboBox::OnSelchange() +{ + CString SelectedItem; + GetLBText(GetCurSel(),SelectedItem); + + + SetWindowText(SelectedItem); + + WPARAM wparam; + int ctrlid=GetDlgCtrlID(); + WORD command=CBN_EDITCHANGE; + memcpy((BYTE*)&wparam+2, &command, 2); + memcpy((BYTE*)&wparam, &ctrlid, 2); + GetOwner()->SendMessage(WM_COMMAND,wparam,(LPARAM)m_hWnd); + +} diff --git a/MissionEditor/MyComboBox.h b/MissionEditor/MyComboBox.h new file mode 100644 index 0000000..500e3db --- /dev/null +++ b/MissionEditor/MyComboBox.h @@ -0,0 +1,68 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_MYCOMBOBOX_H__6B1D6F02_A9A7_11D3_B63B_B4DF98412640__INCLUDED_) +#define AFX_MYCOMBOBOX_H__6B1D6F02_A9A7_11D3_B63B_B4DF98412640__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// MyComboBox.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Fenster CMyComboBox + +class CMyComboBox : public CComboBox +{ +// Konstruktion +public: + CMyComboBox(); + +// Attribute +public: + +// Operationen +public: + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CMyComboBox) + //}}AFX_VIRTUAL + +// Implementierung +public: + virtual ~CMyComboBox(); + + // Generierte Nachrichtenzuordnungsfunktionen +protected: + //{{AFX_MSG(CMyComboBox) + afx_msg void OnSelchange(); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_MYCOMBOBOX_H__6B1D6F02_A9A7_11D3_B63B_B4DF98412640__INCLUDED_ diff --git a/MissionEditor/MyViewFrame.cpp b/MissionEditor/MyViewFrame.cpp new file mode 100644 index 0000000..7f7cbbd --- /dev/null +++ b/MissionEditor/MyViewFrame.cpp @@ -0,0 +1,177 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// MyViewFrame.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "MyViewFrame.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMyViewFrame + +IMPLEMENT_DYNCREATE(CMyViewFrame, CFrameWnd) + +CMyViewFrame::CMyViewFrame() +{ + m_isoview=0; +} + +CMyViewFrame::~CMyViewFrame() +{ +} + + +BEGIN_MESSAGE_MAP(CMyViewFrame, CFrameWnd) + //{{AFX_MSG_MAP(CMyViewFrame) + ON_WM_SYSCOMMAND() + ON_WM_SIZE() + ON_WM_GETMINMAXINFO() + ON_WM_KEYDOWN() + ON_WM_KEYUP() + ON_WM_CHAR() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CMyViewFrame + +BOOL CMyViewFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) +{ + SIZE z; + z.cx=200; + z.cy=200; + + CRect r; + r.right=200; + r.bottom=200; + + + + if(!m_Splitter.CreateStatic(this,1,2)) return FALSE; + + + if(!m_Splitter.CreateView(0,0, + RUNTIME_CLASS(CViewObjects), + z, + pContext)) return FALSE; + + if(!m_Splitter.CreateView(0,1, + RUNTIME_CLASS(CRightFrame), + z, + pContext)) return FALSE; + + OutputDebugString("CMyViewFrame::OnCreateClient(): windows created\n"); + + m_rightFrame=(CRightFrame*)m_Splitter.GetPane(0,1); + + m_isoview=(CIsoView*)m_rightFrame->m_Splitter.GetPane(0,0); + m_isoview->owner=this; + m_browser=(CTileSetBrowserFrame*)m_rightFrame->m_Splitter.GetPane(1,0); + m_objectview=(CViewObjects*)m_Splitter.GetPane(0,0); + + // the minimap is not a child window right now, but it is created here though + auto miniMapClass = AfxRegisterWndClass(0, m_hArrowCursor, static_cast(::GetStockObject(GRAY_BRUSH))); + m_minimap.CreateEx(0, miniMapClass, "Minimap", WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE, r, NULL, 0); + //m_minimap.Create(NULL, "Minimap", WS_OVERLAPPED) + m_minimap.UpdateView(); + + if(!m_statbar.CreateEx(this,SBARS_SIZEGRIP | SBT_TOOLTIPS)) return FALSE; + + return CFrameWnd::OnCreateClient(lpcs, pContext); +} + +void CMyViewFrame::OnSysCommand(UINT nID, LPARAM lParam) +{ +if(nID==SC_CLOSE) + { + // ok now just hide the window + ShowWindow(SW_HIDE); + return; + } + CFrameWnd::OnSysCommand(nID, lParam); +} + +void CMyViewFrame::OnSize(UINT nType, int cx, int cy) +{ + // we now check if our frame window has already created its child windows + // this is true at the second OnSize + // TODO: replace static + static BOOL wasHere=FALSE; + if(wasHere==FALSE) + { + wasHere=TRUE; + return; + } + + CFrameWnd::OnSize(nType, cx, cy); + CStatusBarCtrl& stat=m_statbar.GetStatusBarCtrl(); + + m_statbar.ShowWindow(SW_SHOW); + CRect sr; + GetWindowRect(sr); + //int Widths[]={sr.right-80,80,-1}; + int Widths[]={sr.right-sr.left-130,-1}; + stat.SetParts(2, Widths); + stat.SetSimple(FALSE); + m_statbar.ShowWindow(SW_SHOW); +} + +void CMyViewFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) +{ + lpMMI->ptMinTrackSize.x=260; + lpMMI->ptMinTrackSize.y=150; + CFrameWnd::OnGetMinMaxInfo(lpMMI); +} + +void CMyViewFrame::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + m_isoview->SendMessage(WM_KEYDOWN, nChar, nFlags); + // CFrameWnd::OnKeyDown(nChar, nRepCnt, nFlags); +} + + + +void CMyViewFrame::PostNcDestroy() +{ + // do not call CFrameWnd::PostNcDestroy(), as long as MyViewFrame is not on the heap! + // CFrameWnd::PostNcDestroy(); +} + +void CMyViewFrame::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + // TODO: Code fĂ¼r die Behandlungsroutine fĂ¼r Nachrichten hier einfĂ¼gen und/oder Standard aufrufen + + // CFrameWnd::OnKeyUp(nChar, nRepCnt, nFlags); +} + +void CMyViewFrame::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + // TODO: Code fĂ¼r die Behandlungsroutine fĂ¼r Nachrichten hier einfĂ¼gen und/oder Standard aufrufen + + // CFrameWnd::OnChar(nChar, nRepCnt, nFlags); +} diff --git a/MissionEditor/MyViewFrame.h b/MissionEditor/MyViewFrame.h new file mode 100644 index 0000000..462a194 --- /dev/null +++ b/MissionEditor/MyViewFrame.h @@ -0,0 +1,90 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_MYVIEWFRAME_H__98929AE1_9B75_11D3_B63B_D046A7216340__INCLUDED_) +#define AFX_MYVIEWFRAME_H__98929AE1_9B75_11D3_B63B_D046A7216340__INCLUDED_ + +#include "IsoView.h" + +#if _MSC_VER > 1000 +#pragma once +#endif + +// MyViewFrame.h : Header file +// + +#include "isoview.h" +#include "viewobjects.h" +#include "MiniMap.h" +#include "RightFrame.h" +#include "TileSetBrowserFrame.h" + +///////////////////////////////////////////////////////////////////////////// +// Frame CMyViewFrame + +class CMyViewFrame : public CFrameWnd +{ + DECLARE_DYNCREATE(CMyViewFrame) +protected: + + +// attributes +public: + CMiniMap m_minimap; + CStatusBar m_statbar; + CViewObjects* m_objectview; + CIsoView* m_isoview; + CSplitterWnd m_Splitter; + +// operations +public: + CTileSetBrowserFrame* m_browser; + CRightFrame* m_rightFrame; + CMyViewFrame(); + ~CMyViewFrame(); + +// overwriteables + + //{{AFX_VIRTUAL(CMyViewFrame) + protected: + virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext); + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// implementation +protected: + + // generated message maps + //{{AFX_MSG(CMyViewFrame) + afx_msg void OnSysCommand(UINT nID, LPARAM lParam); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} + +#endif // AFX_MYVIEWFRAME_H__98929AE1_9B75_11D3_B63B_D046A7216340__INCLUDED_ diff --git a/MissionEditor/NewMap.cpp b/MissionEditor/NewMap.cpp new file mode 100644 index 0000000..c7b9e2d --- /dev/null +++ b/MissionEditor/NewMap.cpp @@ -0,0 +1,287 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// NewMap.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "NewMap.h" +#include "MapOpenDialog.h" +#include "resource.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" + +extern CFinalSunApp theApp; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CNewMap + + +CNewMap::CNewMap(CWnd* pParent /*=NULL*/) + : CDialog(CNewMap::IDD, pParent) +{ + //{{AFX_DATA_INIT(CNewMap) + m_ImportOverlay = FALSE; + m_ImportTrees = FALSE; + m_ImportUnits = FALSE; + m_Multiplayer = FALSE; + m_House = _T(""); + m_PrepareHouses = FALSE; + m_AutoProduction = FALSE; + m_Height = 0; + m_Width = 0; + m_Import = -1; + m_Theater = 0; + m_GroundHeight = 2; + //}}AFX_DATA_INIT +} + + +void CNewMap::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CNewMap) + DDX_Control(pDX, IDOK, m_OK); + DDX_Check(pDX, IDC_IMPORTOVERLAY, m_ImportOverlay); + DDX_Check(pDX, IDC_IMPORTTREES, m_ImportTrees); + DDX_Check(pDX, IDC_IMPORTUNITS, m_ImportUnits); + DDX_Check(pDX, IDC_MULTIPLAYER, m_Multiplayer); + DDX_CBString(pDX, IDC_HOUSE, m_House); + DDX_Check(pDX, IDC_PREPAREHOUSES, m_PrepareHouses); + DDX_Check(pDX, IDC_AUTOPROD, m_AutoProduction); + DDX_Text(pDX, IDC_HEIGHT, m_Height); + DDV_MinMaxUInt(pDX, m_Height, 8, 255); + DDX_Text(pDX, IDC_WIDTH, m_Width); + DDV_MinMaxUInt(pDX, m_Width, 8, 255); + DDX_Radio(pDX, IDC_IMPORT, m_Import); + DDX_CBIndex(pDX, IDC_THEATER, m_Theater); + DDX_CBIndex(pDX, IDC_GROUNDHEIGHT, m_GroundHeight); + DDX_Control(pDX, IDC_IMPORTFILE, m_ImportFile); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CNewMap, CDialog) + //{{AFX_MSG_MAP(CNewMap) + ON_BN_CLICKED(IDC_BROWSE, OnBrowse) + ON_BN_CLICKED(IDC_MULTIPLAYER, OnMultiplayer) + ON_CBN_EDITCHANGE(IDC_IMPORTFILE, OnEditchangeImportfile) + ON_BN_CLICKED(IDC_IMPORT, OnImport) + ON_BN_CLICKED(IDC_NEW, OnNew) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CNewMap + +BOOL CNewMap::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // preset some stuff + m_ImportOverlay=TRUE; + m_ImportUnits=TRUE; + m_OK.EnableWindow(FALSE); + m_ImportTrees=TRUE; + m_PrepareHouses=TRUE; + m_AutoProduction=TRUE; + m_Theater=0; + m_Import=1; + m_Width=64; + m_Height=64; + + + CComboBox& house=*((CComboBox*)(GetDlgItem(IDC_HOUSE))); + int i; + for(i=0;i. +*/ + +#if !defined(AFX_NEWMAP_H__868C3FC0_AF27_11D3_B63B_BE68077E9F41__INCLUDED_) +#define AFX_NEWMAP_H__868C3FC0_AF27_11D3_B63B_BE68077E9F41__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// NewMap.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CNewMap + +class CNewMap : public CDialog +{ +// Konstruktion +public: + CString m_MapToImport; + void UpdateStrings(); + CNewMap(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CNewMap) + enum { IDD = IDD_NEWMAP }; + CButton m_OK; + BOOL m_ImportOverlay; + BOOL m_ImportTrees; + BOOL m_ImportUnits; + BOOL m_Multiplayer; + CString m_House; + BOOL m_PrepareHouses; + BOOL m_AutoProduction; + UINT m_Height; + UINT m_Width; + int m_Import; + int m_Theater; + int m_GroundHeight; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CNewMap) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CNewMap) + virtual BOOL OnInitDialog(); + afx_msg void OnBrowse(); + virtual void OnOK(); + afx_msg void OnMultiplayer(); + afx_msg void OnEditchangeImportfile(); + afx_msg void OnImport(); + afx_msg void OnNew(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + CMyComboBox m_ImportFile; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_NEWMAP_H__868C3FC0_AF27_11D3_B63B_BE68077E9F41__INCLUDED_ diff --git a/MissionEditor/NewMapCreateDlg.cpp b/MissionEditor/NewMapCreateDlg.cpp new file mode 100644 index 0000000..2da20b7 --- /dev/null +++ b/MissionEditor/NewMapCreateDlg.cpp @@ -0,0 +1,75 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// NewMapCreateDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "NewMapCreateDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CNewMapCreateDlg + + +CNewMapCreateDlg::CNewMapCreateDlg(CWnd* pParent /*=NULL*/) + : CDialog(CNewMapCreateDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CNewMapCreateDlg) + m_CreateType = -1; + m_AITriggers = TRUE; + //}}AFX_DATA_INIT +} + + +void CNewMapCreateDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CNewMapCreateDlg) + DDX_Radio(pDX, IDC_CREATE, m_CreateType); + DDX_Check(pDX, IDC_AITRIGGERS, m_AITriggers); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CNewMapCreateDlg, CDialog) + //{{AFX_MSG_MAP(CNewMapCreateDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CNewMapCreateDlg + +BOOL CNewMapCreateDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_CreateType=0; + UpdateData(FALSE); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} diff --git a/MissionEditor/NewMapCreateDlg.h b/MissionEditor/NewMapCreateDlg.h new file mode 100644 index 0000000..6c42f3e --- /dev/null +++ b/MissionEditor/NewMapCreateDlg.h @@ -0,0 +1,67 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_NEWMAPCREATEDLG_H__F7D62442_C6DF_11D4_9C87_E63AC3E34349__INCLUDED_) +#define AFX_NEWMAPCREATEDLG_H__F7D62442_C6DF_11D4_9C87_E63AC3E34349__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// NewMapCreateDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CNewMapCreateDlg + +class CNewMapCreateDlg : public CDialog +{ +// Konstruktion +public: + CNewMapCreateDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CNewMapCreateDlg) + enum { IDD = IDD_NEWMAPCREATE }; + int m_CreateType; + BOOL m_AITriggers; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CNewMapCreateDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CNewMapCreateDlg) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_NEWMAPCREATEDLG_H__F7D62442_C6DF_11D4_9C87_E63AC3E34349__INCLUDED_ diff --git a/MissionEditor/NewMapCreateNewDlg.cpp b/MissionEditor/NewMapCreateNewDlg.cpp new file mode 100644 index 0000000..c78eec8 --- /dev/null +++ b/MissionEditor/NewMapCreateNewDlg.cpp @@ -0,0 +1,122 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// NewMapCreateNewDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "NewMapCreateNewDlg.h" +#include "variables.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CNewMapCreateNewDlg + + +CNewMapCreateNewDlg::CNewMapCreateNewDlg(CWnd* pParent /*=NULL*/) + : CDialog(CNewMapCreateNewDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CNewMapCreateNewDlg) + m_Height = 0; + m_Width = 0; + m_StartingHeight = -1; + m_Theater = -1; + //}}AFX_DATA_INIT +} + + +void CNewMapCreateNewDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CNewMapCreateNewDlg) + DDX_Text(pDX, IDC_HEIGHT, m_Height); + DDX_Text(pDX, IDC_WIDTH, m_Width); + DDX_CBIndex(pDX, IDC_STARTINGHEIGHT, m_StartingHeight); + DDX_CBIndex(pDX, IDC_THEATER, m_Theater); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CNewMapCreateNewDlg, CDialog) + //{{AFX_MSG_MAP(CNewMapCreateNewDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CNewMapCreateNewDlg + +BOOL CNewMapCreateNewDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CComboBox& theater=*((CComboBox*)GetDlgItem(IDC_THEATER)); + theater.AddString(THEATER0); + theater.AddString(THEATER1); +#ifdef RA2_MODE + theater.AddString(THEATER2); + if(yuri_mode) // MW YR support + { + theater.AddString(THEATER3); + theater.AddString(THEATER4); + theater.AddString(THEATER5); + } + +#endif + + m_Theater=0; + m_Width=50; + m_Height=50; + m_StartingHeight=0; + + UpdateData(FALSE); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} + +void CNewMapCreateNewDlg::OnOK() +{ + + UpdateData(TRUE); + + if(m_Width>400 || m_Height>400 || m_Width<16 || m_Height<16 || (m_Width + m_Height) > 512) + { + MessageBox("Width and Height must both be between 16 and 400 and both added must be less than 512.","Error"); + return; + } + + if(m_Width+m_Height>256) + { +#ifdef RA2_MODE + int res=MessageBox("Width + height is bigger than 256, this may cause problems in RA2. Continue?","Warning",MB_YESNO); +#else + int res=MessageBox("Width + height is bigger than 256, this may cause problems in TS. Continue?","Warning",MB_YESNO); +#endif + if(res==IDNO) return; + } + + CDialog::OnOK(); +} diff --git a/MissionEditor/NewMapCreateNewDlg.h b/MissionEditor/NewMapCreateNewDlg.h new file mode 100644 index 0000000..0951e0c --- /dev/null +++ b/MissionEditor/NewMapCreateNewDlg.h @@ -0,0 +1,70 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_NEWMAPCREATENEWDLG_H__F7D62443_C6DF_11D4_9C87_E63AC3E34349__INCLUDED_) +#define AFX_NEWMAPCREATENEWDLG_H__F7D62443_C6DF_11D4_9C87_E63AC3E34349__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// NewMapCreateNewDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CNewMapCreateNewDlg + +class CNewMapCreateNewDlg : public CDialog +{ +// Konstruktion +public: + CNewMapCreateNewDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CNewMapCreateNewDlg) + enum { IDD = IDD_NEWMAPCREATENEW }; + int m_Height; + int m_Width; + int m_StartingHeight; + int m_Theater; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CNewMapCreateNewDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CNewMapCreateNewDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_NEWMAPCREATENEWDLG_H__F7D62443_C6DF_11D4_9C87_E63AC3E34349__INCLUDED_ diff --git a/MissionEditor/NewMapImportDlg.cpp b/MissionEditor/NewMapImportDlg.cpp new file mode 100644 index 0000000..de615a9 --- /dev/null +++ b/MissionEditor/NewMapImportDlg.cpp @@ -0,0 +1,118 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// NewMapImportDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "NewMapImportDlg.h" +#include "variables.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CNewMapImportDlg + + +CNewMapImportDlg::CNewMapImportDlg(CWnd* pParent /*=NULL*/) + : CDialog(CNewMapImportDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CNewMapImportDlg) + m_ImportFile = _T(""); + m_ImportOverlay = FALSE; + m_ImportTrees = FALSE; + m_ImportUnits = FALSE; + //}}AFX_DATA_INIT +} + + +void CNewMapImportDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CNewMapImportDlg) + DDX_CBString(pDX, IDC_IMPORTFILE, m_ImportFile); + DDX_Check(pDX, IDC_IMPORTOVERLAY, m_ImportOverlay); + DDX_Check(pDX, IDC_IMPORTTREES, m_ImportTrees); + DDX_Check(pDX, IDC_IMPORTUNITS, m_ImportUnits); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CNewMapImportDlg, CDialog) + //{{AFX_MSG_MAP(CNewMapImportDlg) + ON_BN_CLICKED(IDC_BROWSE, OnBrowse) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CNewMapImportDlg + +void CNewMapImportDlg::OnBrowse() +{ + UpdateData(); + + //CComboBox* m_ImportFile=(CComboBox*)GetDlgItem(IDC_IMPORTFILE); + + CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_FILEMUSTEXIST, "All files|*.mpr;*.map;*.bmp|TS/RA2 multi maps|*.mpr|TS/RA2 single maps|*.map|Windows bitmaps|*.bmp|"); + + char cuPath[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, cuPath); + dlg.m_ofn.lpstrInitialDir=cuPath; + + if(theApp.m_Options.TSExe.GetLength()) dlg.m_ofn.lpstrInitialDir=(char*)(LPCTSTR)theApp.m_Options.TSExe; + + + if(dlg.DoModal()==IDCANCEL) return; + + m_ImportFile=dlg.GetPathName(); + + UpdateData(FALSE); +} + +BOOL CNewMapImportDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CComboBox* m_ImportFile=(CComboBox*)GetDlgItem(IDC_IMPORTFILE); + + CString maps = CString(u8AppDataPath.c_str()) + "\\stdmaps\\*.mpr"; + CFileFind ff; + + if(ff.FindFile(maps)) + { + BOOL bFileAvailable=TRUE; + while(bFileAvailable) { + bFileAvailable=ff.FindNextFile(); + + CString file=ff.GetFileName(); + m_ImportFile->AddString(file); + } + + m_ImportFile->SetCurSel(0); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} diff --git a/MissionEditor/NewMapImportDlg.h b/MissionEditor/NewMapImportDlg.h new file mode 100644 index 0000000..2d0228c --- /dev/null +++ b/MissionEditor/NewMapImportDlg.h @@ -0,0 +1,70 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_NEWMAPIMPORTDLG_H__F7D62444_C6DF_11D4_9C87_E63AC3E34349__INCLUDED_) +#define AFX_NEWMAPIMPORTDLG_H__F7D62444_C6DF_11D4_9C87_E63AC3E34349__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// NewMapImportDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CNewMapImportDlg + +class CNewMapImportDlg : public CDialog +{ +// Konstruktion +public: + CNewMapImportDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CNewMapImportDlg) + enum { IDD = IDD_NEWMAPIMPORT }; + CString m_ImportFile; + BOOL m_ImportOverlay; + BOOL m_ImportTrees; + BOOL m_ImportUnits; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CNewMapImportDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CNewMapImportDlg) + afx_msg void OnBrowse(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_NEWMAPIMPORTDLG_H__F7D62444_C6DF_11D4_9C87_E63AC3E34349__INCLUDED_ diff --git a/MissionEditor/NewMapSpDlg.cpp b/MissionEditor/NewMapSpDlg.cpp new file mode 100644 index 0000000..379ac17 --- /dev/null +++ b/MissionEditor/NewMapSpDlg.cpp @@ -0,0 +1,105 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// NewMapSpDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "NewMapSpDlg.h" +#include "variables.h" +#include "functions.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CNewMapSpDlg + + +CNewMapSpDlg::CNewMapSpDlg(CWnd* pParent /*=NULL*/) + : CDialog(CNewMapSpDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CNewMapSpDlg) + m_AutoProd = FALSE; + m_House = -1; + m_PrepareHouses = FALSE; + //}}AFX_DATA_INIT +} + + +void CNewMapSpDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CNewMapSpDlg) + DDX_Check(pDX, IDC_AUTOPROD, m_AutoProd); + DDX_CBIndex(pDX, IDC_HOUSE, m_House); + DDX_Check(pDX, IDC_PREPAREHOUSES, m_PrepareHouses); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CNewMapSpDlg, CDialog) + //{{AFX_MSG_MAP(CNewMapSpDlg) + ON_BN_CLICKED(IDC_PREPAREHOUSES, OnPreparehouses) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CNewMapSpDlg + +void CNewMapSpDlg::OnPreparehouses() +{ + UpdateData(TRUE); + BOOL bEnable=m_PrepareHouses; + + GetDlgItem(IDC_AUTOPROD)->EnableWindow(bEnable); + GetDlgItem(IDC_HOUSE)->EnableWindow(bEnable); + +} + +BOOL CNewMapSpDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CComboBox& house=*((CComboBox*)(GetDlgItem(IDC_HOUSE))); + int i; + for(i=0;i. +*/ + +#if !defined(AFX_NEWMAPSPDLG_H__F7D62445_C6DF_11D4_9C87_E63AC3E34349__INCLUDED_) +#define AFX_NEWMAPSPDLG_H__F7D62445_C6DF_11D4_9C87_E63AC3E34349__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// NewMapSpDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CNewMapSpDlg + +class CNewMapSpDlg : public CDialog +{ +// Konstruktion +public: + CNewMapSpDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CNewMapSpDlg) + enum { IDD = IDD_NEWMAPSPOPTIONS }; + BOOL m_AutoProd; + int m_House; + BOOL m_PrepareHouses; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CNewMapSpDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CNewMapSpDlg) + afx_msg void OnPreparehouses(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_NEWMAPSPDLG_H__F7D62445_C6DF_11D4_9C87_E63AC3E34349__INCLUDED_ diff --git a/MissionEditor/NewMapTypeDlg.cpp b/MissionEditor/NewMapTypeDlg.cpp new file mode 100644 index 0000000..5e27156 --- /dev/null +++ b/MissionEditor/NewMapTypeDlg.cpp @@ -0,0 +1,73 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// NewMapTypeDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "NewMapTypeDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CNewMapTypeDlg + + +CNewMapTypeDlg::CNewMapTypeDlg(CWnd* pParent /*=NULL*/) + : CDialog(CNewMapTypeDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CNewMapTypeDlg) + m_Singleplayer = -1; + //}}AFX_DATA_INIT +} + + +void CNewMapTypeDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CNewMapTypeDlg) + DDX_Radio(pDX, IDC_SINGLE, m_Singleplayer); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CNewMapTypeDlg, CDialog) + //{{AFX_MSG_MAP(CNewMapTypeDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CNewMapTypeDlg + +BOOL CNewMapTypeDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_Singleplayer=1; + UpdateData(FALSE); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} diff --git a/MissionEditor/NewMapTypeDlg.h b/MissionEditor/NewMapTypeDlg.h new file mode 100644 index 0000000..7467169 --- /dev/null +++ b/MissionEditor/NewMapTypeDlg.h @@ -0,0 +1,66 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_NEWMAPTYPEDLG_H__F7D62441_C6DF_11D4_9C87_E63AC3E34349__INCLUDED_) +#define AFX_NEWMAPTYPEDLG_H__F7D62441_C6DF_11D4_9C87_E63AC3E34349__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// NewMapTypeDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CNewMapTypeDlg + +class CNewMapTypeDlg : public CDialog +{ +// Konstruktion +public: + CNewMapTypeDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CNewMapTypeDlg) + enum { IDD = IDD_NEWMAPTYPE }; + int m_Singleplayer; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CNewMapTypeDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CNewMapTypeDlg) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_NEWMAPTYPEDLG_H__F7D62441_C6DF_11D4_9C87_E63AC3E34349__INCLUDED_ diff --git a/MissionEditor/NewRA2HouseDlg.cpp b/MissionEditor/NewRA2HouseDlg.cpp new file mode 100644 index 0000000..394e60a --- /dev/null +++ b/MissionEditor/NewRA2HouseDlg.cpp @@ -0,0 +1,83 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// NewRA2HouseDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "NewRA2HouseDlg.h" +#include "variables.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CNewRA2HouseDlg + + +CNewRA2HouseDlg::CNewRA2HouseDlg(CWnd* pParent /*=NULL*/) + : CDialog(CNewRA2HouseDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CNewRA2HouseDlg) + m_Country = _T(""); + //}}AFX_DATA_INIT +} + + +void CNewRA2HouseDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CNewRA2HouseDlg) + DDX_CBString(pDX, IDC_COUNTRY, m_Country); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CNewRA2HouseDlg, CDialog) + //{{AFX_MSG_MAP(CNewRA2HouseDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CNewRA2HouseDlg + +#include "functions.h" + +BOOL CNewRA2HouseDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CComboBox* country=(CComboBox*)GetDlgItem(IDC_COUNTRY); + + int i; + for(i=0;iAddString(TranslateHouse(*rules.sections[HOUSES].GetValue(i), TRUE)); + } + + country->SetCurSel(0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} diff --git a/MissionEditor/NewRA2HouseDlg.h b/MissionEditor/NewRA2HouseDlg.h new file mode 100644 index 0000000..0673a1b --- /dev/null +++ b/MissionEditor/NewRA2HouseDlg.h @@ -0,0 +1,66 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_NEWRA2HOUSEDLG_H__142D23E1_ADDC_11D4_9C87_A435A7B6044F__INCLUDED_) +#define AFX_NEWRA2HOUSEDLG_H__142D23E1_ADDC_11D4_9C87_A435A7B6044F__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// NewRA2HouseDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CNewRA2HouseDlg + +class CNewRA2HouseDlg : public CDialog +{ +// Konstruktion +public: + CNewRA2HouseDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CNewRA2HouseDlg) + enum { IDD = IDD_NEWRA2HOUSE }; + CString m_Country; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CNewRA2HouseDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CNewRA2HouseDlg) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_NEWRA2HOUSEDLG_H__142D23E1_ADDC_11D4_9C87_A435A7B6044F__INCLUDED_ diff --git a/MissionEditor/OpenMapDialog.cpp b/MissionEditor/OpenMapDialog.cpp new file mode 100644 index 0000000..83787ba --- /dev/null +++ b/MissionEditor/OpenMapDialog.cpp @@ -0,0 +1,51 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// OpenMapDialog.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "TiberianSun Mission Editor.h" +#include "OpenMapDialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// COpenMapDialog + +IMPLEMENT_DYNAMIC(COpenMapDialog, CFileDialog) + +COpenMapDialog::COpenMapDialog(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName, + DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) : + CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd) +{ +} + + +BEGIN_MESSAGE_MAP(COpenMapDialog, CFileDialog) + //{{AFX_MSG_MAP(COpenMapDialog) + // HINWEIS - Der Klassen-Assistent fĂ¼gt hier Zuordnungsmakros ein und entfernt diese. + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + diff --git a/MissionEditor/OpenMapDialog.h b/MissionEditor/OpenMapDialog.h new file mode 100644 index 0000000..1ad98aa --- /dev/null +++ b/MissionEditor/OpenMapDialog.h @@ -0,0 +1,55 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_OPENMAPDIALOG_H__914D68A0_ACAF_11D3_B63B_F360681B1940__INCLUDED_) +#define AFX_OPENMAPDIALOG_H__914D68A0_ACAF_11D3_B63B_F360681B1940__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// OpenMapDialog.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld COpenMapDialog + +class COpenMapDialog : public CFileDialog +{ + DECLARE_DYNAMIC(COpenMapDialog) + +public: + COpenMapDialog(BOOL bOpenFileDialog, // TRUE fĂ¼r FileOpen, FALSE fĂ¼r FileSaveAs + LPCTSTR lpszDefExt = NULL, + LPCTSTR lpszFileName = NULL, + DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + LPCTSTR lpszFilter = NULL, + CWnd* pParentWnd = NULL); + +protected: + //{{AFX_MSG(COpenMapDialog) + // HINWEIS - Der Klassen-Assistent fĂ¼gt hier Member-Funktionen ein und entfernt diese. + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_OPENMAPDIALOG_H__914D68A0_ACAF_11D3_B63B_F360681B1940__INCLUDED_ diff --git a/MissionEditor/ProgressDlg.cpp b/MissionEditor/ProgressDlg.cpp new file mode 100644 index 0000000..0b83171 --- /dev/null +++ b/MissionEditor/ProgressDlg.cpp @@ -0,0 +1,111 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// ProgressDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "ProgressDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CProgressDlg + + +CProgressDlg::CProgressDlg(CString lpDescription, CWnd* pParent /*=NULL*/) + : CDialog(CProgressDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CProgressDlg) + m_Label = lpDescription; + m_ProgLabel = _T(""); + //}}AFX_DATA_INIT + + m_bCancel=FALSE; + + Create(CProgressDlg::IDD, pParent); +} + + +void CProgressDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CProgressDlg) + DDX_Control(pDX, IDC_PROGRESS, m_Progress); + DDX_Text(pDX, IDC_LABEL, m_Label); + DDX_Text(pDX, IDC_PROGLABEL, m_ProgLabel); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CProgressDlg, CDialog) + //{{AFX_MSG_MAP(CProgressDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CProgressDlg + +void CProgressDlg::SetRange(int min, int max) +{ + m_Progress.SetRange32(min, max); +} + +void CProgressDlg::SetPosition(int nPos) +{ + m_Progress.SetPos(nPos); + m_Progress.UpdateWindow(); + m_ProgLabel="Progress: "; + + + + float p=m_Progress.GetPos(); + int min,max; + m_Progress.GetRange(min,max); + + if(max-min==0) return; + + float f=p/((float)(max-min)); + char c[50]; + itoa(f*100, c, 10); + m_ProgLabel+=c; + m_ProgLabel+=" %"; + + UpdateData(FALSE); +} + +void CProgressDlg::PostNcDestroy() +{ + delete this; + + //CDialog::PostNcDestroy(); +} + +void CProgressDlg::OnCancel() +{ + m_bCancel=TRUE; + + CDialog::OnCancel(); +} diff --git a/MissionEditor/ProgressDlg.h b/MissionEditor/ProgressDlg.h new file mode 100644 index 0000000..1456db5 --- /dev/null +++ b/MissionEditor/ProgressDlg.h @@ -0,0 +1,72 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_PROGRESSDLG_H__6FA29A01_EA1F_11D4_9C88_F09F67B34649__INCLUDED_) +#define AFX_PROGRESSDLG_H__6FA29A01_EA1F_11D4_9C88_F09F67B34649__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ProgressDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CProgressDlg + +class CProgressDlg : public CDialog +{ +// Konstruktion +public: + BOOL m_bCancel; + void SetPosition(int nPos); + void SetRange(int min, int max); + CProgressDlg(CString lpDescription, CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CProgressDlg) + enum { IDD = IDD_PROGRESS }; + CProgressCtrl m_Progress; + CString m_Label; + CString m_ProgLabel; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CProgressDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CProgressDlg) + virtual void OnCancel(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_PROGRESSDLG_H__6FA29A01_EA1F_11D4_9C88_F09F67B34649__INCLUDED_ diff --git a/MissionEditor/PropertySheets/Common.props b/MissionEditor/PropertySheets/Common.props new file mode 100644 index 0000000..cc6956b --- /dev/null +++ b/MissionEditor/PropertySheets/Common.props @@ -0,0 +1,45 @@ + + + + + + $(SolutionDir)\build\intermediate\$(Configuration)-$(Platform)\$(ProjectName)\ + True + + + $(MSBuildThisFileDirectory)..\..\3rdParty\xcc + + + + true + WIN32;_WINDOWS;SCRIPT_SUPPORT;%(PreprocessorDefinitions) + Use + stdafx.h + $(MSBuildThisFileDirectory)\..\..\MissionEditorPackLib + stdcpp20 + /utf-8 %(AdditionalOptions) + + + true + true + Win32 + + + 0x0409 + + + true + true + $(XccVcpkgDir)\lib + Windows + 11194304 + 11194304 + false + "type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'";%(AdditionalManifestDependencies) + + + false + $(MSBuildThisFileDirectory)force_utf8.manifest %(AdditionalManifestFiles) + + + \ No newline at end of file diff --git a/MissionEditor/PropertySheets/Debug.props b/MissionEditor/PropertySheets/Debug.props new file mode 100644 index 0000000..fac5737 --- /dev/null +++ b/MissionEditor/PropertySheets/Debug.props @@ -0,0 +1,33 @@ + + + + + + + $(XccDir)\vcpkg_installed\x86-windows\x86-windows + $(XccVcpkgDirTriplet)\debug + + + + + + MultiThreadedDebugDLL + Default + Disabled + EditAndContinue + _DEBUG;%(PreprocessorDefinitions) + EnableFastChecks + + + _DEBUG;%(PreprocessorDefinitions) + + + _DEBUG;%(PreprocessorDefinitions) + + + ddraw.lib;dxguid.lib;winmm.lib;gdiplus.lib;lzo2.lib;bz2d.lib;zlibd.lib;%(AdditionalDependencies) + libcmt.lib + + + + \ No newline at end of file diff --git a/MissionEditor/PropertySheets/Distribution.props b/MissionEditor/PropertySheets/Distribution.props new file mode 100644 index 0000000..65a9f22 --- /dev/null +++ b/MissionEditor/PropertySheets/Distribution.props @@ -0,0 +1,44 @@ + + + + + + + $(MSBuildThisFileDirectory)\..\..\dist\$(DistributionName) + $(DistributionFolder)\ + + + + + %(RecursiveDir)\COPYING + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MissionEditor/PropertySheets/FinalAlert2.props b/MissionEditor/PropertySheets/FinalAlert2.props new file mode 100644 index 0000000..5ea42f5 --- /dev/null +++ b/MissionEditor/PropertySheets/FinalAlert2.props @@ -0,0 +1,10 @@ + + + + + + + + FinalAlert2 + + \ No newline at end of file diff --git a/MissionEditor/PropertySheets/FinalAlert2YR.props b/MissionEditor/PropertySheets/FinalAlert2YR.props new file mode 100644 index 0000000..33d68f2 --- /dev/null +++ b/MissionEditor/PropertySheets/FinalAlert2YR.props @@ -0,0 +1,10 @@ + + + + + + + + FinalAlert2YR + + \ No newline at end of file diff --git a/MissionEditor/PropertySheets/FinalSun.props b/MissionEditor/PropertySheets/FinalSun.props new file mode 100644 index 0000000..69068da --- /dev/null +++ b/MissionEditor/PropertySheets/FinalSun.props @@ -0,0 +1,10 @@ + + + + + + + + FinalSun + + \ No newline at end of file diff --git a/MissionEditor/PropertySheets/Release.props b/MissionEditor/PropertySheets/Release.props new file mode 100644 index 0000000..0e155dc --- /dev/null +++ b/MissionEditor/PropertySheets/Release.props @@ -0,0 +1,33 @@ + + + + + + + $(XccDir)\vcpkg_installed\x86-windows\x86-windows + $(XccVcpkgDirTriplet) + + + + + + MultiThreadedDLL + AnySuitable + true + MaxSpeed + true + NDEBUG;_AFXDLL;%(PreprocessorDefinitions) + + + NDEBUG;%(PreprocessorDefinitions) + + + NDEBUG;_AFXDLL;%(PreprocessorDefinitions) + + + ddraw.lib;dxguid.lib;winmm.lib;gdiplus.lib;lzo2.lib;bz2.lib;zlib.lib;%(AdditionalDependencies) + libcmt.lib; libcmtd.lib; msvcrtd.lib + + + + \ No newline at end of file diff --git a/MissionEditor/PropertySheets/Tests.props b/MissionEditor/PropertySheets/Tests.props new file mode 100644 index 0000000..a96b067 --- /dev/null +++ b/MissionEditor/PropertySheets/Tests.props @@ -0,0 +1,16 @@ + + + + + True + + + + TESTS;%(PreprocessorDefinitions) + + + Console + mainCRTStartup + + + \ No newline at end of file diff --git a/MissionEditor/PropertySheets/force_utf8.manifest b/MissionEditor/PropertySheets/force_utf8.manifest new file mode 100644 index 0000000..ceeb4d0 --- /dev/null +++ b/MissionEditor/PropertySheets/force_utf8.manifest @@ -0,0 +1,8 @@ + + + + + UTF-8 + + + diff --git a/MissionEditor/RTPDlg.cpp b/MissionEditor/RTPDlg.cpp new file mode 100644 index 0000000..84dbf0b --- /dev/null +++ b/MissionEditor/RTPDlg.cpp @@ -0,0 +1,314 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// RTPDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "RTPDlg.h" +#include "variables.h" +#include "functions.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CRTPDlg + + +CRTPDlg::CRTPDlg(CWnd* pParent /*=NULL*/) + : CDialog(CRTPDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CRTPDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Elementinitialisierung ein + //}}AFX_DATA_INIT +} + + +void CRTPDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CRTPDlg) + DDX_Control(pDX, IDC_PREVIEW, m_Preview); + DDX_Control(pDX, IDC_USED, m_Used); + DDX_Control(pDX, IDC_AVAIL, m_Available); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CRTPDlg, CDialog) + //{{AFX_MSG_MAP(CRTPDlg) + ON_BN_CLICKED(IDC_ADD, OnAdd) + ON_BN_CLICKED(IDC_REMOVE, OnRemove) + ON_LBN_SELCHANGE(IDC_AVAIL, OnSelchangeAvail) + ON_LBN_DBLCLK(IDC_AVAIL, OnDblclkAvail) + ON_LBN_SELCHANGE(IDC_USED, OnSelchangeUsed) + ON_LBN_DBLCLK(IDC_USED, OnDblclkUsed) + ON_WM_PAINT() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CRTPDlg + +BOOL CRTPDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + int i; + for(i=0;i=0) continue; + + addedString=TranslateStringACP(addedString); + + + if(unitname.Find("TREE")>=0) + { + + + if(unitname.GetLength()>0 && unitname!="VEINTREE") // out with it :-) + { + int TreeMin=atoi(g_data.sections[Map->GetTheater()+"Limits"].values["TreeMin"]); + int TreeMax=atoi(g_data.sections[Map->GetTheater()+"Limits"].values["TreeMax"]); + + CString id=unitname; + id.Delete(0, 4); + int n=atoi(id); + + + if(nTreeMax) continue; + + m_Available.AddString(unitname); + } + } + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} + +void CRTPDlg::OnAdd() +{ + int sel=m_Available.GetCurSel(); + if(sel<0) return; + + CString currentname; + m_Available.GetText(sel, currentname); + + m_Available.DeleteString(sel); + m_Used.AddString(currentname); +} + +void CRTPDlg::OnRemove() +{ + int sel=m_Used.GetCurSel(); + if(sel<0) return; + + CString currentname; + m_Used.GetText(sel, currentname); + + m_Used.DeleteString(sel); + m_Available.AddString(currentname); +} + +void CRTPDlg::OnOK() +{ + if(m_Used.GetCount()<=0) + { + //AfxMessageBox("Please select at least one tree","Error", MB_OK); + return; + } + + rndterrainsrc.clear(); + + int i; + for(i=0;iGetUnitTypeID(m_LastSelected); + + PICDATA* p=&treeinfo[id].pic; //ovrlpics[m_currentOverlay][i]; + + + if(p->pic==NULL) + { + CString type; + type=m_LastSelected; + + if(missingimages.find(type)==missingimages.end()) + { + theApp.m_loading->LoadUnitGraphic(type); + Map->UpdateTreeInfo(type); + p=&treeinfo[id].pic; + } + if(p->pic==NULL) + { + missingimages[type]=TRUE; + } + } + + int curwidth=p->wMaxWidth; + int curheight=p->wMaxHeight; + + BITMAPINFO biinfo; + memset(&biinfo, 0, sizeof(BITMAPINFO)); + biinfo.bmiHeader.biBitCount=24; + biinfo.bmiHeader.biWidth=curwidth; + biinfo.bmiHeader.biHeight=curheight; + biinfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + biinfo.bmiHeader.biClrUsed=0; + biinfo.bmiHeader.biPlanes=1; + biinfo.bmiHeader.biCompression=BI_RGB; + biinfo.bmiHeader.biClrImportant=0; + + + int pitch=curwidth*3; + if(pitch==0) return; + + if(pitch%sizeof(DWORD)) + { + pitch+=sizeof(DWORD)-(curwidth*3)%sizeof(DWORD); + } + + BYTE* colors=new(BYTE[pitch*curheight]); + memset(colors, 255, pitch*(curheight)); + + RGBTRIPLE* pal=palIso; +#ifdef NOSURFACES + if(p->pal==iPalTheater) pal=palTheater; + if(p->pal==iPalUnit) pal=palUnit; +#endif + + int k,l; + for(k=0;kpic)[l+k*curwidth]) + { + memcpy(&colors[l*3+(curheight-k-1)*pitch], &pal[((BYTE*)p->pic)[l+k*curwidth]], 3); + } + } + } + + RECT pr; + m_Preview.GetWindowRect(&pr); + this->ScreenToClient(&pr); + + pr.top += 15; + pr.bottom -= 5; + pr.left += 5; + pr.right -= 5; + + CBrush f; + f.Attach(GetStockObject(WHITE_BRUSH)); + dc.FillRect(&pr,&f); + f.Detach(); + + auto clientDC = m_Preview.GetWindowDC(); + StretchDIBits(clientDC->GetSafeHdc(), 20, 30,curwidth, curheight, + 0, 0, curwidth, curheight, colors, &biinfo, DIB_RGB_COLORS, SRCCOPY); + + delete[] colors; + + // Kein Aufruf von CDialog::OnPaint() fĂ¼r Zeichnungsnachrichten +} diff --git a/MissionEditor/RTPDlg.h b/MissionEditor/RTPDlg.h new file mode 100644 index 0000000..18a6a6c --- /dev/null +++ b/MissionEditor/RTPDlg.h @@ -0,0 +1,77 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_RTPDLG_H__8E65AA00_2C54_11D5_89B2_444553540000__INCLUDED_) +#define AFX_RTPDLG_H__8E65AA00_2C54_11D5_89B2_444553540000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// RTPDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CRTPDlg + +class CRTPDlg : public CDialog +{ +// Konstruktion +public: + CRTPDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CRTPDlg) + enum { IDD = IDD_TERRAINPLACING }; + CButton m_Preview; + CListBox m_Used; + CListBox m_Available; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CRTPDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + CString m_LastSelected; + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CRTPDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnAdd(); + afx_msg void OnRemove(); + virtual void OnOK(); + afx_msg void OnSelchangeAvail(); + afx_msg void OnDblclkAvail(); + afx_msg void OnSelchangeUsed(); + afx_msg void OnDblclkUsed(); + afx_msg void OnPaint(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_RTPDLG_H__8E65AA00_2C54_11D5_89B2_444553540000__INCLUDED_ diff --git a/MissionEditor/RightFrame.cpp b/MissionEditor/RightFrame.cpp new file mode 100644 index 0000000..2f3e14c --- /dev/null +++ b/MissionEditor/RightFrame.cpp @@ -0,0 +1,123 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// RightFrame.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "RightFrame.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CRightFrame + +IMPLEMENT_DYNCREATE(CRightFrame, CFrameWnd) + +CRightFrame::CRightFrame() +{ +} + +CRightFrame::~CRightFrame() +{ +} + + +BEGIN_MESSAGE_MAP(CRightFrame, CFrameWnd) + //{{AFX_MSG_MAP(CRightFrame) + ON_WM_SIZE() + ON_WM_CHAR() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CRightFrame + +BOOL CRightFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) +{ + + SIZE z; + z.cx=200; + z.cy=700; + //if(z.cy<100) z.cy=100; + + CRect r; + r.right=200; + r.bottom=200; + + + if(!m_Splitter.CreateStatic(this,2,1)) return FALSE; + + + if(!m_Splitter.CreateView(0,0, + RUNTIME_CLASS(CIsoView), + z, + pContext)) return FALSE; + + z.cy=100; + + if(!m_Splitter.CreateView(1,0, + RUNTIME_CLASS(CTileSetBrowserFrame), + z, + pContext)) return FALSE; + + GetClientRect(&r); + + m_Splitter.SetRowInfo(0, GetSystemMetrics(SM_CYFULLSCREEN)/2, 20); + m_Splitter.SetRowInfo(1, GetSystemMetrics(SM_CYFULLSCREEN)/2, 10); + + //SetWindowLong(m_Splitter->m_hWnd, GWL_STYLE, m_rightFrame->GetStyle() ! WS_THICKFRAME); + + OutputDebugString("CRightFrame::OnCreateClient(): windows created\n"); + + return CFrameWnd::OnCreateClient(lpcs, pContext); +} + +BOOL CRightFrame::PreCreateWindow(CREATESTRUCT& cs) +{ + // cs.style=WS_OVERLAPPED && WS_CAPTION && WS_SYSMENU && WS_MINIMIZEBOX && WS_MAXIMIZEBOX; + + return CFrameWnd::PreCreateWindow(cs); +} + +void CRightFrame::OnSize(UINT nType, int cx, int cy) +{ + CFrameWnd::OnSize(nType, cx, cy); + + +} + +void CRightFrame::RecalcLayout(BOOL bNotify) +{ + // TODO: Speziellen Code hier einfĂ¼gen und/oder Basisklasse aufrufen + + CFrameWnd::RecalcLayout(bNotify); +} + +void CRightFrame::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + + CFrameWnd::OnChar(nChar, nRepCnt, nFlags); +} diff --git a/MissionEditor/RightFrame.h b/MissionEditor/RightFrame.h new file mode 100644 index 0000000..76e1a0b --- /dev/null +++ b/MissionEditor/RightFrame.h @@ -0,0 +1,73 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_RIGHTFRAME_H__22553762_8405_11D4_9C87_EE62BC46B24A__INCLUDED_) +#define AFX_RIGHTFRAME_H__22553762_8405_11D4_9C87_EE62BC46B24A__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// RightFrame.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Rahmen CRightFrame + +class CRightFrame : public CFrameWnd +{ + DECLARE_DYNCREATE(CRightFrame) +protected: + CRightFrame(); // Dynamische Erstellung verwendet geschĂ¼tzten Konstruktor + +// Attribute +public: + +// Operationen +public: + CSplitterWnd m_Splitter; + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CRightFrame) + public: + virtual void RecalcLayout(BOOL bNotify = TRUE); + protected: + virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext); + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + //}}AFX_VIRTUAL + +// Implementierung +protected: + virtual ~CRightFrame(); + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CRightFrame) + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_RIGHTFRAME_H__22553762_8405_11D4_9C87_EE62BC46B24A__INCLUDED_ diff --git a/MissionEditor/SaveMapOptionsDlg.cpp b/MissionEditor/SaveMapOptionsDlg.cpp new file mode 100644 index 0000000..c420601 --- /dev/null +++ b/MissionEditor/SaveMapOptionsDlg.cpp @@ -0,0 +1,122 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// SaveMapOptionsDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "SaveMapOptionsDlg.h" +#include "variables.h" +#include "inifile.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CSaveMapOptionsDlg + + +CSaveMapOptionsDlg::CSaveMapOptionsDlg(CWnd* pParent /*=NULL*/) + : CDialog(CSaveMapOptionsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CSaveMapOptionsDlg) + m_Compress = 1; + m_PreviewMode = 0; + m_MapName = _T(""); + m_AirWar = FALSE; + m_Cooperative = FALSE; + m_Duel = FALSE; + m_Meatgrind = FALSE; + m_Megawealth = FALSE; + m_Navalwar = FALSE; + m_Nukewar = FALSE; + m_Standard = FALSE; + m_TeamGame = FALSE; + //}}AFX_DATA_INIT + + CIniFile& ini=Map->GetIniFile(); + if(!Map->IsMultiplayer()) + m_PreviewMode=1; + + m_MapName=ini.sections["Basic"].values["Name"]; +} + + +void CSaveMapOptionsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSaveMapOptionsDlg) + DDX_Radio(pDX, IDC_COMPRESS, m_Compress); + DDX_Radio(pDX, IDC_PREVIEWMODE, m_PreviewMode); + DDX_Text(pDX, IDC_MAPNAME, m_MapName); + #ifdef RA2_MODE + DDX_Check(pDX, IDC_AIRWAR, m_AirWar); + DDX_Check(pDX, IDC_COOPERATIVE, m_Cooperative); + DDX_Check(pDX, IDC_DUEL, m_Duel); + DDX_Check(pDX, IDC_MEATGRIND, m_Meatgrind); + DDX_Check(pDX, IDC_MEGAWEALTH, m_Megawealth); + DDX_Check(pDX, IDC_NAVALWAR, m_Navalwar); + DDX_Check(pDX, IDC_NUKEWAR, m_Nukewar); + DDX_Check(pDX, IDC_STANDARD, m_Standard); + DDX_Check(pDX, IDC_TEAMGAME, m_TeamGame); + #endif + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CSaveMapOptionsDlg, CDialog) + //{{AFX_MSG_MAP(CSaveMapOptionsDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CSaveMapOptionsDlg + +BOOL CSaveMapOptionsDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CIniFile& ini=Map->GetIniFile(); + if(!Map->IsMultiplayer()) + { + GetDlgItem(IDC_PREVIEWMODE)->EnableWindow(FALSE); + GetDlgItem(IDC_NOPREVIEW)->EnableWindow(FALSE); + GetDlgItem(IDC_EXISTINGPREVIEW)->EnableWindow(FALSE); + +#ifndef TS_MODE + GetDlgItem(IDC_AIRWAR)->EnableWindow(FALSE); + GetDlgItem(IDC_COOPERATIVE)->EnableWindow(FALSE); + GetDlgItem(IDC_DUEL)->EnableWindow(FALSE); + GetDlgItem(IDC_MEATGRIND)->EnableWindow(FALSE); + GetDlgItem(IDC_MEGAWEALTH)->EnableWindow(FALSE); + GetDlgItem(IDC_NAVALWAR)->EnableWindow(FALSE); + GetDlgItem(IDC_NUKEWAR)->EnableWindow(FALSE); + GetDlgItem(IDC_STANDARD)->EnableWindow(FALSE); + GetDlgItem(IDC_TEAMGAME)->EnableWindow(FALSE); +#endif + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} diff --git a/MissionEditor/SaveMapOptionsDlg.h b/MissionEditor/SaveMapOptionsDlg.h new file mode 100644 index 0000000..a90f1d6 --- /dev/null +++ b/MissionEditor/SaveMapOptionsDlg.h @@ -0,0 +1,77 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_SAVEMAPOPTIONSDLG_H__DD7874E1_CED2_11D4_9C87_444553540000__INCLUDED_) +#define AFX_SAVEMAPOPTIONSDLG_H__DD7874E1_CED2_11D4_9C87_444553540000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// SaveMapOptionsDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CSaveMapOptionsDlg + +class CSaveMapOptionsDlg : public CDialog +{ +// Konstruktion +public: + CSaveMapOptionsDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CSaveMapOptionsDlg) + enum { IDD = IDD_SAVEOPTIONS }; + int m_Compress; + int m_PreviewMode; + CString m_MapName; + BOOL m_AirWar; + BOOL m_Cooperative; + BOOL m_Duel; + BOOL m_Meatgrind; + BOOL m_Megawealth; + BOOL m_Navalwar; + BOOL m_Nukewar; + BOOL m_Standard; + BOOL m_TeamGame; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CSaveMapOptionsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CSaveMapOptionsDlg) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_SAVEMAPOPTIONSDLG_H__DD7874E1_CED2_11D4_9C87_444553540000__INCLUDED_ diff --git a/MissionEditor/SavingDlg.cpp b/MissionEditor/SavingDlg.cpp new file mode 100644 index 0000000..2f1684f --- /dev/null +++ b/MissionEditor/SavingDlg.cpp @@ -0,0 +1,71 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// SavingDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "SavingDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CSavingDlg + + +CSavingDlg::CSavingDlg(CWnd* pParent /*=NULL*/) + : CDialog(CSavingDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CSavingDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Elementinitialisierung ein + //}}AFX_DATA_INIT + + Create(CSavingDlg::IDD, pParent); +} + + +void CSavingDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSavingDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier DDX- und DDV-Aufrufe ein + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CSavingDlg, CDialog) + //{{AFX_MSG_MAP(CSavingDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Zuordnungsmakros fĂ¼r Nachrichten ein + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CSavingDlg + +void CSavingDlg::PostNcDestroy() +{ + + // CDialog::PostNcDestroy(); +} diff --git a/MissionEditor/SavingDlg.h b/MissionEditor/SavingDlg.h new file mode 100644 index 0000000..9820494 --- /dev/null +++ b/MissionEditor/SavingDlg.h @@ -0,0 +1,69 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_SAVINGDLG_H__9E604CC1_850C_11D4_9C87_BC8AE639B54A__INCLUDED_) +#define AFX_SAVINGDLG_H__9E604CC1_850C_11D4_9C87_BC8AE639B54A__INCLUDED_ + +#include "resource.h" + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// SavingDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CSavingDlg + +class CSavingDlg : public CDialog +{ +// Konstruktion +public: + CSavingDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CSavingDlg) + enum { IDD = IDD_SAVING }; + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Datenelemente ein + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CSavingDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CSavingDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Member-Funktionen ein + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_SAVINGDLG_H__9E604CC1_850C_11D4_9C87_BC8AE639B54A__INCLUDED_ diff --git a/MissionEditor/ScriptTypes.cpp b/MissionEditor/ScriptTypes.cpp new file mode 100644 index 0000000..a341e00 --- /dev/null +++ b/MissionEditor/ScriptTypes.cpp @@ -0,0 +1,751 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// ScriptTypes.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "ScriptTypes.h" +#include "FinalSunDlg.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" +#include "inlines.h" + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +#define TMISSION_COUNT 59 +#define TPROPERTY_COUNT 4 +#define UNLOAD_COUNT 4 + + +// The various missions that a team can have. +enum TeamMissionType { + TMISSION_ATTACK, + TMISSION_ATT_WAYPT, + TMISSION_BERZERK, + TMISSION_MOVE, + TMISSION_MOVECELL, + TMISSION_GUARD, + TMISSION_LOOP, + TMISSION_WIN, + TMISSION_UNLOAD, + TMISSION_DEPLOY, + TMISSION_HOUND_DOG, + TMISSION_DO, + TMISSION_SET_GLOBAL, + TMISSION_IDLE_ANIM, + TMISSION_LOAD, + TMISSION_SPY, + TMISSION_PATROL, + TMISSION_SCRIPT, + TMISSION_TEAMCHANGE, + TMISSION_PANIC, + TMISSION_CHANGE_HOUSE, + TMISSION_SCATTER, + TMISSION_GOTO_SHROUD, + TMISSION_LOSE, + TMISSION_PLAY_SPEECH, + TMISSION_PLAY_SOUND, + TMISSION_PLAY_MOVIE, + TMISSION_PLAY_MUSIC, + TMISSION_REDUCE_TIBERIUM, + TMISSION_BEGIN_PRODUCTION, + TMISSION_FIRE_SALE, + TMISSION_SELF_DESTRUCT, + TMISSION_ION_STORM_START, + TMISSION_ION_STORM_END, + TMISSION_CENTER_VIEWPOINT, + TMISSION_RESHROUD, + TMISSION_REVEAL, + TMISSION_DESTROY_MEMBERS, + TMISSION_CLEAR_GLOBAL, + TMISSION_SET_LOCAL, + TMISSION_CLEAR_LOCAL, + TMISSION_UNPANIC, + TMISSION_FORCE_FACING, + TMISSION_FULLY_LOADED, + TMISSION_UNLOAD_TRUCK, + TMISSION_LOAD_TRUCK, + TMISSION_ATTACK_BUILDING_WITH_PROPERTY, + TMISSION_MOVETO_BUILDING_WITH_PROPERTY, + TMISSION_SCOUT, + TMISSION_SUCCESS, + TMISSION_FLASH, + TMISSION_PLAY_ANIM, + TMISSION_TALK_BUBBLE, + TMISSION_GATHER_FAR, + TMISSION_GATHER_NEAR, + TMISSION_ACTIVATE_CURTAIN, + TMISSION_CHRONO_ATTACK_BUILDING_WITH_PROPERTY, + TMISSION_CHRONO_ATTACK, + TMISSION_MOVETO_OWN_BUILDING_WITH_PROPERTY, +}; + +char const * TMissions[TMISSION_COUNT] = { + "Attack...", + "Attack Waypoint...", + "Go Berzerk", + "Move to waypoint...", + "Move to Cell...", + "Guard area (timer ticks)...", + "Jump to line #...", + "Player wins", + "Unload...", + "Deploy", + "Follow friendlies", + "Do this...", + "Set global...", + "Idle Anim...", + "Load onto Transport", + "Spy on bldg @ waypt...", + "Patrol to waypoint...", + "Change script...", + "Change team...", + "Panic", + "Change house...", + "Scatter", + "Goto nearby shroud", + "Player loses", + "Play speech...", + "Play sound...", + "Play movie...", + "Play music...", + "Reduce tiberium", + "Begin production", + "Fire sale", + "Self destruct", + "Ion storm start in...", + "Ion storn end", + "Center view on team (speed)...", + "Reshroud map", + "Reveal map", + "Delete team members", + "Clear global...", + "Set local...", + "Clear local...", + "Unpanic", + "Force facing...", + "Wait till fully loaded", + "Truck unload", + "Truck load", + "Attack enemy building", + "Moveto enemy building", + "Scout", + "Success", + "Flash", + "Play Anim", + "Talk Bubble", + "Gather at Enemy", + "Gather at Base", + "Iron Curtain Me", + "Chrono Prep for ABwP", + "Chrono Prep for AQ", + "Move to own building", +}; + +char const * TMissionsHelp[TMISSION_COUNT] = { + "Attack some general target", + "Attack anything nearby the specified waypoint", + "Cyborg members of the team will go berzerk.", + "Orders the team to move to a waypoint on the map", + "Orders the team to move to a specific cell on the map", + "Guard an area for a specified amount of time", + "Move to a new line number in the script. Used for loops.", + "Duh", + "Unloads all loaded units. The command parameter specifies which units should stay a part of the team, and which should be severed from the team.", + "Causes all deployable units in the team to deploy", + "Causes the team to follow the nearest friendly unit", + "Give all team members the specified mission", + "Sets a global variable", + "Causes team members to enter their idle animation", + "Causes all units to load into transports, if able", + "**OBSOLETE**", + "Move to a waypoint while scanning for enemies", + "Causes the team to start using a new script", + "Causes the team to switch team types", + "Causes all units in the team to panic", + "All units in the team switch houses", + "Tells all units to scatter", + "Causes units to flee to a shrouded cell", + "Causes the player to lose", + "Plays the specified voice file", + "Plays the specified sound file", + "Plays the specified movie file", + "Plays the specified theme", + "Reduces the amount of tiberium around team members", + "Signals the owning house to begin production", + "Causes an AI house to sell all of its buildings and do a Braveheart", + "Causes all team members to self destruct", + "Causes an ion storm to begin at the specified time", + "Causes an ion storm to end", + "Center view on team (speed)...", + "Reshrouds the map", + "Reveals the map", + "Delete all members from the team", + "Clears the specified global variable", + "Sets the specified local variable", + "Clears the specified local variable", + "Causes all team members to stop panicking", + "Forces team members to face a certain direction", + "Waits until all transports are full", + "Causes all trucks to unload their crates (ie, change imagery)", + "Causes all trucks to load crates (ie, change imagery)", + "Attack a specific type of building with the specified property", + "Move to a specific type of building with the specified property", + "The team will scout the bases of the players that have not been scouted", + "Record a team as having successfully accomplished its mission. Used for AI trigger weighting. Put this at the end of every AITrigger script.", + "Flashes a team for a period of team.", + "Plays an anim over every unit in the team.", + "Displays talk bubble over first unit in the team.", + "Uses AISafeDistance to find a spot close to enemy's base to gather close.", + "Gathers outside own base perimeter.", + "Calls (and waits if nearly ready) for House to deliver Iron Curtain to Team.", + "Teleports team to Building With Property, but needs similar attack order as next mission.", + "Teleports team to Attack Quarry, but needs similar attack order as next mission.", + "A BwP move that will only search through buildings owned by this house.", +}; + + +char const *TargetProperties[TPROPERTY_COUNT] = { + "Least Threat", + "Greatest Threat", + "Nearest", + "Farthest", +}; + +char const *UnloadTypeNames[UNLOAD_COUNT] = { + "Keep Transports, Keep Units", + "Keep Transports, Lose Units", + "Lose Transports, Keep Units", + "Lose Transports, Lose Units", +}; + + +///////////////////////////////////////////////////////////////////////////// +// Eigenschaftenseite CScriptTypes + +IMPLEMENT_DYNCREATE(CScriptTypes, CDialog) + +CScriptTypes::CScriptTypes() : CDialog(CScriptTypes::IDD) +{ + //{{AFX_DATA_INIT(CScriptTypes) + m_Name = _T(""); + //}}AFX_DATA_INIT +} + +CScriptTypes::~CScriptTypes() +{ +} + +void CScriptTypes::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CScriptTypes) + DDX_Control(pDX, IDC_DESCRIPTION, m_DescriptionEx); + DDX_Control(pDX, IDC_PDESC, m_Desc); + DDX_Control(pDX, IDC_TYPE, m_Type); + DDX_Control(pDX, IDC_SCRIPTTYPE, m_ScriptType); + DDX_Control(pDX, IDC_PARAM, m_Param); + DDX_Control(pDX, IDC_ACTION, m_Action); + DDX_Text(pDX, IDC_NAME, m_Name); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CScriptTypes, CDialog) + //{{AFX_MSG_MAP(CScriptTypes) + ON_CBN_EDITCHANGE(IDC_SCRIPTTYPE, OnEditchangeScripttype) + ON_CBN_SELCHANGE(IDC_SCRIPTTYPE, OnSelchangeScripttype) + ON_LBN_SELCHANGE(IDC_ACTION, OnSelchangeAction) + ON_EN_CHANGE(IDC_NAME, OnChangeName) + ON_CBN_EDITCHANGE(IDC_TYPE, OnEditchangeType) + ON_CBN_SELCHANGE(IDC_TYPE, OnSelchangeType) + ON_CBN_EDITCHANGE(IDC_PARAM, OnEditchangeParam) + ON_CBN_SELCHANGE(IDC_PARAM, OnSelchangeParam) + ON_BN_CLICKED(IDC_ADDACTION, OnAddaction) + ON_BN_CLICKED(IDC_DELETEACTION, OnDeleteaction) + ON_BN_CLICKED(IDC_ADD, OnAdd) + ON_BN_CLICKED(IDC_DELETE, OnDelete) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CScriptTypes + +void CScriptTypes::UpdateDialog() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_ScriptType.GetCurSel(); + + + while(m_ScriptType.DeleteString(0)!=CB_ERR); + + + // MW 07/24/01: clear dialog + m_DescriptionEx.SetWindowText(""); + m_Name=""; + m_Param.SetWindowText(""); + m_Action.SetWindowText(""); + m_Type.SetCurSel(-1); + + UpdateData(FALSE); + + + int i; + for(i=0;i=0) m_ScriptType.SetCurSel(sel); + OnSelchangeScripttype(); + + +} + +void CScriptTypes::OnEditchangeScripttype() +{ + +} + +void CScriptTypes::OnSelchangeScripttype() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Action.GetCurSel(); + while(m_Action.DeleteString(0)!=CB_ERR); + + CString Scripttype; + if(m_ScriptType.GetCurSel()<0) return; + m_ScriptType.GetLBText(m_ScriptType.GetCurSel(), Scripttype); + TruncSpace(Scripttype); + + m_Name=ini.sections[(LPCTSTR)Scripttype].values["Name"]; + + int count=ini.sections[(LPCTSTR)Scripttype].values.size()-1; + int i; + for(i=0;i=0) m_Action.SetCurSel(sel); + OnSelchangeAction(); + + UpdateData(FALSE); +} + +void CScriptTypes::OnSelchangeAction() +{ + CIniFile& ini=Map->GetIniFile(); + + CString Scripttype; + char action[50]; + if(m_ScriptType.GetCurSel()<0) return; + if(m_Action.GetCurSel()<0) return; + m_ScriptType.GetLBText(m_ScriptType.GetCurSel(), Scripttype); + TruncSpace(Scripttype); + + itoa(m_Action.GetCurSel(), action, 10); + //m_Type.SetWindowText(GetParam(ini.sections[(LPCTSTR)Scripttype].values[action],0)); + m_Type.SetCurSel(atoi(GetParam(ini.sections[(LPCTSTR)Scripttype].values[action], 0))); + + OnSelchangeType(); + + m_Param.SetWindowText(GetParam(ini.sections[(LPCTSTR)Scripttype].values[action],1)); + + +} + +void CScriptTypes::OnChangeName() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(); + + CEdit* n=(CEdit*)GetDlgItem(IDC_NAME); + + DWORD pos=n->GetSel(); + CString Scripttype; + if(m_ScriptType.GetCurSel()<0) return; + m_ScriptType.GetLBText(m_ScriptType.GetCurSel(), Scripttype); + TruncSpace(Scripttype); + + + + ini.sections[(LPCTSTR)Scripttype].values["Name"]=m_Name; + + UpdateDialog(); + n->SetSel(pos); +} + +void CScriptTypes::OnEditchangeType() +{ + CIniFile& ini=Map->GetIniFile(); + + while(m_Param.DeleteString(0)!=CB_ERR); + CString Scripttype; + char action[50]; + if(m_Action.GetCurSel()<0) return; + if(m_ScriptType.GetCurSel()<0) return; + m_ScriptType.GetLBText(m_ScriptType.GetCurSel(), Scripttype); + TruncSpace(Scripttype); + + //CString type; + //m_Type.GetWindowText(type); + //TruncSpace(type); + //MessageBox("beep"); + int type=m_Type.GetCurSel(); + + int i; + char tmp[50]; + + switch(type) + { + case 0: + ListTargets(m_Param); + m_Desc.SetWindowText("Target:"); + break; + case 39: + case 40: + ListGlobals(m_Param); + break; + + case 11: + ListBehaviours(m_Param); + break; + case 1: + case 3: + case 16: + ListWaypoints(m_Param); + m_Desc.SetWindowText("Waypoint:"); + break; + case 4: + m_Desc.SetWindowText("Cell:"); + break; + case 5: + m_Desc.SetWindowText("Time units to guard:"); + break; + case 6: + m_Desc.SetWindowText("Script action #:"); + while(m_Param.DeleteString(0)!=CB_ERR); + for(i=1;i<=ini.sections[(LPCTSTR)Scripttype].values.size()-1;i++) + m_Param.AddString(itoa(i,tmp,10)); + break; + case 8: + m_Desc.SetWindowText("Split groups:"); + while(m_Param.DeleteString(0)!=CB_ERR); + int i; + for(i=0;iGetUnitName(*rules.sections["BuildingTypes"].GetValue(i)); + m_Param.AddString(s); + } + + break; + } + + default: + m_Desc.SetWindowText("Parameter of action:"); + } + + itoa(m_Action.GetCurSel(), action, 10); + + char types[50]; + itoa(type, types, 10); + ini.sections[(LPCTSTR)Scripttype].values[action]=SetParam(ini.sections[(LPCTSTR)Scripttype].values[action], 0, (LPCTSTR)types); + + + +} + +void CScriptTypes::OnSelchangeType() +{ + CString str; + if(m_Type.GetCurSel()>-1) + { + //m_Type.GetLBText(m_Type.GetCurSel(), str); + //m_Type.SetWindowText(str); + + m_DescriptionEx.SetWindowText(TMissionsHelp[m_Type.GetCurSel()]); + } + + + + OnEditchangeType(); +} + +void CScriptTypes::OnEditchangeParam() +{ + CIniFile& ini=Map->GetIniFile(); + + CString Scripttype; + char action[50]; + if(m_Action.GetCurSel()<0) return; + if(m_ScriptType.GetCurSel()<0) return; + m_ScriptType.GetLBText(m_ScriptType.GetCurSel(), Scripttype); + TruncSpace(Scripttype); + + CString param; + m_Param.GetWindowText(param); + TruncSpace(param); + + param=TranslateHouse(param); + + itoa(m_Action.GetCurSel(), action, 10); + ini.sections[(LPCTSTR)Scripttype].values[action]=SetParam(ini.sections[(LPCTSTR)Scripttype].values[action], 1, (LPCTSTR)param); + + +} + +void CScriptTypes::OnSelchangeParam() +{ + m_Param.SetWindowText(GetText(&m_Param)); + OnEditchangeParam(); +} + +void CScriptTypes::OnAddaction() +{ + CIniFile& ini=Map->GetIniFile(); + + CString Scripttype; + if(m_ScriptType.GetCurSel()<0) return; + m_ScriptType.GetLBText(m_ScriptType.GetCurSel(), Scripttype); + TruncSpace(Scripttype); + + + char action[20]; + int count=ini.sections[(LPCTSTR)Scripttype].values.size()-1; + itoa(count,action,10); + ini.sections[(LPCTSTR)Scripttype].values[action]="0,0"; + + UpdateDialog(); +} + +void CScriptTypes::OnDeleteaction() +{ + CIniFile& ini=Map->GetIniFile(); + + CString Scripttype; + if(m_Action.GetCurSel()<0) return; + if(m_ScriptType.GetCurSel()<0) return; + m_ScriptType.GetLBText(m_ScriptType.GetCurSel(), Scripttype); + TruncSpace(Scripttype); + + + // okay, action is now the deleted one... + int i; + for(i=m_Action.GetCurSel(); iGetIniFile(); + + CString ID=GetFreeID(); + + CString p=GetFree("ScriptTypes"); + ini.sections["ScriptTypes"].values[p]=ID; + ini.sections[ID].values["Name"]="New script"; + + + + int i; + for(i=0;iUpdateDialogs(TRUE); + //UpdateDialog(); +} + +void CScriptTypes::OnDelete() +{ + CIniFile& ini=Map->GetIniFile(); + + CString Scripttype; + if(m_ScriptType.GetCurSel()<0) return; + m_ScriptType.GetLBText(m_ScriptType.GetCurSel(), Scripttype); + TruncSpace(Scripttype); + + int res=MessageBox("Are you sure to delete this ScriptType? Don´t forget to delete any references to this ScriptType","Delete ScriptType", MB_YESNO | MB_ICONQUESTION); + if(res!=IDYES) return; + + ini.sections.erase((LPCTSTR)Scripttype); + ini.sections["ScriptTypes"].values.erase(*ini.sections["ScriptTypes"].GetValueName(ini.sections["ScriptTypes"].FindValue((LPCTSTR)Scripttype))); + //UpdateDialog(); + ((CFinalSunDlg*)theApp.m_pMainWnd)->UpdateDialogs(TRUE); +} + + + +void CScriptTypes::ListBehaviours(CComboBox &cb) +{ + while(cb.DeleteString(0)!=CB_ERR); + + cb.AddString("0 - Sleep"); + cb.AddString("1 - Attack nearest enemy"); + cb.AddString("2 - Move"); + cb.AddString("3 - QMove"); + cb.AddString("4 - Retreat home for R&R"); + cb.AddString("5 - Guard"); + cb.AddString("6 - Sticky (never recruit)"); + cb.AddString("7 - Enter object"); + cb.AddString("8 - Capture object"); + cb.AddString("9 - Move into & get eaten"); + cb.AddString("10 - Harvest"); + cb.AddString("11 - Area Guard"); + cb.AddString("12 - Return (to refinery)"); + cb.AddString("13 - Stop"); + cb.AddString("14 - Ambush (wait until discovered)"); + cb.AddString("15 - Hunt"); + cb.AddString("16 - Unload"); + cb.AddString("17 - Sabotage (move in & destroy)"); + cb.AddString("18 - Construction"); + cb.AddString("19 - Deconstruction"); + cb.AddString("20 - Repair"); + cb.AddString("21 - Rescue"); + cb.AddString("22 - Missile"); + cb.AddString("23 - Harmless"); + cb.AddString("24 - Open"); + cb.AddString("25 - Patrol"); + cb.AddString("26 - Paradrop approach drop zone"); + cb.AddString("27 - Paradrop overlay drop zone"); + cb.AddString("28 - Wait"); + cb.AddString("29 - Attack move"); + if(yuri_mode) + { + // cb.AddString("30 - Spyplane approach"); + // cb.AddString("31 - Spyplane retreat"); + } +} + +BOOL CScriptTypes::OnInitDialog() +{ + CDialog::OnInitDialog(); + + while(m_Type.DeleteString(0)!=CB_ERR); + + + int i; + for(i=0;i0) + { + m_Type.AddString(p); + } + } + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} diff --git a/MissionEditor/ScriptTypes.h b/MissionEditor/ScriptTypes.h new file mode 100644 index 0000000..632d1e2 --- /dev/null +++ b/MissionEditor/ScriptTypes.h @@ -0,0 +1,89 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_SCRIPTTYPES_H__981EF700_951E_11D3_B63B_BCCF9C98B341__INCLUDED_) +#define AFX_SCRIPTTYPES_H__981EF700_951E_11D3_B63B_BCCF9C98B341__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ScriptTypes.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CScriptTypes + +class CScriptTypes : public CDialog +{ + DECLARE_DYNCREATE(CScriptTypes) + +// Konstruktion +public: + void UpdateDialog(); + CScriptTypes(); + ~CScriptTypes(); + +// Dialogfelddaten + //{{AFX_DATA(CScriptTypes) + enum { IDD = IDD_SCRIPTTYPES }; + CEdit m_DescriptionEx; + CStatic m_Desc; + CComboBox m_Type; + CComboBox m_ScriptType; + CComboBox m_Param; + CListBox m_Action; + CString m_Name; + //}}AFX_DATA + + +// Ăœberschreibungen + // Der Klassen-Assistent generiert virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CScriptTypes) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + void ListBehaviours(CComboBox& cb); + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CScriptTypes) + afx_msg void OnEditchangeScripttype(); + afx_msg void OnSelchangeScripttype(); + afx_msg void OnSelchangeAction(); + afx_msg void OnChangeName(); + afx_msg void OnEditchangeType(); + afx_msg void OnSelchangeType(); + afx_msg void OnEditchangeParam(); + afx_msg void OnSelchangeParam(); + afx_msg void OnAddaction(); + afx_msg void OnDeleteaction(); + afx_msg void OnAdd(); + afx_msg void OnDelete(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_SCRIPTTYPES_H__981EF700_951E_11D3_B63B_BCCF9C98B341__INCLUDED_ diff --git a/MissionEditor/SearchWaypointDlg.cpp b/MissionEditor/SearchWaypointDlg.cpp new file mode 100644 index 0000000..a344356 --- /dev/null +++ b/MissionEditor/SearchWaypointDlg.cpp @@ -0,0 +1,102 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// SearchWaypointDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "SearchWaypointDlg.h" +#include "variables.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CSearchWaypointDlg + + +CSearchWaypointDlg::CSearchWaypointDlg(CWnd* pParent /*=NULL*/) + : CDialog(CSearchWaypointDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CSearchWaypointDlg) + m_Waypoints = _T(""); + //}}AFX_DATA_INIT +} + + +void CSearchWaypointDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSearchWaypointDlg) + DDX_LBString(pDX, IDC_WAYPOINTS, m_Waypoints); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CSearchWaypointDlg, CDialog) + //{{AFX_MSG_MAP(CSearchWaypointDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CSearchWaypointDlg + +BOOL CSearchWaypointDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + CListBox& ctrl=*(CListBox*)GetDlgItem(IDC_WAYPOINTS); + + while(ctrl.DeleteString(0)!=LB_ERR); + + int i; + int count=Map->GetWaypointCount(); + + for(i=0;iGetWaypointData(i, &id, &pos); + + ctrl.SetItemData(ctrl.InsertString(i, id), i); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} + +void CSearchWaypointDlg::OnOK() +{ + CListBox& ctrl=*(CListBox*)GetDlgItem(IDC_WAYPOINTS); + + int sel=ctrl.GetCurSel(); + + if(sel<0) m_WaypointIndex=-1; + else + { + m_WaypointIndex=ctrl.GetItemData(sel); + } + + CDialog::OnOK(); +} diff --git a/MissionEditor/SearchWaypointDlg.h b/MissionEditor/SearchWaypointDlg.h new file mode 100644 index 0000000..6cb34b5 --- /dev/null +++ b/MissionEditor/SearchWaypointDlg.h @@ -0,0 +1,68 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_SEARCHWAYPOINTDLG_H__28D1CCC0_874C_11D5_89B3_00E07D97C331__INCLUDED_) +#define AFX_SEARCHWAYPOINTDLG_H__28D1CCC0_874C_11D5_89B3_00E07D97C331__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// SearchWaypointDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CSearchWaypointDlg + +class CSearchWaypointDlg : public CDialog +{ +// Konstruktion +public: + int m_WaypointIndex; + CSearchWaypointDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CSearchWaypointDlg) + enum { IDD = IDD_SEARCHWAYPOINT }; + CString m_Waypoints; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CSearchWaypointDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CSearchWaypointDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_SEARCHWAYPOINTDLG_H__28D1CCC0_874C_11D5_89B3_00E07D97C331__INCLUDED_ diff --git a/MissionEditor/ShutDownDlg.cpp b/MissionEditor/ShutDownDlg.cpp new file mode 100644 index 0000000..56f98d1 --- /dev/null +++ b/MissionEditor/ShutDownDlg.cpp @@ -0,0 +1,71 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// ShutDownDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "ShutDownDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CShutDownDlg + + +CShutDownDlg::CShutDownDlg(CWnd* pParent /*=NULL*/) + : CDialog(CShutDownDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CShutDownDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Elementinitialisierung ein + //}}AFX_DATA_INIT + + Create(CShutDownDlg::IDD, pParent); +} + + +void CShutDownDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CShutDownDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier DDX- und DDV-Aufrufe ein + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CShutDownDlg, CDialog) + //{{AFX_MSG_MAP(CShutDownDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Zuordnungsmakros fĂ¼r Nachrichten ein + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CShutDownDlg + + +void CShutDownDlg::PostNcDestroy() +{ + // delete this; +} diff --git a/MissionEditor/ShutDownDlg.h b/MissionEditor/ShutDownDlg.h new file mode 100644 index 0000000..24a019d --- /dev/null +++ b/MissionEditor/ShutDownDlg.h @@ -0,0 +1,69 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_SHUTDOWNDLG_H__28D9E061_8340_11D4_9C87_A1B9E12BB04A__INCLUDED_) +#define AFX_SHUTDOWNDLG_H__28D9E061_8340_11D4_9C87_A1B9E12BB04A__INCLUDED_ + +#include "resource.h" + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ShutDownDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CShutDownDlg + +class CShutDownDlg : public CDialog +{ +// Konstruktion +public: + CShutDownDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CShutDownDlg) + enum { IDD = IDD_SHUTDOWN }; + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Datenelemente ein + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CShutDownDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CShutDownDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Member-Funktionen ein + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_SHUTDOWNDLG_H__28D9E061_8340_11D4_9C87_A1B9E12BB04A__INCLUDED_ diff --git a/MissionEditor/SingleplayerSettings.cpp b/MissionEditor/SingleplayerSettings.cpp new file mode 100644 index 0000000..9a1c67c --- /dev/null +++ b/MissionEditor/SingleplayerSettings.cpp @@ -0,0 +1,227 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// SingleplayerSettings.cpp: implementation file +// + +#include "stdafx.h" +#include "finalsun.h" +#include "SingleplayerSettings.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// property page CSingleplayerSettings + +IMPLEMENT_DYNCREATE(CSingleplayerSettings, CDialog) + +CSingleplayerSettings::CSingleplayerSettings() : CDialog(IDD) +{ + //{{AFX_DATA_INIT(CSingleplayerSettings) + + //}}AFX_DATA_INIT +} + +CSingleplayerSettings::~CSingleplayerSettings() +{ +} + +void CSingleplayerSettings::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSingleplayerSettings) + DDX_Control(pDX, IDC_TIMERINHERIT, m_TimerInherit); + DDX_Control(pDX, IDC_STARTINGDROPSHIPS, m_StartingDropships); + DDX_Control(pDX, IDC_FILLSILOS, m_FillSilos); + DDX_Control(pDX, IDC_CARRYOVERMONEY, m_CarryOverMoney); + DDX_Control(pDX, IDC_WIN, m_Win); + DDX_Control(pDX, IDC_PREMAPSELECT, m_PreMapSelect); + DDX_Control(pDX, IDC_POSTSCORE, m_PostScore); + DDX_Control(pDX, IDC_LOSE, m_Lose); + DDX_Control(pDX, IDC_INTRO, m_Intro); + DDX_Control(pDX, IDC_BRIEF, m_Brief); + DDX_Control(pDX, IDC_ACTION, m_Action); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CSingleplayerSettings, CDialog) + //{{AFX_MSG_MAP(CSingleplayerSettings) + ON_CBN_EDITCHANGE(IDC_INTRO, OnEditchangeIntro) + ON_CBN_EDITCHANGE(IDC_BRIEF, OnEditchangeBrief) + ON_CBN_EDITCHANGE(IDC_WIN, OnEditchangeWin) + ON_CBN_EDITCHANGE(IDC_LOSE, OnEditchangeLose) + ON_CBN_EDITCHANGE(IDC_ACTION, OnEditchangeAction) + ON_CBN_EDITCHANGE(IDC_POSTSCORE, OnEditchangePostscore) + ON_CBN_EDITCHANGE(IDC_PREMAPSELECT, OnEditchangePremapselect) + ON_CBN_EDITCHANGE(IDC_STARTINGDROPSHIPS, OnEditchangeStartingdropships) + ON_EN_CHANGE(IDC_CARRYOVERMONEY, OnChangeCarryovermoney) + ON_CBN_EDITCHANGE(IDC_TIMERINHERIT, OnEditchangeTimerinherit) + ON_CBN_EDITCHANGE(IDC_FILLSILOS, OnEditchangeFillsilos) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// message handlers + +void CSingleplayerSettings::UpdateDialog() +{ + CIniFile& ini=Map->GetIniFile(); + + CIniFileSection& sec=ini.sections["Basic"]; + + if(sec.values.find("Intro")!=sec.values.end()) + m_Intro.SetWindowText(sec.values["Intro"]); + if(sec.values.find("Brief")!=sec.values.end()) + m_Brief.SetWindowText(sec.values["Brief"]); + if(sec.values.find("Win")!=sec.values.end()) + m_Win.SetWindowText(sec.values["Win"]); + if(sec.values.find("Lose")!=sec.values.end()) + m_Lose.SetWindowText(sec.values["Lose"]); + if(sec.values.find("Action")!=sec.values.end()) + m_Action.SetWindowText(sec.values["Action"]); + if(sec.values.find("PostScore")!=sec.values.end()) + m_PostScore.SetWindowText(sec.values["PostScore"]); + if(sec.values.find("PreMapSelect")!=sec.values.end()) + m_PreMapSelect.SetWindowText(sec.values["PreMapSelect"]); + + if(sec.values.find("StartingDropships")!=sec.values.end()) + m_StartingDropships.SetWindowText(sec.values["StartingDropships"]); + if(sec.values.find("CarryOverMoney")!=sec.values.end()) + m_CarryOverMoney.SetWindowText(sec.values["CarryOverMoney"]); + if(sec.values.find("TimerInherit")!=sec.values.end()) + m_TimerInherit.SetWindowText(sec.values["TimerInherit"]); + if(sec.values.find("FillSilos")!=sec.values.end()) + m_FillSilos.SetWindowText(sec.values["FillSilos"]); + + ListMovies(m_Intro, TRUE); + ListMovies(m_Brief, TRUE); + ListMovies(m_Win, TRUE); + ListMovies(m_Lose, TRUE); + ListMovies(m_Action, TRUE); + ListMovies(m_PostScore, TRUE); + ListMovies(m_PreMapSelect, TRUE); + + + UpdateStrings(); +} + +void CSingleplayerSettings::OnEditchangeIntro() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["Intro"]=GetText(&m_Intro); +} + +void CSingleplayerSettings::OnEditchangeBrief() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["Brief"]=GetText(&m_Brief); +} + +void CSingleplayerSettings::OnEditchangeWin() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["Win"]=GetText(&m_Win); +} + +void CSingleplayerSettings::OnEditchangeLose() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["Lose"]=GetText(&m_Lose); +} + +void CSingleplayerSettings::OnEditchangeAction() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["Action"]=GetText(&m_Action); +} + +void CSingleplayerSettings::OnEditchangePostscore() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["PostScore"]=GetText(&m_PostScore); +} + +void CSingleplayerSettings::OnEditchangePremapselect() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["PreMapSelect"]=GetText(&m_PreMapSelect); +} + +void CSingleplayerSettings::OnEditchangeStartingdropships() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["StartingDropships"]=GetText(&m_StartingDropships); +} + +void CSingleplayerSettings::OnChangeCarryovermoney() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["CarryOverMoney"]=GetText(&m_CarryOverMoney); +} + +void CSingleplayerSettings::OnEditchangeTimerinherit() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["TimerInherit"]=GetText(&m_TimerInherit); +} + +void CSingleplayerSettings::OnEditchangeFillsilos() +{ + CIniFile& ini=Map->GetIniFile(); + ini.sections["Basic"].values["FillSilos"]=GetText(&m_FillSilos); +} + +void CSingleplayerSettings::UpdateStrings() +{ + SetDlgItemText(IDC_LSTARTINGDROPSHIPS, GetLanguageStringACP("SingleplayerStartingDropships")); + SetDlgItemText(IDC_LCARRYOVERMONEY, GetLanguageStringACP("SingleplayerCarryOverMoney")); + SetDlgItemText(IDC_LINHERITTIMER, GetLanguageStringACP("SingleplayerTimerInherit")); + SetDlgItemText(IDC_LFILLSILOS, GetLanguageStringACP("SingleplayerFillSilos")); + SetDlgItemText(IDC_LMOVIES, GetLanguageStringACP("SingleplayerMovies")); + SetDlgItemText(IDC_LINTRO, GetLanguageStringACP("SingleplayerIntro")); + SetDlgItemText(IDC_LBRIEF, GetLanguageStringACP("SingleplayerBrief")); + SetDlgItemText(IDC_LWIN, GetLanguageStringACP("SingleplayerWin")); + SetDlgItemText(IDC_LLOSE, GetLanguageStringACP("SingleplayerLose")); + SetDlgItemText(IDC_LACTION, GetLanguageStringACP("SingleplayerAction")); + SetDlgItemText(IDC_LPOSTSCORE, GetLanguageStringACP("SingleplayerPostScore")); + SetDlgItemText(IDC_LPREMAPSELECT, GetLanguageStringACP("SingleplayerPreMapSelect")); + SetDlgItemText(IDC_DESC, GetLanguageStringACP("SingleplayerDesc")); + + SetWindowText(TranslateStringACP("Singleplayer settings")); + +#ifdef RA2_MODE + GetDlgItem(IDC_LSTARTINGDROPSHIPS)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_STARTINGDROPSHIPS)->ShowWindow(SW_HIDE); +#endif +} + +void CSingleplayerSettings::PostNcDestroy() +{ + // do not call CDialog::PostNcDestroy(); + // CDialog::PostNcDestroy(); +} diff --git a/MissionEditor/SingleplayerSettings.h b/MissionEditor/SingleplayerSettings.h new file mode 100644 index 0000000..835e23f --- /dev/null +++ b/MissionEditor/SingleplayerSettings.h @@ -0,0 +1,92 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_SINGLEPLAYERSETTINGS_H__082D6780_CA89_11D3_B63B_00485453E8BA__INCLUDED_) +#define AFX_SINGLEPLAYERSETTINGS_H__082D6780_CA89_11D3_B63B_00485453E8BA__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// SingleplayerSettings.h : Header file +// + +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +// dialog field CSingleplayerSettings + +class CSingleplayerSettings : public CDialog +{ + DECLARE_DYNCREATE(CSingleplayerSettings) + +// construction +public: + void UpdateStrings(); + void UpdateDialog(); + CSingleplayerSettings(); + ~CSingleplayerSettings(); + +// dialog field data + //{{AFX_DATA(CSingleplayerSettings) + enum { IDD = IDD_SINGLEPLAYER }; + CMyComboBox m_TimerInherit; + CMyComboBox m_StartingDropships; + CMyComboBox m_FillSilos; + CFloatEdit m_CarryOverMoney; + CMyComboBox m_Win; + CMyComboBox m_PreMapSelect; + CMyComboBox m_PostScore; + CMyComboBox m_Lose; + CMyComboBox m_Intro; + CMyComboBox m_Brief; + CMyComboBox m_Action; + //}}AFX_DATA + + +// overwriteables + //{{AFX_VIRTUAL(CSingleplayerSettings) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // ddx/ddv support + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// implementation +protected: + // generated message maps + //{{AFX_MSG(CSingleplayerSettings) + afx_msg void OnEditchangeIntro(); + afx_msg void OnEditchangeBrief(); + afx_msg void OnEditchangeWin(); + afx_msg void OnEditchangeLose(); + afx_msg void OnEditchangeAction(); + afx_msg void OnEditchangePostscore(); + afx_msg void OnEditchangePremapselect(); + afx_msg void OnEditchangeStartingdropships(); + afx_msg void OnChangeCarryovermoney(); + afx_msg void OnEditchangeTimerinherit(); + afx_msg void OnEditchangeFillsilos(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} + +#endif // AFX_SINGLEPLAYERSETTINGS_H__082D6780_CA89_11D3_B63B_00485453E8BA__INCLUDED_ diff --git a/MissionEditor/SpecialFlags.cpp b/MissionEditor/SpecialFlags.cpp new file mode 100644 index 0000000..20027c1 --- /dev/null +++ b/MissionEditor/SpecialFlags.cpp @@ -0,0 +1,311 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// SpecialFlags.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "SpecialFlags.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CSpecialFlags + + +CSpecialFlags::CSpecialFlags(CWnd* pParent /*=NULL*/) + : CDialog(CSpecialFlags::IDD, 0) +{ + //{{AFX_DATA_INIT(CSpecialFlags) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Elementinitialisierung ein + //}}AFX_DATA_INIT +} + + +void CSpecialFlags::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSpecialFlags) + DDX_Control(pDX, IDC_VISCEROIDS, m_Visceroids); + DDX_Control(pDX, IDC_TIBERIUMSPREADS, m_TiberiumSpreads); + DDX_Control(pDX, IDC_TIBERIUMGROWS, m_TiberiumGrows); + DDX_Control(pDX, IDC_TIBERIUMEXPLOSIVE, m_TiberiumExplosive); + DDX_Control(pDX, IDC_METEORITES, m_Meteorites); + DDX_Control(pDX, IDC_MCVDEPLOY, m_MCVDeploy); + DDX_Control(pDX, IDC_IONSTORMS, m_IonStorms); + DDX_Control(pDX, IDC_INITIALVETERAN, m_InitialVeteran); + DDX_Control(pDX, IDC_INERT, m_Inert); + DDX_Control(pDX, IDC_HARVESTERIMMUNE, m_HarvesterImmune); + DDX_Control(pDX, IDC_FOGOFWAR, m_FogOfWar); + DDX_Control(pDX, IDC_FIXEDALLIANCE, m_FixedAlliance); + DDX_Control(pDX, IDC_DESTROYABLEBRIDGES, m_DestroyableBridges); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CSpecialFlags, CDialog) + //{{AFX_MSG_MAP(CSpecialFlags) + ON_CBN_EDITCHANGE(IDC_TIBERIUMGROWS, OnEditchangeTiberiumgrows) + ON_CBN_EDITCHANGE(IDC_TIBERIUMSPREADS, OnEditchangeTiberiumspreads) + ON_CBN_EDITCHANGE(IDC_TIBERIUMEXPLOSIVE, OnEditchangeTiberiumexplosive) + ON_CBN_EDITCHANGE(IDC_DESTROYABLEBRIDGES, OnEditchangeDestroyablebridges) + ON_CBN_EDITCHANGE(IDC_MCVDEPLOY, OnEditchangeMcvdeploy) + ON_CBN_EDITCHANGE(IDC_INITIALVETERAN, OnEditchangeInitialveteran) + ON_CBN_EDITCHANGE(IDC_FIXEDALLIANCE, OnEditchangeFixedalliance) + ON_CBN_EDITCHANGE(IDC_HARVESTERIMMUNE, OnEditchangeHarvesterimmune) + ON_CBN_EDITCHANGE(IDC_FOGOFWAR, OnEditchangeFogofwar) + ON_CBN_EDITCHANGE(IDC_INERT, OnEditchangeInert) + ON_CBN_EDITCHANGE(IDC_IONSTORMS, OnEditchangeIonstorms) + ON_CBN_EDITCHANGE(IDC_METEORITES, OnEditchangeMeteorites) + ON_CBN_EDITCHANGE(IDC_VISCEROIDS, OnEditchangeVisceroids) + + ON_CBN_SELCHANGE(IDC_TIBERIUMGROWS, OnEditchangeTiberiumgrows) + ON_CBN_SELCHANGE(IDC_TIBERIUMSPREADS, OnEditchangeTiberiumspreads) + ON_CBN_SELCHANGE(IDC_TIBERIUMEXPLOSIVE, OnEditchangeTiberiumexplosive) + ON_CBN_SELCHANGE(IDC_DESTROYABLEBRIDGES, OnEditchangeDestroyablebridges) + ON_CBN_SELCHANGE(IDC_MCVDEPLOY, OnEditchangeMcvdeploy) + ON_CBN_SELCHANGE(IDC_INITIALVETERAN, OnEditchangeInitialveteran) + ON_CBN_SELCHANGE(IDC_FIXEDALLIANCE, OnEditchangeFixedalliance) + ON_CBN_SELCHANGE(IDC_HARVESTERIMMUNE, OnEditchangeHarvesterimmune) + ON_CBN_SELCHANGE(IDC_FOGOFWAR, OnEditchangeFogofwar) + ON_CBN_SELCHANGE(IDC_INERT, OnEditchangeInert) + ON_CBN_SELCHANGE(IDC_IONSTORMS, OnEditchangeIonstorms) + ON_CBN_SELCHANGE(IDC_METEORITES, OnEditchangeMeteorites) + ON_CBN_SELCHANGE(IDC_VISCEROIDS, OnEditchangeVisceroids) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +void CSpecialFlags::UpdateDialog() +{ + CIniFile& ini=Map->GetIniFile(); + + CIniFileSection *sec; + sec=&ini.sections["SpecialFlags"]; + m_DestroyableBridges.SetWindowText(sec->values["DestroyableBridges"]); + m_FixedAlliance.SetWindowText(sec->values["FixedAlliance"]); + m_FogOfWar.SetWindowText(sec->values["FogOfWar"]); + m_HarvesterImmune.SetWindowText(sec->values["HarvesterImmune"]); + m_Inert.SetWindowText(sec->values["Inert"]); + m_InitialVeteran.SetWindowText(sec->values["InitialVeteran"]); + m_IonStorms.SetWindowText(sec->values["IonStorms"]); + m_MCVDeploy.SetWindowText(sec->values["MCVDeploy"]); + m_Meteorites.SetWindowText(sec->values["Meteorites"]); + m_TiberiumExplosive.SetWindowText(sec->values["TiberiumExplosive"]); + m_TiberiumGrows.SetWindowText(sec->values["TiberiumGrows"]); + m_TiberiumSpreads.SetWindowText(sec->values["TiberiumSpreads"]); + m_Visceroids.SetWindowText(sec->values["Visceroids"]); + +#ifdef RA2_MODE + SetDlgItemText(IDC_LTIBERIUMGROWS,"Ore grows:"); + SetDlgItemText(IDC_LTIBERIUMSPREADS,"Ore spreads:"); + GetDlgItem(IDC_LTIBERIUMEXPLOSIVE)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_TIBERIUMEXPLOSIVE)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_HARVESTERIMMUNE)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_LHARVESTERIMMUNE)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_METEORITES)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_LMETEORITES)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_VISCEROIDS)->ShowWindow(SW_HIDE); + GetDlgItem(IDC_LVISCEROIDS)->ShowWindow(SW_HIDE); + + SetDlgItemText(IDC_LFOGOFWAR, "Shroud:"); + SetDlgItemText(IDC_LIONSTORMS, "Weather Storms:"); +#endif + +}; +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CSpecialFlags + +void CSpecialFlags::OnEditchangeTiberiumgrows() +{ + CIniFile& ini=Map->GetIniFile(); + + CIniFileSection *sec; + sec=&ini.sections["SpecialFlags"]; + CString str; + + + str=GetText(&m_TiberiumGrows); + sec->values["TiberiumGrows"]=(LPCTSTR)str; +} + +void CSpecialFlags::OnEditchangeTiberiumspreads() +{ + CIniFile& ini=Map->GetIniFile(); + + CIniFileSection *sec; + sec=&ini.sections["SpecialFlags"]; + CString str; + + + str=GetText(&m_TiberiumSpreads); + sec->values["TiberiumSpreads"]=(LPCTSTR)str; +} + +void CSpecialFlags::OnEditchangeTiberiumexplosive() +{ + CIniFile& ini=Map->GetIniFile(); + + CIniFileSection *sec; + sec=&ini.sections["SpecialFlags"]; + CString str; + + + str=GetText(&m_TiberiumExplosive); + sec->values["TiberiumExplosive"]=(LPCTSTR)str; +} + +void CSpecialFlags::OnEditchangeDestroyablebridges() +{ + CIniFile& ini=Map->GetIniFile(); + + CIniFileSection *sec; + sec=&ini.sections["SpecialFlags"]; + CString str; + + + str=GetText(&m_DestroyableBridges); + sec->values["DestroyableBridges"]=(LPCTSTR)str; +} + +void CSpecialFlags::OnEditchangeMcvdeploy() +{ + CIniFile& ini=Map->GetIniFile(); + + CIniFileSection *sec; + sec=&ini.sections["SpecialFlags"]; + CString str; + + + str=GetText(&m_MCVDeploy); + sec->values["MCVDeploy"]=(LPCTSTR)str; +} + +void CSpecialFlags::OnEditchangeInitialveteran() +{ + CIniFile& ini=Map->GetIniFile(); + + CIniFileSection *sec; + sec=&ini.sections["SpecialFlags"]; + CString str; + + + str=GetText(&m_InitialVeteran); + sec->values["InitialVeteran"]=(LPCTSTR)str; +} + +void CSpecialFlags::OnEditchangeFixedalliance() +{ + CIniFile& ini=Map->GetIniFile(); + + CIniFileSection *sec; + sec=&ini.sections["SpecialFlags"]; + CString str; + + + str=GetText(&m_FixedAlliance); + sec->values["FixedAlliance"]=(LPCTSTR)str; +} + +void CSpecialFlags::OnEditchangeHarvesterimmune() +{ + CIniFile& ini=Map->GetIniFile(); + + CIniFileSection *sec; + sec=&ini.sections["SpecialFlags"]; + CString str; + + + str=GetText(&m_HarvesterImmune); + sec->values["HarvesterImmune"]=(LPCTSTR)str; +} + +void CSpecialFlags::OnEditchangeFogofwar() +{ + CIniFile& ini=Map->GetIniFile(); + + CIniFileSection *sec; + sec=&ini.sections["SpecialFlags"]; + CString str; + + + str=GetText(&m_FogOfWar); + sec->values["FogOfWar"]=(LPCTSTR)str; +} + +void CSpecialFlags::OnEditchangeInert() +{ + CIniFile& ini=Map->GetIniFile(); + + CIniFileSection *sec; + sec=&ini.sections["SpecialFlags"]; + CString str; + + + str=GetText(&m_Inert); + sec->values["Inert"]=(LPCTSTR)str; +} + +void CSpecialFlags::OnEditchangeIonstorms() +{ + CIniFile& ini=Map->GetIniFile(); + + CIniFileSection *sec; + sec=&ini.sections["SpecialFlags"]; + CString str; + + + str=GetText(&m_IonStorms); + sec->values["IonStorms"]=(LPCTSTR)str; +} + +void CSpecialFlags::OnEditchangeMeteorites() +{ + CIniFile& ini=Map->GetIniFile(); + + CIniFileSection *sec; + sec=&ini.sections["SpecialFlags"]; + CString str; + + + str=GetText(&m_Meteorites); + sec->values["Meteorites"]=(LPCTSTR)str; +} + +void CSpecialFlags::OnEditchangeVisceroids() +{ + CIniFile& ini=Map->GetIniFile(); + + CIniFileSection *sec; + sec=&ini.sections["SpecialFlags"]; + CString str; + + + str=GetText(&m_Visceroids); + sec->values["Visceroids"]=(LPCTSTR)str; +} diff --git a/MissionEditor/SpecialFlags.h b/MissionEditor/SpecialFlags.h new file mode 100644 index 0000000..e02146e --- /dev/null +++ b/MissionEditor/SpecialFlags.h @@ -0,0 +1,91 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_SPECIALFLAGS_H__500DF000_7058_11D3_99E1_97DB32807805__INCLUDED_) +#define AFX_SPECIALFLAGS_H__500DF000_7058_11D3_99E1_97DB32807805__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// SpecialFlags.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CSpecialFlags + +class CSpecialFlags : public CDialog +{ +// Konstruktion +public: + void UpdateDialog(); + CSpecialFlags(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CSpecialFlags) + enum { IDD = IDD_SPECIALFLAGS }; + CMyComboBox m_Visceroids; + CMyComboBox m_TiberiumSpreads; + CMyComboBox m_TiberiumGrows; + CMyComboBox m_TiberiumExplosive; + CMyComboBox m_Meteorites; + CMyComboBox m_MCVDeploy; + CMyComboBox m_IonStorms; + CMyComboBox m_InitialVeteran; + CMyComboBox m_Inert; + CMyComboBox m_HarvesterImmune; + CMyComboBox m_FogOfWar; + CMyComboBox m_FixedAlliance; + CMyComboBox m_DestroyableBridges; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CSpecialFlags) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CSpecialFlags) + afx_msg void OnEditchangeTiberiumgrows(); + afx_msg void OnEditchangeTiberiumspreads(); + afx_msg void OnEditchangeTiberiumexplosive(); + afx_msg void OnEditchangeDestroyablebridges(); + afx_msg void OnEditchangeMcvdeploy(); + afx_msg void OnEditchangeInitialveteran(); + afx_msg void OnEditchangeFixedalliance(); + afx_msg void OnEditchangeHarvesterimmune(); + afx_msg void OnEditchangeFogofwar(); + afx_msg void OnEditchangeInert(); + afx_msg void OnEditchangeIonstorms(); + afx_msg void OnEditchangeMeteorites(); + afx_msg void OnEditchangeVisceroids(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_SPECIALFLAGS_H__500DF000_7058_11D3_99E1_97DB32807805__INCLUDED_ diff --git a/MissionEditor/StdAfx.cpp b/MissionEditor/StdAfx.cpp new file mode 100644 index 0000000..e687021 --- /dev/null +++ b/MissionEditor/StdAfx.cpp @@ -0,0 +1,36 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// stdafx.cpp : Quelltextdatei, die nur die Standard-Includes einbindet +// TiberianSun Mission Editor.pch ist die vorcompilierte Header-Datei +// stdafx.obj enthält die vorcompilierte Typinformation + +#include "stdafx.h" + +#include "structs.h" + + + +TILEDATA::~TILEDATA() +{ + memset(this,0, sizeof(TILEDATA)); +} + + diff --git a/MissionEditor/StdAfx.h b/MissionEditor/StdAfx.h new file mode 100644 index 0000000..456a46f --- /dev/null +++ b/MissionEditor/StdAfx.h @@ -0,0 +1,64 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// stdafx.h : include everything that should be available everywhere in the code +// + +#if !defined(AFX_STDAFX_H__9F773426_63BB_11D3_99E0_C30F10710B17__INCLUDED_) +#define AFX_STDAFX_H__9F773426_63BB_11D3_99E0_C30F10710B17__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#define VC_EXTRALEAN +#define NOMINMAX + +#pragma warning(disable: 4503) +#pragma warning(disable: 4786) +#pragma warning(disable: 4800) + + +#include +#include +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include +#endif + +#include "defines.h" +#include "IniFile.h" +#include "InputBox.h" +#include "floatedit.h" +#include "MyComboBox.h" +#include +// #include "structs.h" +// #include "variables.h" +// #include "functions.h" +// #include "inlines.h" +// #include "MapData.h" +#include "resource.h" +#include "TipDlg.h" + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ inserts additional declarations exactly above this line. + +#endif // !defined(AFX_STDAFX_H__9F773426_63BB_11D3_99E0_C30F10710B17__INCLUDED_) + diff --git a/MissionEditor/Structs.h b/MissionEditor/Structs.h new file mode 100644 index 0000000..d536611 --- /dev/null +++ b/MissionEditor/Structs.h @@ -0,0 +1,658 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/************************************** + Global structs here +**************************************/ + +#ifndef GLOBALSTRUCTS_H_INCLUDED +#define GLOBALSTRUCTS_H_INCLUDED + +#include "defines.h" +#include +#include +#include +#include "MissionEditorPackLib.h" +#include "Vec2.h" + +class MapTool; + + +enum class TheaterChar : char +{ + T = 'T', + A = 'A', + U = 'U', + N = 'N', + D = 'D', + L = 'L', + Generic = 'G', + None = 0 +}; + +inline TheaterChar toTheaterChar(char c) +{ + switch (c) + { + case 'T': + return TheaterChar::T; + case 'A': + return TheaterChar::A; + case 'U': + return TheaterChar::U; + case 'N': + return TheaterChar::N; + case 'D': + return TheaterChar::D; + case 'L': + return TheaterChar::L; + case 'G': + return TheaterChar::Generic; + default: + return TheaterChar::None; + } +} + +struct CLIPBOARD_MAPCOPY_ENTRY +{ + BOOL bRedrawTerrain; + BYTE overlay; + BYTE overlaydata; + WORD wGround; + WORD bMapData; + BYTE bSubTile; + BYTE bHeight; + BYTE bMapData2; + + // for RA2<->TS conversion: + WORD wTileSet; + BYTE bTile; +}; + +struct CLIPBOARD_DATA +{ + DWORD dwType; + DWORD dwVersion; + DWORD dwReserved; + BYTE bGame; // 0 TS, 1 RA2 + UINT iWidth; + UINT iHeight; +}; + +struct VBORDER +{ + short left; + short right; +}; + +/* +picdata + +Holds information for every picture: +a directdraw surface, and additional data +*/ +struct PICDATA{ + PICDATA() = default; + PICDATA(const PICDATA& c) = default; + PICDATA& operator=(const PICDATA& c) = default; + ~PICDATA() = default; + +#ifndef NOSURFACES_OBJECTS + LPDIRECTDRAWSURFACE4 pic; +#else + void* pic = nullptr; // BYTE* to image, exception: if bType==PICDATA_TYPE_BMP then this is a LPDIRECTDRAWSURFACE! + VBORDER* vborder = nullptr; + int* pal = nullptr; + std::shared_ptr> lighting; + std::shared_ptr> rawPic; + std::shared_ptr> _vBorder; +#endif + + FSunPackLib::VoxelNormalClass normalClass = FSunPackLib::VoxelNormalClass::Unknown; + short x = 0; // for SHPs (starting point of main graphic inside surface) + short y = 0; // for SHPs (starting point of main graphic inside surface) + WORD wWidth = 0; // for non-shps: size of whole surface, else size of main graphic + WORD wHeight = 0; // for non-shps: size of whole surface, else size of main graphic + WORD wMaxWidth = 0; // for SHPs (size of whole surface) + WORD wMaxHeight = 0; // for SHPs (size of whole surface) + BYTE bType = 0; // is loaded from voxel, shp, bmp, etc... (for drawing logic) + TheaterChar bTerrain = TheaterChar::None; + BOOL bTried = 0; // already tried to load this? - superseded by global array missingimages + + inline ProjectedVec drawOffset() const + { + return ProjectedVec(x, y); + } + +#ifdef NOSURFACES_OBJECTS + void createVBorder(); +#endif + +}; + +/* +TILEPIC / TILEDATA + +Holds information for every tile/subtile in TS. +*/ +struct SUBTILE{ +#ifndef NOSURFACES + LPDIRECTDRAWSURFACE4 pic; +#else +#ifdef NOSURFACES_EXTRACT + BOOL bNotExtracted; // pic is not extracted, even if NOSURFACES_EXTRACT is specifed. Probably there is inner transparency! +#endif + BYTE* pic; // optionally use direct blitting? This is either a palette index array or non-palette data (if NOSURFACES_EXTRACT is specified) + VBORDER * vborder; +#endif + + WORD wWidth; // width of tile + WORD wHeight; // height " + short sX; // x starting pos + short sY; // y starting pos + BYTE bZHeight; // z difference from tile ground surface (1unit == f_y/2pixel == 12pixel) + BYTE bDirection; // for ramps for example + BYTE bTerrainType; // water, etc... + RGBTRIPLE rgbLeft; + RGBTRIPLE rgbRight; + BYTE bHackedTerrainType; // same like bTerrainType, except some shore pieces that were hacked in fsdata.ini + + std::shared_ptr anim; + + inline ProjectedVec drawOffset() const + { + return ProjectedVec(sX, sY); + } +}; +struct TILEDATA{ + TILEDATA() = default; + ~TILEDATA(); + WORD wTileSet = 0; + SUBTILE* tiles = nullptr; // the different tiles + WORD wTileCount = 0; // number of tiles + WORD cx = 0; + WORD cy = 0; + BOOL bAllowTiberium = 0; + BOOL bAllowToPlace = TRUE; + BOOL bMorphable = FALSE; // morphable using lower/raise ground function? + BOOL bHide = FALSE; // for user interface only + BOOL bMarbleMadness = FALSE; + WORD wMarbleGround = 0xFFFF; + +public: + RECT rect = { 0 }; + + TILEDATA* lpReplacements = nullptr; + BYTE bReplacementCount = 0; +}; + +/* +actiondata + +CViewObjects sets this data struct, +and CIsoView uses it to interact with the user´s CViewObjects and terrain editing choice +*/ +struct ACTIONDATA{ + DWORD mode; + DWORD type; + DWORD data; + DWORD data2; + DWORD data3; + int z_data; + CString data_s; + std::unique_ptr tool; + + ~ACTIONDATA(); + + void reset(); +}; + +struct SIDEINFO{ + CString name; + int orig_n; +}; + +struct HOUSEINFO{ + CString name; + SIDEINFO* side; // side is used for rules.ini owner= settings + RGBTRIPLE color; + BOOL bPlayable; +}; + +/********************** + Unittype infos +**********************/ + +/* +building infos +*/ +struct BUILDING_INFO +{ + PICDATA pic[8]; + int pic_count; + BYTE w; + BYTE h; + BOOL bTemp; + BOOL bSnow; + BOOL bUrban; +}; + +struct TREE_INFO +{ + PICDATA pic; + BYTE w; + BYTE h; +}; + +#ifdef SMUDGE_SUPP +struct SMUDGE_INFO +{ + PICDATA pic; + //BYTE w; + //BYTE h; +}; +#endif + +/* +** Condition enumeration +*/ +enum ConditionEnum { + COND_LT = 0, // less than + COND_LE, // less than or equal to + COND_EQ, // equal to + COND_GE, // greater than or equal to + COND_GT, // greater than + COND_NE, // not equal to + COND_COUNT +}; + +struct AITrigInfo +{ + union{ + struct{ + int Number; + ConditionEnum Condition; + }; + char Padding[32]; + }; +}; + + +/* +Struct for string items +*/ +struct XCString +{ + XCString() + { + //wString=new(WCHAR[2]); + //memset(wString, 0, 4); + wString=NULL; + bUsedDefault=FALSE; + len=0; + } + ~XCString() + { + if(wString) delete[] wString; + len=0; + wString=NULL; + } + void SetString(const CHAR* cString) + { + len=strlen(cString); + + this->cString=cString; + + if(wString) delete[] wString; + + bUsedDefault=FALSE; + wString=new(WCHAR[len+1]); + memset(wString, 0, (len+1)*2); + + //MultiByteToWideChar(CP_ACP, WC_COMPOSITECHECK, cString, len, wString, len+1); + mbstowcs(wString, cString, len); + + } + void SetString(const WCHAR* wString, int len) + { + this->len=len; + + if(this->wString) delete[] this->wString; + + bUsedDefault=FALSE; + + this->wString=new(WCHAR[len+1]); + memset(this->wString, 0, (len+1)*2); + memcpy(this->wString, wString, len*2); + + auto bufferSize = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, this->wString, len + 1, nullptr, 0, NULL, &bUsedDefault); + if (bufferSize == 0) + { + cString = ""; + return; // failed + } + + std::vector bByte(bufferSize + 4, 0); + if (WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, this->wString, len + 1, (LPSTR)bByte.data(), bufferSize, NULL, &bUsedDefault) == 0) + { + cString = ""; + return; // failed + } + cString = bByte.data(); + + } + CString cString; + WCHAR* wString; + BOOL bUsedDefault; + int len; +}; + + +/********************** + Map stuff structs +***********************/ + +/* +AITRIGGERTYPE{}; + +Data for ai trigger types +*/ +struct AITRIGGERTYPE{ + CString ID; // ai trigger id + CString name; // param 1 + CString teamtype1; // param 2 + CString owner; // param 3 + CString techlevel; // flag 1/ param 4 + CString type; // param 5 + CString unittype; // param 6 + CString data; // param 7 + CString float1; // param 8 + CString float2; // param 9 + CString float3; // param 10 + CString skirmish; // param 11 + CString flag4; // param 12 + CString multihouse; // param 13 + CString basedefense; // param 14 + CString teamtype2; // param 15 + CString easy; // param 16 + CString medium; // param 17 + CString hard; // param 18 +}; + +/* +STDOBJECTDATA + +Data for Trees, Units, Infantry, Aircraft & Structures +This should be used for painting procedure... +except if you want to draw the upgrades on buildings +*/ +struct STDOBJECTDATA +{ + CString house; // 1 + CString type; // 2 + CString strength; // 3 + CString y; // 4 + CString x; // 5 +}; + +/* +STRUCTURE + +Data for a structure +*/ +struct STRUCTURE{ + CString house; // 1 + CString type; // 2 + CString strength; // 3 + CString y; // 4 + CString x; // 5 + CString direction; // 6 + CString tag; // 7 + CString flag1; // 8 + CString flag2; // 9 + CString energy; // 10 + CString upgradecount; // 11 + CString spotlight; // 12 + CString upgrade1; // 13 + CString upgrade2; // 14 + CString upgrade3; // 15 + CString flag3; // 16 + CString flag4; // 17 + unsigned deleted:1; +}; + +// structure data especially for painting +struct STRUCTUREPAINT{ + COLORREF col; + CString type; + short x; + short y; + short direction; + BYTE strength; + BYTE upradecount; + CString upgrade1; + CString upgrade2; + CString upgrade3; +}; + + +/* +struct INFANTRY{}; + +Data for an infantry unit +*/ +struct INFANTRY{ + CString house; // 1 + CString type; // 2 + CString strength; // 3 + CString y; // 4 + CString x; // 5 + CString pos; // 6 + CString action; // 7 + CString direction; // 8 + CString tag; // 9 + CString flag1; // 10 + CString flag2; // 11 + CString flag3; // 12 + CString flag4; // 13 + CString flag5; // 14 + unsigned deleted:1; +}; + +struct UNIT{ + CString house; // 1 + CString type; // 2 + CString strength; // 3 + CString y; // 4 + CString x; // 5 + CString direction; // 6 + CString action; // 7 + CString tag; // 8 + CString flag1; // 9 + CString flag2; // 10 + CString flag3; // 11 + CString flag4; // 12 + CString flag5; // 13 + CString flag6; // 14 + unsigned deleted:1; +}; + + + +struct AIRCRAFT{ + CString house; // 1 + CString type; // 2 + CString strength; // 3 + CString y; // 4 + CString x; // 5 + CString direction; // 6 + CString action; // 7 + CString tag; // 8 + CString flag1; // 9 + CString flag2; // 10 + CString flag3; // 11 + CString flag4; // 12 + unsigned deleted:1; +}; + +struct TERRAIN{ + CString type; + int x; + int y; + unsigned deleted:1; +}; + +// MW 08/07/01: Smudge +#ifdef SMUDGE_SUPP +struct SMUDGE{ + CString type; + int x; + int y; + unsigned deleted:1; +}; +#endif + +/* +NODE + +Data for a node +*/ +struct NODE{ + CString house; + CString type; + CString x; + CString y; +}; + + +struct RA2STRFILEHEAD +{ + DWORD dwFlag1; + DWORD dwCount1; + DWORD dwCount2; + DWORD dwUnused; + DWORD dwFlag2; +}; + +#define RA2STRFILEHEADSIZE 20 + +struct RA2STRINGENTRY +{ + RA2STRINGENTRY(){ + //memset(this, 0, sizeof(RA2STRINGENTRY)); + id=NULL; + value=NULL; + value_asc=0; + value_asc_size=0; + dwFlag = 0; + id_size = 0; + value_size = 0; + } + ~RA2STRINGENTRY(){ + if(value) delete[] value; + if(id) delete[] id; + if(value_asc) delete[] value_asc; + value=NULL; + value_size=0; + id=NULL; + id_size=0; + value_asc=0; + value_asc_size=0; + } + RA2STRINGENTRY(RA2STRINGENTRY& ref) + { + value=NULL; + value_size=0; + id=NULL; + id_size = 0; + value_asc=0; + value_asc_size=0; + + if(ref.value_size && ref.value) + { + value_size=ref.value_size; + value=new(WCHAR[value_size+1]); + memcpy(value, ref.value, value_size*sizeof(WCHAR)); + value[value_size]=0; + } + if(ref.id_size && ref.id) + { + id_size=ref.id_size; + id=new(CHAR[id_size+1]); + memcpy(id, ref.id, id_size*sizeof(CHAR)); + id[id_size]=0; + } + if(ref.value_asc_size && ref.value_asc) + { + value_asc_size=ref.value_asc_size; + value_asc=new(CHAR[value_asc_size+1]); + memcpy(value_asc, ref.value_asc, value_asc_size*sizeof(CHAR)); + value_asc[value_asc_size]=0; + } + dwFlag=ref.dwFlag; + } + RA2STRINGENTRY& operator=(RA2STRINGENTRY& ref) + { + if(value) delete[] value; + if(id) delete[] id; + value=NULL; + value_size=0; + id=NULL; + value_asc=0; + value_asc_size=0; + + if(ref.value_size) + { + value_size=ref.value_size; + value=new(WCHAR[value_size+1]); + memcpy(value, ref.value, value_size*sizeof(WCHAR)); + value[value_size]=0; + } + if(ref.id_size) + { + id_size=ref.id_size; + id=new(CHAR[id_size+1]); + memcpy(id, ref.id, id_size*sizeof(CHAR)); + id[id_size]=0; + } + if(ref.value_asc_size) + { + value_asc_size=ref.value_asc_size; + value_asc=new(CHAR[value_asc_size+1]); + memcpy(value_asc, ref.value_asc, value_asc_size*sizeof(CHAR)); + value_asc[value_asc_size]=0; + } + dwFlag=ref.dwFlag; + + return *this; + } + + DWORD dwFlag; + CHAR* id; + DWORD id_size; + DWORD value_size; + WCHAR* value; + CHAR* value_asc; + DWORD value_asc_size; +}; + + + +#endif \ No newline at end of file diff --git a/MissionEditor/TSOptions.cpp b/MissionEditor/TSOptions.cpp new file mode 100644 index 0000000..e939af7 --- /dev/null +++ b/MissionEditor/TSOptions.cpp @@ -0,0 +1,128 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// TSOptions.cpp: implementation +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "TSOptions.h" +#include "resource.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" + +extern CFinalSunApp theApp; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTSOptions + + +CTSOptions::CTSOptions(CWnd* pParent /*=NULL*/) + : CDialog(CTSOptions::IDD, pParent) + , m_PreferLocalTheaterFiles(FALSE) +{ + //{{AFX_DATA_INIT(CTSOptions) + m_LikeTS = -1; + //}}AFX_DATA_INIT +} + + +void CTSOptions::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTSOptions) + DDX_Control(pDX, IDC_LANGUAGE, m_Language); + DDX_Control(pDX, IDC_EDIT1, m_TSExe); + DDX_Radio(pDX, IDC_RULESLIKETS, m_LikeTS); + DDX_Check(pDX, IDC_PREFER_LOCAL_THEATER_FILES, m_PreferLocalTheaterFiles); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTSOptions, CDialog) + //{{AFX_MSG_MAP(CTSOptions) + ON_BN_CLICKED(IDC_CHOOSE, OnChoose) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CTSOptions + +void CTSOptions::OnChoose() +{ +#ifndef RA2_MODE + CFileDialog fd(TRUE, NULL, "Sun.exe", OFN_FILEMUSTEXIST, "Tiberian Sun EXE|Sun.exe|"); +#else + CFileDialog fd(TRUE, NULL, "ra2.exe", OFN_FILEMUSTEXIST, "Red Alert 2 EXE|ra2.exe|"); +#endif + + fd.DoModal(); + + this->GetDlgItem(IDC_EDIT1)->SetWindowText((LPCTSTR)fd.GetPathName()); + + delete fd; +} + +void CTSOptions::OnOK() +{ + this->GetDlgItem(IDC_EDIT1)->GetWindowText(m_TSEXE); + int n=m_Language.GetItemData(m_Language.GetCurSel()); + + m_LanguageName=*language.sections["Languages"].GetValue(n); + + CDialog::OnOK(); +} + +BOOL CTSOptions::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_TSExe.SetWindowText((LPCTSTR)theApp.m_Options.TSExe); + + if(theApp.m_Options.bSearchLikeTS) m_LikeTS=0; + else m_LikeTS=1; + + m_PreferLocalTheaterFiles = theApp.m_Options.bPreferLocalTheaterFiles ? TRUE : FALSE; + + UpdateData(FALSE); + + int i; + for(i=0;i. +*/ + +#if !defined(AFX_TSOPTIONS_H__AFDC93E0_651A_11D3_99E0_B9A145C86B12__INCLUDED_) +#define AFX_TSOPTIONS_H__AFDC93E0_651A_11D3_99E0_B9A145C86B12__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// TSOptions.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTSOptions + +class CTSOptions : public CDialog +{ +// Konstruktion +public: + BOOL m_PreferLocalTheaterFiles; + CString m_LanguageName; + CString m_TSEXE; + CTSOptions(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CTSOptions) + enum { IDD = IDD_TSOPTIONS }; + CComboBox m_Language; + CEdit m_TSExe; + int m_LikeTS; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CTSOptions) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CTSOptions) + afx_msg void OnChoose(); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_TSOPTIONS_H__AFDC93E0_651A_11D3_99E0_B9A145C86B12__INCLUDED_ diff --git a/MissionEditor/Tags.cpp b/MissionEditor/Tags.cpp new file mode 100644 index 0000000..36a7328 --- /dev/null +++ b/MissionEditor/Tags.cpp @@ -0,0 +1,353 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Tags.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "Tags.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" +#include "inlines.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Eigenschaftenseite CTags + +IMPLEMENT_DYNCREATE(CTags, CDialog) + +CTags::CTags() : CDialog(CTags::IDD) +{ + //{{AFX_DATA_INIT(CTags) + m_Name = _T(""); + //}}AFX_DATA_INIT +} + +CTags::~CTags() +{ +} + +void CTags::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTags) + DDX_Control(pDX, IDC_REPEAT, m_Repeat); + DDX_Control(pDX, IDC_TAG, m_Tag); + DDX_Control(pDX, IDC_TRIGGER, m_Trigger); + DDX_Text(pDX, IDC_NAME, m_Name); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTags, CDialog) + //{{AFX_MSG_MAP(CTags) + ON_CBN_SELCHANGE(IDC_TAG, OnSelchangeTag) + ON_EN_CHANGE(IDC_NAME, OnChangeName) + ON_CBN_EDITCHANGE(IDC_REPEAT, OnEditchangeRepeat) + ON_CBN_SELCHANGE(IDC_REPEAT, OnSelchangeRepeat) + ON_CBN_EDITCHANGE(IDC_TRIGGER, OnEditchangeTrigger) + ON_CBN_SELCHANGE(IDC_TRIGGER, OnSelchangeTrigger) + ON_BN_CLICKED(IDC_DELETE, OnDelete) + ON_BN_CLICKED(IDC_ADD, OnAdd) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CTags + +void CTags::UpdateDialog() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Tag.GetCurSel(); + + while(m_Tag.DeleteString(0)!=CB_ERR); + while(m_Trigger.DeleteString(0)!=CB_ERR); + + int i; + for(i=0;iGetIniFile(); + + int index=m_Tag.GetCurSel(); + if(index<0) return; + CString type; + m_Tag.GetLBText(index, type); + if(type.Find(" ")>=0) type.SetAt(type.Find(" "),0); + + CString data=ini.sections["Tags"].values[(LPCTSTR)type]; + m_Name=GetParam(data,1); + CString trigger=GetParam(data,2); + CString typ=trigger; + + trigger+=" ("; + if(ini.sections["Triggers"].values.find(typ)!=ini.sections["Triggers"].values.end()) + trigger+=GetParam(ini.sections["Triggers"].values[typ],2); + trigger+=")"; + + m_Trigger.SetWindowText(trigger); + + + m_Repeat.SetWindowText(GetParam(data,0)); + + + + UpdateData(FALSE); +} + +void CTags::OnChangeName() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(); + + CEdit& name=*(CEdit*)GetDlgItem(IDC_NAME); + int sel2=name.GetSel(); + + int index=m_Tag.GetCurSel(); + if(index<0) return; + CString type; + m_Tag.GetLBText(index, type); + if(type.Find(" ")>=0) type.SetAt(type.Find(" "),0); + + CString data=ini.sections["Tags"].values[(LPCTSTR)type]; + + CString tag, repeat; + tag=GetParam(data,2); + repeat=GetParam(data,0); + data=repeat+","+(LPCTSTR)m_Name+","+tag; + ini.sections["Tags"].values[(LPCTSTR)type]=data; + + UpdateDialog(); + name.SetSel(sel2); +} + +void CTags::OnEditchangeRepeat() +{ + CIniFile& ini=Map->GetIniFile(); + + int index=m_Tag.GetCurSel(); + if(index<0) return; + + CString str; + m_Repeat.GetWindowText(str); + + CString type; + m_Tag.GetLBText(index, type); + if(type.Find(" ")>=0) type.SetAt(type.Find(" "),0); + + CString data=ini.sections["Tags"].values[(LPCTSTR)type]; + + CString trigger, name; + trigger=GetParam(data,2); + name=GetParam(data,1); + data=(CString)(LPCTSTR)str+","+name+","+trigger; + ini.sections["Tags"].values[(LPCTSTR)type]=data; + + + UpdateDialog(); + +} + +void CTags::OnSelchangeRepeat() +{ + CIniFile& ini=Map->GetIniFile(); + + int index=m_Tag.GetCurSel(); + if(index<0) return; + + int v=m_Repeat.GetCurSel(); + CString str; + + + m_Repeat.GetLBText(v,str); + + + CString type; + m_Tag.GetLBText(index, type); + TruncSpace(type); + + TruncSpace(str); + + CString data=ini.sections["Tags"].values[(LPCTSTR)type]; + + CString trigger, name; + trigger=GetParam(data,2); + name=GetParam(data,1); + data=(CString)(LPCTSTR)str+","+name+","+trigger; + ini.sections["Tags"].values[(LPCTSTR)type]=data; + + + UpdateDialog(); +} + +void CTags::OnEditchangeTrigger() +{ + CIniFile& ini=Map->GetIniFile(); + + int index=m_Tag.GetCurSel(); + if(index<0) return; + + CString str; + m_Trigger.GetWindowText(str); + if(str.Find(" ")>=0) str.SetAt(str.Find(" "),0); + + CString type; + m_Tag.GetLBText(index, type); + if(type.Find(" ")>=0) type.SetAt(type.Find(" "),0); + + CString data=ini.sections["Tags"].values[(LPCTSTR)type]; + + CString repeat, name; + repeat=GetParam(data,0); + name=GetParam(data,1); + data=repeat+","+name+","+(LPCTSTR)str; + ini.sections["Tags"].values[(LPCTSTR)type]=data; + + + //UpdateDialog(); + +} + +void CTags::OnSelchangeTrigger() +{ + CIniFile& ini=Map->GetIniFile(); + + int index=m_Tag.GetCurSel(); + if(index<0) return; + + int v=m_Trigger.GetCurSel(); + CString str; + + + m_Trigger.GetLBText(v,str); + + if(str.Find(" ")>=0) str.SetAt(str.Find(" "),0); + + CString type; + m_Tag.GetLBText(index, type); + if(type.Find(" ")>=0) type.SetAt(type.Find(" "),0); + + CString data=ini.sections["Tags"].values[(LPCTSTR)type]; + + CString repeat, name; + repeat=GetParam(data,0); + name=GetParam(data,1); + data=repeat+","+name+","+(LPCTSTR)str; + ini.sections["Tags"].values[(LPCTSTR)type]=data; + + + //UpdateDialog(); +} + +void CTags::OnDelete() +{ + CIniFile& ini=Map->GetIniFile(); + + int index=m_Tag.GetCurSel(); + if(index<0) return; + + CString type; + m_Tag.GetLBText(index, type); + if(type.Find(" ")>=0) type.SetAt(type.Find(" "),0); + + int res=MessageBox("Are you sure to delete the selected tag? This may cause the attached trigger to don´t work anymore, if no other tag has the trigger attached.","Delete tag", MB_YESNO); + if(res==IDNO) return; + + ini.sections["Tags"].values.erase((LPCTSTR)type); + UpdateDialog(); +} + +void CTags::OnAdd() +{ + CIniFile& ini=Map->GetIniFile(); + + CString ID=GetFreeID(); + + if(ini.sections["Triggers"].values.size()<1) + { + MessageBox("Before creating tags, you need at least one trigger.","Error"); + return; + }; + + CString data; + data="0,New Tag,"; + data+=*ini.sections["Triggers"].GetValueName(0); + ini.sections["Tags"].values[ID]=data; + + + UpdateDialog(); + + int i; + for(i=0;i=0) j.SetAt(j.Find(" "),0); + + if(j==ID) + { + m_Tag.SetCurSel(i); + break; + } + } +} diff --git a/MissionEditor/Tags.h b/MissionEditor/Tags.h new file mode 100644 index 0000000..2371db6 --- /dev/null +++ b/MissionEditor/Tags.h @@ -0,0 +1,80 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_TAGS_H__103BF600_9378_11D3_B63B_8867017BB441__INCLUDED_) +#define AFX_TAGS_H__103BF600_9378_11D3_B63B_8867017BB441__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Tags.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTags + +class CTags : public CDialog +{ + DECLARE_DYNCREATE(CTags) + +// Konstruktion +public: + void UpdateDialog(); + CTags(); + ~CTags(); + +// Dialogfelddaten + //{{AFX_DATA(CTags) + enum { IDD = IDD_TAGS }; + CComboBox m_Repeat; + CComboBox m_Tag; + CComboBox m_Trigger; + CString m_Name; + //}}AFX_DATA + + +// Ăœberschreibungen + // Der Klassen-Assistent generiert virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CTags) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CTags) + afx_msg void OnSelchangeTag(); + afx_msg void OnChangeName(); + afx_msg void OnEditchangeRepeat(); + afx_msg void OnSelchangeRepeat(); + afx_msg void OnEditchangeTrigger(); + afx_msg void OnSelchangeTrigger(); + afx_msg void OnDelete(); + afx_msg void OnAdd(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_TAGS_H__103BF600_9378_11D3_B63B_8867017BB441__INCLUDED_ diff --git a/MissionEditor/TaskForce.cpp b/MissionEditor/TaskForce.cpp new file mode 100644 index 0000000..16a1a48 --- /dev/null +++ b/MissionEditor/TaskForce.cpp @@ -0,0 +1,567 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// TaskForce.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "TaskForce.h" +#include "FinalSunDlg.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" +#include "inlines.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Eigenschaftenseite CTaskForce + +IMPLEMENT_DYNCREATE(CTaskForce, CDialog) + +CTaskForce::CTaskForce() : CDialog(CTaskForce::IDD) +{ + //{{AFX_DATA_INIT(CTaskForce) + m_Group = _T(""); + m_Name = _T(""); + m_NumberOfUnits = 0; + //}}AFX_DATA_INIT +} + +CTaskForce::~CTaskForce() +{ +} + +void CTaskForce::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTaskForce) + DDX_Control(pDX, IDC_UNITTYPE, m_UnitType); + DDX_Control(pDX, IDC_UNITS, m_Units); + DDX_Control(pDX, IDC_TASKFORCES, m_TaskForces); + DDX_Text(pDX, IDC_GROUP, m_Group); + DDX_Text(pDX, IDC_NAME, m_Name); + DDX_Text(pDX, IDC_NUMBERUNITS, m_NumberOfUnits); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTaskForce, CDialog) + //{{AFX_MSG_MAP(CTaskForce) + ON_CBN_EDITCHANGE(IDC_TASKFORCES, OnEditchangeTaskforces) + ON_CBN_SELCHANGE(IDC_TASKFORCES, OnSelchangeTaskforces) + ON_LBN_SELCHANGE(IDC_UNITS, OnSelchangeUnits) + ON_BN_CLICKED(IDC_DELETEUNIT, OnDeleteunit) + ON_EN_CHANGE(IDC_NUMBERUNITS, OnChangeNumberunits) + ON_EN_CHANGE(IDC_NAME, OnChangeName) + ON_CBN_EDITCHANGE(IDC_UNITTYPE, OnEditchangeUnittype) + ON_CBN_SELCHANGE(IDC_UNITTYPE, OnSelchangeUnittype) + ON_BN_CLICKED(IDC_ADDUNIT, OnAddunit) + ON_BN_CLICKED(IDC_DELETETASKFORCE, OnDeletetaskforce) + ON_BN_CLICKED(IDC_ADDTASKFORCE, OnAddtaskforce) + ON_EN_CHANGE(IDC_GROUP, OnChangeGroup) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CTaskForce + +void CTaskForce::UpdateDialog() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_TaskForces.GetCurSel(); + int sel2=m_Units.GetCurSel(); + + while(m_TaskForces.DeleteString(0)!=CB_ERR); + while(m_Units.DeleteString(0)!=LB_ERR); + while(m_UnitType.DeleteString(0)!=CB_ERR); + + // MW 07/24/01: Clear + m_Group=""; + m_Name=""; + m_NumberOfUnits=0; + UpdateData(FALSE); + + int i; + CIniFileSection& sec=ini.sections["TaskForces"]; + for(i=0;iGetUnitName((char*)(LPCTSTR)type); + + s+=")"; + m_UnitType.AddString(s); + } + for(i=0;iGetUnitName((char*)(LPCTSTR)type); + + s+=")"; + m_UnitType.AddString(s); + } + + ss="VehicleTypes"; + for(i=0;iGetUnitName((char*)(LPCTSTR)type); + + s+=")"; + m_UnitType.AddString(s); + } + for(i=0;iGetUnitName((char*)(LPCTSTR)type); + + s+=")"; + m_UnitType.AddString(s); + } + + ss="AircraftTypes"; + for(i=0;iGetUnitName((char*)(LPCTSTR)type); + + s+=")"; + m_UnitType.AddString(s); + } + for(i=0;iGetUnitName((char*)(LPCTSTR)type); + + s+=")"; + m_UnitType.AddString(s); + } + + + if(sel<0) + { + if(m_TaskForces.SetCurSel(0)!=CB_ERR) + OnSelchangeTaskforces(); + } + else + { + if(m_TaskForces.SetCurSel(sel)!=CB_ERR) + OnSelchangeTaskforces(); + } + + + + + + if(!(sel2<0)) + { + if(m_Units.SetCurSel(sel2)!=LB_ERR) + OnSelchangeUnits(); + } + + +} + +void CTaskForce::OnEditchangeTaskforces() +{ + // TODO: Code fĂ¼r die Behandlungsroutine der Steuerelement-Benachrichtigung hier einfĂ¼gen + +} + +void CTaskForce::OnSelchangeTaskforces() +{ + CIniFile& ini=Map->GetIniFile(); + + CString tf; + tf=GetText(&m_TaskForces); + + TruncSpace(tf); + CIniFileSection & sec=ini.sections[(char*)(LPCTSTR)tf]; + m_Name=sec.values["Name"]; + m_Group=sec.values["Group"]; + + int i; + while(m_Units.DeleteString(0)!=LB_ERR); + for(i=0;iGetUnitName(type); + //s+=")"; + + m_Units.SetItemData(m_Units.AddString(s), i); + + + } + UpdateData(FALSE); + + if(m_Units.SetCurSel(0)!=LB_ERR) OnSelchangeUnits(); + + +} + +void CTaskForce::OnSelchangeUnits() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Units.GetCurSel(); + int u=m_Units.GetItemData(sel); + CString tf; + tf=GetText(&m_TaskForces); + TruncSpace(tf); + CIniFileSection & sec=ini.sections[(char*)(LPCTSTR)tf]; + + char k[50]; + itoa(u, k, 10); + CString data=sec.values[k]; + CString c=GetParam(data, 0); + + CString s; + CString type=GetParam(data,1); + /*if(ini.sections.find((char*)(LPCTSTR)type)!=ini.sections.end() && ini.sections[(char*)(LPCTSTR)type].values.find("Name")!=ini.sections[(char*)(LPCTSTR)type].values.end()) + s=ini.sections[(char*)(LPCTSTR)type].values["Name"]; + else + s=rules.sections[(char*)(LPCTSTR)type].values["Name"];*/ + s=Map->GetUnitName(type); + + m_UnitType.SetWindowText(((CString)(LPCTSTR)type + (CString)" (" + s + (CString)")")); + m_NumberOfUnits=atoi(c); + + UpdateData(FALSE); +} + +void CTaskForce::OnDeleteunit() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Units.GetCurSel(); + if(sel<0) return; + int u=m_Units.GetItemData(sel); + CString tf; + tf=GetText(&m_TaskForces); + + TruncSpace(tf); + CIniFileSection & sec=ini.sections[(char*)(LPCTSTR)tf]; + + char k[50]; + itoa(u, k, 10); + if(sec.values.size()<4) { + sec.values.erase(k); + m_Units.DeleteString(sel); + m_UnitType.SetWindowText(""); + m_NumberOfUnits=atoi("0"); + UpdateDialog(); + + return; + } + + int lastpos=sec.values.size()-3; + char l[50]; + itoa(lastpos, l, 10); + sec.values[k]=sec.values[l]; + sec.values.erase(l); + m_Units.DeleteString(sel); + + + UpdateDialog(); + return; +} + +void CTaskForce::OnChangeNumberunits() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(); + + int sel=m_Units.GetCurSel(); + if(sel<0) return; + int u=m_Units.GetItemData(sel); + CString tf; + tf=GetText(&m_TaskForces); + + TruncSpace(tf); + CIniFileSection & sec=ini.sections[(char*)(LPCTSTR)tf]; + + char k[50], n[50];; + itoa(u, k, 10); + itoa(m_NumberOfUnits, n, 10); + CString data=sec.values[k]; + CString c=GetParam(data, 1); + sec.values[k]=n+(CString)","+c; + UpdateDialog(); +} + +void CTaskForce::OnChangeName() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(); + + CEdit& n=*(CEdit*)GetDlgItem(IDC_NAME); + DWORD pos=n.GetSel(); + + if(m_TaskForces.GetCurSel()<0) return; + CString tf; + tf=GetText(&m_TaskForces); + + TruncSpace(tf); + CIniFileSection & sec=ini.sections[(char*)(LPCTSTR)tf]; + + sec.values["Name"]=m_Name; + + UpdateDialog(); + n.SetSel(pos); +} + +void CTaskForce::OnEditchangeUnittype() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Units.GetCurSel(); + if(sel<0) return; + int u=m_Units.GetItemData(sel); + CString tf; + tf=GetText(&m_TaskForces); + + TruncSpace(tf); + CIniFileSection & sec=ini.sections[(char*)(LPCTSTR)tf]; + + char k[50]; + itoa(u, k, 10); + + CString count=GetParam(sec.values[k],0); + CString type=GetText(&m_UnitType); + TruncSpace(type); + + sec.values[k]=count+","+(char*)(LPCTSTR)type; + + CString ut; + m_UnitType.GetWindowText(ut); + UpdateDialog(); + m_UnitType.SetWindowText(ut); + + +} + +void CTaskForce::OnSelchangeUnittype() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Units.GetCurSel(); + if(sel<0) return; + int u=m_Units.GetItemData(sel); + CString tf; + tf=GetText(&m_TaskForces); + + TruncSpace(tf); + CIniFileSection & sec=ini.sections[(char*)(LPCTSTR)tf]; + + char k[50]; + itoa(u, k, 10); + + CString count=GetParam(sec.values[k],0); + CString type=GetText(&m_UnitType); + + TruncSpace(type); + + sec.values[k]=count+","+(char*)(LPCTSTR)type; + + UpdateDialog(); + //m_UnitType.SetWindowText("H"); +} + +void CTaskForce::OnAddunit() +{ + CIniFile& ini=Map->GetIniFile(); + + CString tf; + if(m_TaskForces.GetCurSel()<0) return; + tf=GetText(&m_TaskForces); + + TruncSpace(tf); + CIniFileSection & sec=ini.sections[(char*)(LPCTSTR)tf]; + + char k[50]; + int c=m_Units.GetCount(); + if(c==LB_ERR) c=0; + itoa(c, k, 10); + + sec.values[k]="1"+(CString)","+*rules.sections["InfantryTypes"].GetValue(0); + + UpdateDialog(); +} + +void CTaskForce::OnDeletetaskforce() +{ + CIniFile& ini=Map->GetIniFile(); + + CString tf; + if(m_TaskForces.GetCurSel()<0) return; + tf=GetText(&m_TaskForces); + + TruncSpace(tf); + CIniFileSection & sec=ini.sections[(char*)(LPCTSTR)tf]; + + int res; + res=MessageBox("Are you sure to delete the selected task force? If you delete it, make sure to eliminate ANY references to this task force in team-types.","Delete task force",MB_YESNO); + if(res==IDNO) return; + + int v=ini.sections["TaskForces"].FindValue((char*)(LPCTSTR)tf); + if(v==-1) return; // SHOULD NEVER BE!!!! AND CANNOT BE!!! BUT MAYBE A BUG... + + ini.sections["TaskForces"].values.erase(*ini.sections["TaskForces"].GetValueName(v)); + ini.sections.erase((char*)(LPCTSTR)tf); + while(m_Units.DeleteString(0)!=LB_ERR); + //UpdateDialog(); + ((CFinalSunDlg*)theApp.m_pMainWnd)->UpdateDialogs(TRUE); +} + +CString GetFree(const char* section); +void CTaskForce::OnAddtaskforce() +{ + CIniFile& ini=Map->GetIniFile(); + + CString ID=GetFreeID(); + CString tf=GetFree("TaskForces"); + ini.sections["TaskForces"].values[tf]=ID; + + ini.sections[ID].values["Name"]="New task force"; + ini.sections[ID].values["Group"]="-1"; + + //UpdateDialog(); + + ((CFinalSunDlg*)theApp.m_pMainWnd)->UpdateDialogs(TRUE); + + int i; + for(i=0;iGetIniFile(); + + UpdateData(); + + CString tf; + if(m_TaskForces.GetCurSel()<0) return; + tf=GetText(&m_TaskForces); + + TruncSpace(tf); + CIniFileSection & sec=ini.sections[(char*)(LPCTSTR)tf]; + + sec.values["Group"]=m_Group; + + UpdateDialog(); + +} diff --git a/MissionEditor/TaskForce.h b/MissionEditor/TaskForce.h new file mode 100644 index 0000000..e84716a --- /dev/null +++ b/MissionEditor/TaskForce.h @@ -0,0 +1,86 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_TASKFORCE_H__58AF6EC0_92E3_11D3_B63B_85DE97E7FB41__INCLUDED_) +#define AFX_TASKFORCE_H__58AF6EC0_92E3_11D3_B63B_85DE97E7FB41__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// TaskForce.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTaskForce + +class CTaskForce : public CDialog +{ + DECLARE_DYNCREATE(CTaskForce) + +// Konstruktion +public: + void UpdateDialog(); + CTaskForce(); + ~CTaskForce(); + +// Dialogfelddaten + //{{AFX_DATA(CTaskForce) + enum { IDD = IDD_TASKFORCES }; + CComboBox m_UnitType; + CListBox m_Units; + CComboBox m_TaskForces; + CString m_Group; + CString m_Name; + int m_NumberOfUnits; + //}}AFX_DATA + + +// Ăœberschreibungen + // Der Klassen-Assistent generiert virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CTaskForce) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CTaskForce) + afx_msg void OnEditchangeTaskforces(); + afx_msg void OnSelchangeTaskforces(); + afx_msg void OnSelchangeUnits(); + afx_msg void OnDeleteunit(); + afx_msg void OnChangeNumberunits(); + afx_msg void OnChangeName(); + afx_msg void OnEditchangeUnittype(); + afx_msg void OnSelchangeUnittype(); + afx_msg void OnAddunit(); + afx_msg void OnDeletetaskforce(); + afx_msg void OnAddtaskforce(); + afx_msg void OnChangeGroup(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_TASKFORCE_H__58AF6EC0_92E3_11D3_B63B_85DE97E7FB41__INCLUDED_ diff --git a/MissionEditor/TeamTypes.cpp b/MissionEditor/TeamTypes.cpp new file mode 100644 index 0000000..4d9955f --- /dev/null +++ b/MissionEditor/TeamTypes.cpp @@ -0,0 +1,1288 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// TeamTypes.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "TeamTypes.h" +#include "FinalSunDlg.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" +#include "inlines.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Eigenschaftenseite CTeamTypes + +IMPLEMENT_DYNCREATE(CTeamTypes, CDialog) + +CTeamTypes::CTeamTypes() : CDialog(CTeamTypes::IDD) +{ + //{{AFX_DATA_INIT(CTeamTypes) + m_Aggressive = FALSE; + m_Annoyance = FALSE; + m_AreTeamMembersRecruitable = FALSE; + m_Autocreate = FALSE; + m_AvoidThreats = FALSE; + m_Droppod = FALSE; + m_Full = FALSE; + m_Group = _T(""); + m_GuardSlower = FALSE; + m_House = _T(""); + m_IonImmune = FALSE; + m_IsBaseDefense = FALSE; + m_Loadable = FALSE; + m_LooseRecruit = FALSE; + m_Max = _T(""); + m_Name = _T(""); + m_OnlyTargetHouseEnemy = FALSE; + m_OnTransOnly = FALSE; + m_Prebuild = FALSE; + m_Priority = _T(""); + m_Recruiter = FALSE; + m_Reinforce = FALSE; + m_Script = _T(""); + m_Suicide = FALSE; + m_TaskForce = _T(""); + m_TechLevel = _T(""); + m_TransportReturnsOnUnload = FALSE; + m_Waypoint = _T(""); + m_Whiner = FALSE; + m_VeteranLevel = _T(""); + m_Tag = _T(""); + m_TransportWaypoint = _T(""); + m_MindControlDecision = _T(""); + //}}AFX_DATA_INIT +} + +CTeamTypes::~CTeamTypes() +{ +} + +void CTeamTypes::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTeamTypes) + DDX_Control(pDX, IDC_MCD_L, m_MCD_L); + DDX_Control(pDX, IDC_TEAMTYPES, m_TeamTypes); + DDX_Check(pDX, IDC_AGGRESSIVE, m_Aggressive); + DDX_Check(pDX, IDC_ANNOYANCE, m_Annoyance); + DDX_Check(pDX, IDC_ARETEAMMEMBERSRECRUITABLE, m_AreTeamMembersRecruitable); + DDX_Check(pDX, IDC_AUTOCREATE, m_Autocreate); + DDX_Check(pDX, IDC_AVOIDTHREATS, m_AvoidThreats); + DDX_Check(pDX, IDC_DROPPOD, m_Droppod); + DDX_Check(pDX, IDC_FULL, m_Full); + DDX_CBString(pDX, IDC_GROUP, m_Group); + DDX_Check(pDX, IDC_GUARDSLOWER, m_GuardSlower); + DDX_CBString(pDX, IDC_HOUSE, m_House); + DDX_Check(pDX, IDC_IONIMMUNE, m_IonImmune); + DDX_Check(pDX, IDC_ISBASEDEFENSE, m_IsBaseDefense); + DDX_Check(pDX, IDC_LOADABLE, m_Loadable); + DDX_Check(pDX, IDC_LOOSERECRUIT, m_LooseRecruit); + DDX_Text(pDX, IDC_MAX, m_Max); + DDX_Text(pDX, IDC_NAME, m_Name); + DDX_Check(pDX, IDC_ONLYTARGETHOUSEENEMY, m_OnlyTargetHouseEnemy); + DDX_Check(pDX, IDC_ONTRANSONLY, m_OnTransOnly); + DDX_Check(pDX, IDC_PREBUILD, m_Prebuild); + DDX_Text(pDX, IDC_PRIORITY, m_Priority); + DDX_Check(pDX, IDC_RECRUITER, m_Recruiter); + DDX_Check(pDX, IDC_REINFORCE, m_Reinforce); + DDX_CBString(pDX, IDC_SCRIPT, m_Script); + DDX_Check(pDX, IDC_SUICIDE, m_Suicide); + DDX_CBString(pDX, IDC_TASKFORCE, m_TaskForce); + DDX_CBString(pDX, IDC_TECHLEVEL, m_TechLevel); + DDX_Check(pDX, IDC_TRANSPORTRETURNSONUNLOAD, m_TransportReturnsOnUnload); + DDX_CBString(pDX, IDC_WAYPOINT, m_Waypoint); + DDX_Check(pDX, IDC_WHINER, m_Whiner); + DDX_CBString(pDX, IDC_VETERANLEVEL, m_VeteranLevel); + DDX_CBString(pDX, IDC_TAG, m_Tag); + DDX_CBString(pDX, IDC_TRANSPORTWAYPOINT, m_TransportWaypoint); + DDX_CBString(pDX, IDC_MINDCONTROLDECISION, m_MindControlDecision); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTeamTypes, CDialog) + //{{AFX_MSG_MAP(CTeamTypes) + ON_CBN_SELCHANGE(IDC_TEAMTYPES, OnSelchangeTeamtypes) + ON_EN_CHANGE(IDC_NAME, OnChangeName) + ON_BN_CLICKED(IDC_DELETETEAMTYPE, OnDeleteteamtype) + ON_CBN_EDITCHANGE(IDC_VETERANLEVEL, OnEditchangeVeteranlevel) + ON_CBN_EDITCHANGE(IDC_HOUSE, OnEditchangeHouse) + ON_EN_CHANGE(IDC_PRIORITY, OnChangePriority) + ON_EN_CHANGE(IDC_MAX, OnChangeMax) + ON_CBN_EDITCHANGE(IDC_TECHLEVEL, OnEditchangeTechlevel) + ON_CBN_EDITCHANGE(IDC_GROUP, OnEditchangeGroup) + ON_CBN_EDITCHANGE(IDC_WAYPOINT, OnEditchangeWaypoint) + ON_CBN_EDITCHANGE(IDC_SCRIPT, OnEditchangeScript) + ON_CBN_EDITCHANGE(IDC_TASKFORCE, OnEditchangeTaskforce) + ON_CBN_KILLFOCUS(IDC_VETERANLEVEL, OnKillfocusVeteranlevel) + ON_CBN_KILLFOCUS(IDC_HOUSE, OnKillfocusHouse) + ON_CBN_KILLFOCUS(IDC_TECHLEVEL, OnKillfocusTechlevel) + ON_CBN_KILLFOCUS(IDC_GROUP, OnKillfocusGroup) + ON_CBN_KILLFOCUS(IDC_WAYPOINT, OnKillfocusWaypoint) + ON_CBN_KILLFOCUS(IDC_SCRIPT, OnKillfocusScript) + ON_CBN_KILLFOCUS(IDC_TASKFORCE, OnKillfocusTaskforce) + ON_WM_SHOWWINDOW() + ON_BN_CLICKED(IDC_LOADABLE, OnLoadable) + ON_BN_CLICKED(IDC_FULL, OnFull) + ON_BN_CLICKED(IDC_ANNOYANCE, OnAnnoyance) + ON_BN_CLICKED(IDC_GUARDSLOWER, OnGuardslower) + ON_BN_CLICKED(IDC_RECRUITER, OnRecruiter) + ON_BN_CLICKED(IDC_DROPPOD, OnDroppod) + ON_BN_CLICKED(IDC_WHINER, OnWhiner) + ON_BN_CLICKED(IDC_LOOSERECRUIT, OnLooserecruit) + ON_BN_CLICKED(IDC_AGGRESSIVE, OnAggressive) + ON_BN_CLICKED(IDC_SUICIDE, OnSuicide) + ON_BN_CLICKED(IDC_AUTOCREATE, OnAutocreate) + ON_BN_CLICKED(IDC_PREBUILD, OnPrebuild) + ON_BN_CLICKED(IDC_ONTRANSONLY, OnOntransonly) + ON_BN_CLICKED(IDC_REINFORCE, OnReinforce) + ON_BN_CLICKED(IDC_AVOIDTHREATS, OnAvoidthreats) + ON_BN_CLICKED(IDC_IONIMMUNE, OnIonimmune) + ON_BN_CLICKED(IDC_TRANSPORTRETURNSONUNLOAD, OnTransportreturnsonunload) + ON_BN_CLICKED(IDC_ARETEAMMEMBERSRECRUITABLE, OnAreteammembersrecruitable) + ON_BN_CLICKED(IDC_ISBASEDEFENSE, OnIsbasedefense) + ON_BN_CLICKED(IDC_ONLYTARGETHOUSEENEMY, OnOnlytargethouseenemy) + ON_BN_CLICKED(IDC_NEWTEAMTYPE, OnNewteamtype) + ON_CBN_EDITCHANGE(IDC_TAG, OnEditchangeTag) + ON_CBN_KILLFOCUS(IDC_TAG, OnKillfocusTag) + ON_CBN_EDITCHANGE(IDC_TRANSPORTWAYPOINT, OnEditchangeTransportwaypoint) + ON_CBN_KILLFOCUS(IDC_TRANSPORTWAYPOINT, OnKillfocusTransportwaypoint) + ON_CBN_EDITCHANGE(IDC_MINDCONTROLDECISION, OnEditchangeMindcontroldecision) + ON_CBN_KILLFOCUS(IDC_MINDCONTROLDECISION, OnKillfocusMindcontroldecision) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +BOOL stob(const char* s) +{ + if(_stricmp(s,"no")==NULL) + { + return FALSE; + } + return TRUE; +} + +CString btos(BOOL b) +{ + CString s="no"; + if(b==TRUE) s="yes"; + return s; +} + +int letter2number(char let){ + int reply=let-'A'; + /*if(let=='A')reply=0; + if(let=='B')reply=1; + if(let=='C')reply=2; + if(let=='D')reply=3; + if(let=='E')reply=4; + if(let=='F')reply=5; + if(let=='G')reply=6; + if(let=='H')reply=7; + if(let=='I')reply=8; + if(let=='J')reply=9; + if(let=='K')reply=10; + if(let=='L')reply=11; + if(let=='M')reply=12; + if(let=='N')reply=13; + if(let=='O')reply=14; + if(let=='P')reply=15; + if(let=='Q')reply=16; + if(let=='R')reply=17; + if(let=='S')reply=18; + if(let=='T')reply=19; + if(let=='U')reply=20; + if(let=='V')reply=21; + if(let=='W')reply=22; + if(let=='X')reply=23; + if(let=='Y')reply=24; + if(let=='Z')reply=25;*/ + return reply; + +} + +char number2letter(int let){ + int reply=let+'A'; + /*if(let==0)reply='A'; + if(let==1)reply='B'; + if(let==2)reply='C'; + if(let==3)reply='D'; + if(let==4)reply='E'; + if(let==5)reply='F'; + if(let==6)reply='G'; + if(let==7)reply='H'; + if(let==8)reply='I'; + if(let==9)reply='J'; + if(let==10)reply='K'; + if(let==11)reply='L'; + if(let==12)reply='M'; + if(let==13)reply='N'; + if(let==14)reply='O'; + if(let==15)reply='P'; + if(let==16)reply='Q'; + if(let==17)reply='R'; + if(let==18)reply='S'; + if(let==19)reply='T'; + if(let==20)reply='U'; + if(let==21)reply='V'; + if(let==22)reply='W'; + if(let==23)reply='X'; + if(let==24)reply='Y'; + if(let==25)reply='Z';*/ + + return reply; + +} + +int GetWaypoint(const char* c) +{ + if(strlen(c)==0) return -1; + int i; + int res=0; + for(i=0;iShowWindow(SW_HIDE); + m_MCD_L.ShowWindow(SW_HIDE); + } + + CIniFile& ini=Map->GetIniFile(); + + CComboBox& taskforces=*(CComboBox*)GetDlgItem(IDC_TASKFORCE); + CComboBox& scripts=*(CComboBox*)GetDlgItem(IDC_SCRIPT); + CComboBox& houses=*(CComboBox*)GetDlgItem(IDC_HOUSE); + + int sel=m_TeamTypes.GetCurSel(); + + while(m_TeamTypes.DeleteString(0)!=CB_ERR); + while(taskforces.DeleteString(0)!=CB_ERR); + while(scripts.DeleteString(0)!=CB_ERR); + + // MW 07/24/01: Clear: + m_Aggressive=0; + m_Annoyance=0; + m_AreTeamMembersRecruitable=0; + m_Autocreate=0; + m_AvoidThreats=0; + m_Droppod=0; + m_Full=0; + m_Group=""; + m_GuardSlower=0; + m_House=""; + m_IonImmune=0; + m_IsBaseDefense=0; + m_Loadable=0; + m_LooseRecruit=0; + m_Max=""; + m_Name=""; + m_OnlyTargetHouseEnemy=0; + m_OnTransOnly=0; + m_Prebuild=0; + m_Priority=""; + m_Recruiter=0; + m_Reinforce=0; + m_Script=""; + m_Suicide=0; + m_Tag=""; + m_TaskForce=""; + m_TechLevel=""; + m_TransportReturnsOnUnload=0; + m_TransportWaypoint=""; + m_VeteranLevel=""; + m_MindControlDecision=""; + + UpdateData(FALSE); + + int i; + for(i=0;iDeleteString(0)!=CB_ERR); + // houses: rules.ini + map definitions! + if(ini.sections.find("Houses")!=ini.sections.end()) + { + if(ini.sections["Houses"].values.size()==0) goto wasnohouse; + // we use the map definitions! + for(i=0;iAddString(*ini.sections["Houses"].GetValue(i)); + } + } + else + { + wasnohouse: + for(i=0;iAddString(*rules.sections["Houses"].GetValue(i)); + } + }*/ + ListHouses(*house, FALSE, TRUE, TRUE); + + CComboBox* wayp; + wayp=(CComboBox*)GetDlgItem(IDC_WAYPOINT); + + while(wayp->DeleteString(0)!=CB_ERR); + // houses: rules.ini + map definitions! + if(ini.sections.find("Waypoints")!=ini.sections.end()) + { + for(i=0;iAddString(*ini.sections["Waypoints"].GetValueName(i)); + } + } + + wayp=(CComboBox*)GetDlgItem(IDC_TRANSPORTWAYPOINT); + + while(wayp->DeleteString(0)!=CB_ERR); + // houses: rules.ini + map definitions! + wayp->SetItemData(wayp->InsertString(0,TranslateStringACP("None")),0); + + if(ini.sections.find("Waypoints")!=ini.sections.end()) + { + for(i=0;iSetItemData(wayp->AddString(*ini.sections["Waypoints"].GetValueName(i)),1); + } + } + +#ifdef TS_MODE + wayp->ShowWindow(SW_HIDE); +#endif + + m_TeamTypes.SetCurSel(0); + if(sel>=0) m_TeamTypes.SetCurSel(sel); + OnSelchangeTeamtypes(); + + +} + +void CTeamTypes::OnSelchangeTeamtypes() +{ + CIniFile& ini=Map->GetIniFile(); + + if(m_TeamTypes.GetCurSel()<0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + m_Aggressive=stob(sec.values["Aggressive"]); + m_Annoyance=stob(sec.values["Annoyance"]); + m_AreTeamMembersRecruitable=stob(sec.values["AreTeamMembersRecruitable"]); + m_Autocreate=stob(sec.values["Autocreate"]); + m_AvoidThreats=stob(sec.values["AvoidThreats"]); + m_Droppod=stob(sec.values["Droppod"]); + m_Full=stob(sec.values["Full"]); + m_Group=sec.values["Group"]; + m_GuardSlower=stob(sec.values["GuardSlower"]); + m_House=TranslateHouse(sec.values["House"], TRUE); + m_IonImmune=stob(sec.values["IonImmune"]); + m_IsBaseDefense=stob(sec.values["IsBaseDefense"]); + m_Loadable=stob(sec.values["Loadable"]); + m_LooseRecruit=stob(sec.values["LooseRecruit"]); + m_Max=sec.values["Max"]; + m_Name=sec.values["Name"]; + m_OnlyTargetHouseEnemy=stob(sec.values["OnlyTargetHouseEnemy"]); + m_OnTransOnly=stob(sec.values["OnTransOnly"]); + m_Prebuild=stob(sec.values["Prebuild"]); + m_Priority=sec.values["Priority"]; + m_Recruiter=stob(sec.values["Recruiter"]); + m_Reinforce=stob(sec.values["Reinforce"]); + m_Script=(sec.values["Script"]); + if(ini.sections.find(sec.values["Script"])!=ini.sections.end()) + m_Script+=(" ("+ini.sections[sec.values["Script"]].values["Name"]+")"); + m_Suicide=stob(sec.values["Suicide"]); + if(sec.values.find("Tag")!=sec.values.end()) + { + m_Tag=sec.values["Tag"]; + if(ini.sections["Tags"].values.find((LPCTSTR)m_Tag)!=ini.sections["Tags"].values.end()) + { + CString tag=m_Tag; + m_Tag+=" "; + m_Tag+=GetParam(ini.sections["Tags"].values[(LPCTSTR)tag], 1); + } + } + else + { + m_Tag=GetLanguageStringACP("None"); + } + m_TaskForce=(sec.values["TaskForce"]); + if(ini.sections.find(sec.values["TaskForce"])!=ini.sections.end()) + m_TaskForce+=(" ("+ini.sections[sec.values["TaskForce"]].values["Name"]+")"); + m_TechLevel=sec.values["TechLevel"]; + m_TransportReturnsOnUnload=stob(sec.values["TransportsReturnOnUnload"]); + m_VeteranLevel=sec.values["VeteranLevel"]; + + if(yuri_mode) + m_MindControlDecision=sec.values["MindControlDecision"]; + + + int w=GetWaypoint(sec.values["Waypoint"]); + char c[50]; + itoa(w,c,10); + if(w!=-1) + m_Waypoint=c; + else + m_Waypoint=""; + +#ifdef RA2_MODE + if(isTrue(sec.values["UseTransportOrigin"])) + { + int w=GetWaypoint(sec.values["TransportWaypoint"]); + char c[50]; + itoa(w,c,10); + if(w!=-1) + m_TransportWaypoint=c; + else + m_TransportWaypoint=""; + + } + else + m_TransportWaypoint=TranslateStringACP("None"); +#endif + + m_Whiner=stob(sec.values["Whiner"]); + + UpdateData(FALSE); +} + +void CTeamTypes::OnChangeName() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CEdit& n=*(CEdit*)GetDlgItem(IDC_NAME); + DWORD pos=n.GetSel(); + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["Name"]=m_Name; + + UpdateDialog(); + + n.SetSel(pos); +} + +void CTeamTypes::OnDeleteteamtype() +{ + CIniFile& ini=Map->GetIniFile(); + + if(m_TeamTypes.GetCurSel()!=-1) + { + int res=MessageBox("Are you sure that you want to delete the selected team-type? If you delete it, don´t forget to delete any reference to the team-type.","Delete team-type",MB_YESNO); + if(res==IDNO) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + + int i; + CIniFile& ini=Map->GetIniFile(); + for(i=0;iUpdateDialogs(TRUE); + //UpdateDialog(); +} + +void CTeamTypes::OnEditchangeVeteranlevel() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["VeteranLevel"]=m_VeteranLevel; +} + +void CTeamTypes::OnEditchangeHouse() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["House"]=TranslateHouse(m_House); +} + +void CTeamTypes::OnChangePriority() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["Priority"]=m_Priority; +} + +void CTeamTypes::OnChangeMax() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["Max"]=m_Max; +} + +void CTeamTypes::OnEditchangeTechlevel() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["TechLevel"]=m_TechLevel; +} + +void CTeamTypes::OnEditchangeGroup() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + //MessageBox(str); + + sec.values["Group"]=m_Group; +} + +void CTeamTypes::OnEditchangeWaypoint() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + if(strlen(m_Waypoint)==0) sec.values["Waypoint"]=""; + else + sec.values["Waypoint"]=GetWaypoint(atoi(m_Waypoint)); +} + +void CTeamTypes::OnEditchangeScript() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + CString tmp=m_Script; + TruncSpace(tmp); + sec.values["Script"]=tmp; + +} + +void CTeamTypes::OnEditchangeTaskforce() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + CString tmp=m_TaskForce; + TruncSpace(tmp); + sec.values["TaskForce"]=tmp; +} + + + +void CTeamTypes::OnKillfocusVeteranlevel() +{ + OnEditchangeVeteranlevel(); +} + +void CTeamTypes::OnKillfocusHouse() +{ + OnEditchangeHouse(); +} + +void CTeamTypes::OnKillfocusTechlevel() +{ + OnEditchangeTechlevel(); +} + +void CTeamTypes::OnKillfocusGroup() +{ + OnEditchangeGroup(); +} + +void CTeamTypes::OnKillfocusWaypoint() +{ + OnEditchangeWaypoint(); +} + +void CTeamTypes::OnKillfocusScript() +{ + OnEditchangeScript(); +} + +void CTeamTypes::OnKillfocusTaskforce() +{ + OnEditchangeTaskforce(); +} + +void CTeamTypes::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialog::OnShowWindow(bShow, nStatus); + + if(!bShow) + { + OnKillfocusGroup(); + OnKillfocusHouse(); + OnKillfocusScript(); + OnKillfocusTaskforce(); + OnKillfocusTechlevel(); + OnKillfocusVeteranlevel(); + OnKillfocusWaypoint(); + OnKillfocusTag(); +#ifdef RA2_MODE + OnKillfocusTransportwaypoint(); + if(yuri_mode) OnKillfocusMindcontroldecision(); +#endif + } +} + + + +void CTeamTypes::OnLoadable() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["Loadable"]=btos(m_Loadable); +} + +void CTeamTypes::OnFull() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["Full"]=btos(m_Full); +} + +void CTeamTypes::OnAnnoyance() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["Annoyance"]=btos(m_Annoyance); +} + +void CTeamTypes::OnGuardslower() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["GuardSlower"]=btos(m_GuardSlower); +} + +void CTeamTypes::OnRecruiter() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["Recruiter"]=btos(m_Recruiter); +} + +void CTeamTypes::OnDroppod() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["Droppod"]=btos(m_Droppod); +} + +void CTeamTypes::OnWhiner() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["Whiner"]=btos(m_Whiner); +} + +void CTeamTypes::OnLooserecruit() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["LooseRecruit"]=btos(m_LooseRecruit); +} + +void CTeamTypes::OnAggressive() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["Aggressive"]=btos(m_Aggressive); +} + +void CTeamTypes::OnSuicide() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["Suicide"]=btos(m_Suicide); +} + +void CTeamTypes::OnAutocreate() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["Autocreate"]=btos(m_Autocreate); +} + +void CTeamTypes::OnPrebuild() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["Prebuild"]=btos(m_Prebuild); +} + +void CTeamTypes::OnOntransonly() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["OnTransOnly"]=btos(m_OnTransOnly); +} + +void CTeamTypes::OnReinforce() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["Reinforce"]=btos(m_Reinforce); +} + +void CTeamTypes::OnAvoidthreats() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["AvoidThreats"]=btos(m_AvoidThreats); +} + +void CTeamTypes::OnIonimmune() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["IonImmune"]=btos(m_IonImmune); +} + +void CTeamTypes::OnTransportreturnsonunload() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["TransportsReturnOnUnload"]=btos(m_TransportReturnsOnUnload); +} + +void CTeamTypes::OnAreteammembersrecruitable() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["AreTeamMembersRecruitable"]=btos(m_AreTeamMembersRecruitable); +} + +void CTeamTypes::OnIsbasedefense() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["IsBaseDefense"]=btos(m_IsBaseDefense); +} + +void CTeamTypes::OnOnlytargethouseenemy() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + sec.values["OnlyTargetHouseEnemy"]=btos(m_OnlyTargetHouseEnemy); +} + +CString GetFree(const char* section); + +void CTeamTypes::OnNewteamtype() +{ + CIniFile& ini=Map->GetIniFile(); + + CString id=GetFreeID() ; + CString p; + p=GetFree("TeamTypes"); + + + ini.sections["TeamTypes"].values[p]=id; + CIniFileSection& s=ini.sections[id]; + s.values["Name"]="New teamtype"; + s.values["VeteranLevel"]="1"; + s.values["Loadable"]="no"; + s.values["Full"]="yes"; + s.values["Annoyance"]="no"; + s.values["GuardSlower"]="no"; + s.values["Recruiter"]="no"; + s.values["Autocreate"]="yes"; + s.values["Prebuild"]="no"; + s.values["Reinforce"]="no"; + s.values["Droppod"]="no"; + s.values["Whiner"]="no"; + s.values["LooseRecruit"]="no"; + s.values["Aggressive"]="no"; + s.values["Suicide"]="no"; + s.values["Priority"]="5"; + s.values["Max"]="5"; + s.values["TechLevel"]="0"; + s.values["Group"]="-1"; + s.values["OnTransOnly"]="no"; + s.values["AvoidThreats"]="no"; + s.values["IonImmune"]="no"; + s.values["TransportsReturnOnUnload"]="no"; + s.values["AreTeamMembersRecruitable"]="no"; + s.values["IsBaseDefense"]="no"; + s.values["OnlyTargetHouseEnemy"]="no"; + +#ifdef RA2_MODE + s.values["UseTransportOrigin"]="no"; + if(yuri_mode) s.values["MindControlDecision"]="0"; + +#endif + + + //UpdateDialog(); + ((CFinalSunDlg*)theApp.m_pMainWnd)->UpdateDialogs(TRUE); + + int i; + for(i=0;iGetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + TruncSpace(m_Tag); + + sec.values["Tag"]=m_Tag; + if(m_Tag==GetLanguageStringACP("None") || m_Tag.GetLength()==0) + { + sec.values.erase("Tag"); + } +} + +void CTeamTypes::OnKillfocusTag() +{ + OnEditchangeTag(); +} + +void CTeamTypes::OnEditchangeTransportwaypoint() +{ +#ifndef RA2_MODE + return; +#endif + + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + if(strlen(m_TransportWaypoint)==0 || isSame(m_TransportWaypoint, TranslateStringACP("None"))) + { + sec.values.erase("TransportWaypoint"); + sec.values["UseTransportOrigin"]="no"; + } + else + { + sec.values["TransportWaypoint"]=GetWaypoint(atoi(m_TransportWaypoint)); + sec.values["UseTransportOrigin"]="yes"; + } + +} + +void CTeamTypes::OnKillfocusTransportwaypoint() +{ + OnEditchangeTransportwaypoint(); +} + +void CTeamTypes::OnEditchangeMindcontroldecision() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(TRUE); + if(m_TeamTypes.GetCount()==0) return; + + CString str; + str=GetText(&m_TeamTypes); + TruncSpace(str); + CIniFileSection& sec=ini.sections[(char*)(LPCTSTR)str]; + + CString tmp=m_MindControlDecision; + TruncSpace(tmp); + sec.values["MindControlDecision"]=tmp; +} + +void CTeamTypes::OnKillfocusMindcontroldecision() +{ + OnEditchangeMindcontroldecision(); +} diff --git a/MissionEditor/TeamTypes.h b/MissionEditor/TeamTypes.h new file mode 100644 index 0000000..f697372 --- /dev/null +++ b/MissionEditor/TeamTypes.h @@ -0,0 +1,154 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +//{{AFX_INCLUDES() + +//}}AFX_INCLUDES +#if !defined(AFX_TEAMTYPES_H__EE440E20_929B_11D3_B63B_F2ECCFA7A541__INCLUDED_) +#define AFX_TEAMTYPES_H__EE440E20_929B_11D3_B63B_F2ECCFA7A541__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// TeamTypes.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTeamTypes + + +class CTeamTypes : public CDialog +{ + DECLARE_DYNCREATE(CTeamTypes) + +// Konstruktion +public: + void UpdateDialog(); + CTeamTypes(); + ~CTeamTypes(); + +// Dialogfelddaten + //{{AFX_DATA(CTeamTypes) + enum { IDD = IDD_TEAMTYPES }; + CStatic m_MCD_L; + CComboBox m_TeamTypes; + BOOL m_Aggressive; + BOOL m_Annoyance; + BOOL m_AreTeamMembersRecruitable; + BOOL m_Autocreate; + BOOL m_AvoidThreats; + BOOL m_Droppod; + BOOL m_Full; + CString m_Group; + BOOL m_GuardSlower; + CString m_House; + BOOL m_IonImmune; + BOOL m_IsBaseDefense; + BOOL m_Loadable; + BOOL m_LooseRecruit; + CString m_Max; + CString m_Name; + BOOL m_OnlyTargetHouseEnemy; + BOOL m_OnTransOnly; + BOOL m_Prebuild; + CString m_Priority; + BOOL m_Recruiter; + BOOL m_Reinforce; + CString m_Script; + BOOL m_Suicide; + CString m_TaskForce; + CString m_TechLevel; + BOOL m_TransportReturnsOnUnload; + CString m_Waypoint; + BOOL m_Whiner; + CString m_VeteranLevel; + CString m_Tag; + CString m_TransportWaypoint; + CString m_MindControlDecision; + //}}AFX_DATA + + +// Ăœberschreibungen + // Der Klassen-Assistent generiert virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CTeamTypes) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CTeamTypes) + afx_msg void OnSelchangeTeamtypes(); + afx_msg void OnChangeName(); + afx_msg void OnDeleteteamtype(); + afx_msg void OnEditchangeVeteranlevel(); + afx_msg void OnEditchangeHouse(); + afx_msg void OnChangePriority(); + afx_msg void OnChangeMax(); + afx_msg void OnEditchangeTechlevel(); + afx_msg void OnEditchangeGroup(); + afx_msg void OnEditchangeWaypoint(); + afx_msg void OnEditchangeScript(); + afx_msg void OnEditchangeTaskforce(); + afx_msg void OnKillfocusVeteranlevel(); + afx_msg void OnKillfocusHouse(); + afx_msg void OnKillfocusTechlevel(); + afx_msg void OnKillfocusGroup(); + afx_msg void OnKillfocusWaypoint(); + afx_msg void OnKillfocusScript(); + afx_msg void OnKillfocusTaskforce(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + afx_msg void OnLoadable(); + afx_msg void OnFull(); + afx_msg void OnAnnoyance(); + afx_msg void OnGuardslower(); + afx_msg void OnRecruiter(); + afx_msg void OnDroppod(); + afx_msg void OnWhiner(); + afx_msg void OnLooserecruit(); + afx_msg void OnAggressive(); + afx_msg void OnSuicide(); + afx_msg void OnAutocreate(); + afx_msg void OnPrebuild(); + afx_msg void OnOntransonly(); + afx_msg void OnReinforce(); + afx_msg void OnAvoidthreats(); + afx_msg void OnIonimmune(); + afx_msg void OnTransportreturnsonunload(); + afx_msg void OnAreteammembersrecruitable(); + afx_msg void OnIsbasedefense(); + afx_msg void OnOnlytargethouseenemy(); + afx_msg void OnNewteamtype(); + afx_msg void OnEditchangeTag(); + afx_msg void OnKillfocusTag(); + afx_msg void OnEditchangeTransportwaypoint(); + afx_msg void OnKillfocusTransportwaypoint(); + afx_msg void OnEditchangeMindcontroldecision(); + afx_msg void OnKillfocusMindcontroldecision(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_TEAMTYPES_H__EE440E20_929B_11D3_B63B_F2ECCFA7A541__INCLUDED_ diff --git a/MissionEditor/TerrainDlg.cpp b/MissionEditor/TerrainDlg.cpp new file mode 100644 index 0000000..8e557f1 --- /dev/null +++ b/MissionEditor/TerrainDlg.cpp @@ -0,0 +1,275 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// TerrainDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "TerrainDlg.h" +#include "TileSetBrowserFrame.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" +#include "inlines.h" +#include + +extern ACTIONDATA AD; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTerrainDlg + + +CTerrainDlg::CTerrainDlg(CWnd* pParent /*=NULL*/) + : CDialogBar() +{ + //{{AFX_DATA_INIT(CTerrainDlg) + //}}AFX_DATA_INIT +} + + +void CTerrainDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialogBar::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTerrainDlg) + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTerrainDlg, CDialogBar) + //{{AFX_MSG_MAP(CTerrainDlg) + ON_CBN_SELCHANGE(IDC_TILESET, OnSelchangeTileset) + ON_CBN_SELCHANGE(IDC_OVERLAY, OnSelchangeOverlay) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CTerrainDlg + +void CTerrainDlg::OnOK() +{ + // stub +} + +void CTerrainDlg::OnCancel() +{ + DestroyWindow(); +} + +BOOL CTerrainDlg::OnInitDialog() +{ + //CDialogBar::OnInitDialog(); + + return FALSE; +} + +void CTerrainDlg::PostNcDestroy() +{ + //delete this; + //CDialog::PostNcDestroy(); +} + +void CTerrainDlg::OnSelchangeTileset() +{ + //while(m_Type.DeleteString(0)!=CB_ERR); + + CString currentTileSet; + CComboBox* TileSet; + TileSet = (CComboBox*)GetDlgItem(IDC_TILESET); + TileSet->GetLBText(TileSet->GetCurSel(), currentTileSet); + + TruncSpace(currentTileSet); + + ((CTileSetBrowserFrame*)GetParentFrame())->m_view.SetTileSet(atoi(currentTileSet)); +} + + + +BOOL CTerrainDlg::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) +{ + + return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext); + + +} + +// needed to find out if pic exists +extern PICDATA* ovrlpics[0xFF][max_ovrl_img]; + +void CTerrainDlg::Update() +{ + CComboBox* TileSet; + TileSet = (CComboBox*)GetDlgItem(IDC_TILESET); + + while (TileSet->DeleteString(0) != CB_ERR); + + if (tiles) + { + int i; + int tilecount = 0; + for (i = 0;i < 10000;i++) + { + CString tset; + char c[50]; + itoa(i, c, 10); + int e; + for (e = 0;e < 4 - strlen(c);e++) + tset += "0"; + tset += c; + CString sec = "TileSet"; + sec += tset; + + if (tiles->sections.find(sec) == tiles->sections.end()) + break; + if (atoi(tiles->sections[sec].values["TilesInSet"]) == 0) + continue; + + CString string; + string = tset; + string += " ("; + string += TranslateStringACP(tiles->sections[sec].values["SetName"]); + string += ")"; + + BOOL bForced = FALSE; + BOOL bForcedNot = FALSE; + + + // force yes + CString datsec = (CString)"UseSet" + Map->GetTheater(); + auto tsetc = CString(std::to_string(atoi(tset)).c_str()); + + if (g_data.sections[datsec].FindValue(tsetc) >= 0) + bForced = TRUE; + + // force no + datsec = (CString)"IgnoreSet" + Map->GetTheater(); + if (g_data.sections[datsec].FindValue(tsetc) >= 0) + bForcedNot = TRUE; + + + if (bForced || (!bForcedNot && (*tiledata)[tilecount].bAllowToPlace && !(*tiledata)[tilecount].bMarbleMadness)) + TileSet->SetItemData(TileSet->AddString(string), i); + + tilecount += atoi(tiles->sections[sec].values["TilesInSet"]); + } + + TileSet->SetCurSel(0); + OnSelchangeTileset(); + } + + CComboBox* Overlays; + Overlays = (CComboBox*)GetDlgItem(IDC_OVERLAY); + + while (Overlays->DeleteString(0) != CB_ERR); + + int i; + + int e = 0; + for (i = 0;i < rules.sections["OverlayTypes"].values.size();i++) + { + CString id = *rules.sections["OverlayTypes"].GetValue(i); + id.TrimLeft(); + id.TrimRight(); + + if (id.GetLength() > 0) + { + + if (rules.sections.find(id) != rules.sections.end() && rules.sections[id].FindName("Name") >= 0) + { + int p; + BOOL bListIt = TRUE; + for (p = 0;p < max_ovrl_img;p++) + if (ovrlpics[i][p] != NULL && ovrlpics[i][p]->pic != NULL) + bListIt = TRUE; + +#ifdef RA2_MODE + if ((i >= 39 && i <= 60) || (i >= 180 && i <= 201) || i == 239 || i == 178 || i == 167 || i == 126 + || (i >= 122 && i <= 125)) + bListIt = FALSE; +#endif + + if (bListIt) + { + CString str; + str = TranslateStringACP(rules.sections[(*rules.sections["OverlayTypes"].GetValue(i))].values["Name"]); + Overlays->SetItemData(Overlays->AddString(str), e); + } + } + e++; + } + } +} + + +DWORD CTerrainDlg::GetTileID(DWORD dwTileSet, int iTile) +{ + int i, e; + DWORD tilecount = 0; + for (i = 0;i < 10000;i++) + { + CString tset; + char c[50]; + itoa(i, c, 10); + int e; + for (e = 0;e < 4 - strlen(c);e++) + tset += "0"; + tset += c; + CString sec = "TileSet"; + sec += tset; + + if (tiles->sections.find(sec) == tiles->sections.end()) + return 0xFFFFFFFF; + + + for (e = 0;e < atoi(tiles->sections[sec].values["TilesInSet"]);e++) + { + if (i == dwTileSet && e == iTile) + return tilecount; + tilecount++; + + } + + + } + + return tilecount; + +} + + +void CTerrainDlg::OnSelchangeOverlay() +{ + CComboBox* Overlay; + Overlay = (CComboBox*)GetDlgItem(IDC_OVERLAY); + //TileSet->GetLBText(TileSet->GetCurSel(), currentTileSet); + int n = Overlay->GetCurSel(); + + if (n < 0) return; + + int sel = Overlay->GetItemData(n); + + ((CTileSetBrowserFrame*)GetParentFrame())->m_view.SetOverlay(sel); +} diff --git a/MissionEditor/TerrainDlg.h b/MissionEditor/TerrainDlg.h new file mode 100644 index 0000000..5b2206d --- /dev/null +++ b/MissionEditor/TerrainDlg.h @@ -0,0 +1,74 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_TERRAINDLG_H__9746CA41_703A_11D4_9C87_EB588B546B1A__INCLUDED_) +#define AFX_TERRAINDLG_H__9746CA41_703A_11D4_9C87_EB588B546B1A__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// TerrainDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTerrainDlg + +class CTerrainDlg : public CDialogBar +{ +// Konstruktion +public: + DWORD GetTileID(DWORD dwTileSet, int iTile); + void Update(); + CTerrainDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CTerrainDlg) + enum { IDD = IDD_TERRAINBAR }; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CTerrainDlg) + public: + virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CTerrainDlg) + virtual void OnOK(); + virtual void OnCancel(); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeTileset(); + afx_msg void OnSelchangeOverlay(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_TERRAINDLG_H__9746CA41_703A_11D4_9C87_EB588B546B1A__INCLUDED_ diff --git a/MissionEditor/TerrainModifier.cpp b/MissionEditor/TerrainModifier.cpp new file mode 100644 index 0000000..38574b2 --- /dev/null +++ b/MissionEditor/TerrainModifier.cpp @@ -0,0 +1,47 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// TerrainModifier.cpp: Implementierung der Klasse CTerrainModifier. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "stdafx.h" +#include "TerrainModifier.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +////////////////////////////////////////////////////////////////////// +// Konstruktion/Destruktion +////////////////////////////////////////////////////////////////////// + +CTerrainModifier::CTerrainModifier() +{ + +} + +CTerrainModifier::~CTerrainModifier() +{ + +} diff --git a/MissionEditor/TerrainModifier.h b/MissionEditor/TerrainModifier.h new file mode 100644 index 0000000..ef2a9d1 --- /dev/null +++ b/MissionEditor/TerrainModifier.h @@ -0,0 +1,42 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// TerrainModifier.h: Schnittstelle fĂ¼r die Klasse CTerrainModifier. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_TERRAINMODIFIER_H__3853D322_CD37_11D4_9C87_F2DC6A2E6849__INCLUDED_) +#define AFX_TERRAINMODIFIER_H__3853D322_CD37_11D4_9C87_F2DC6A2E6849__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "MapModifier.h" + +class CTerrainModifier : public CMapModifier +{ +public: + CTerrainModifier(); + virtual ~CTerrainModifier(); + +}; + +#endif // !defined(AFX_TERRAINMODIFIER_H__3853D322_CD37_11D4_9C87_F2DC6A2E6849__INCLUDED_) diff --git a/MissionEditor/TextDrawer.cpp b/MissionEditor/TextDrawer.cpp new file mode 100644 index 0000000..c878715 --- /dev/null +++ b/MissionEditor/TextDrawer.cpp @@ -0,0 +1,186 @@ +#include "TextDrawer.h" +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "TextDrawer.h" +#include +#include "Vec2.h" +#include "MissionEditorPackLib.h" + +TextDrawer::TextDrawer(IDirectDraw4* pDirectDraw, int fontSizeInPoints, COLORREF col, COLORREF shadowCol): m_fontSizeInPoints(fontSizeInPoints), m_col(col), m_shadowCol(shadowCol) +{ + auto dc = CDC::FromHandle(::GetDC(NULL)); + auto fontSizeInPixels = -MulDiv(fontSizeInPoints, dc->GetDeviceCaps(LOGPIXELSY), 72); + m_fontSizeInPixels = fontSizeInPixels; + + CFont f; + f.CreateFont(fontSizeInPixels, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS, NONANTIALIASED_QUALITY, VARIABLE_PITCH, "COURIER NEW"); + + // Build a string that contains all required characters in order + std::string s; + for (char c = 32; c <= 126; ++c) + s.push_back(c); + + // get the extent in pixels of all characters + dc->SelectObject(f); + const auto extent = dc->GetTextExtent(s.c_str(), s.size()); + + // Now create the DirectDraw surface + DDSURFACEDESC2 desc = { 0 }; + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + desc.dwWidth = extent.cx; + desc.dwHeight = extent.cy * 2; + + m_charExtent.set(extent.cx / s.size(), extent.cy); + + auto bkcol = col == RGB(10, 10, 10) ? RGB(11, 11, 11) : RGB(10, 10, 10); + + auto pSurface = CComPtr(); + if (pDirectDraw->CreateSurface(&desc, &pSurface, nullptr) != DD_OK) + return; + + desc.dwFlags |= DDSD_PIXELFORMAT; + pSurface->GetSurfaceDesc(&desc); + if (pSurface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL) == DD_OK) + { + FSunPackLib::ColorConverter c(desc.ddpfPixelFormat); + std::int32_t backcolor = c.GetColor(bkcol); + auto bytes_per_pixel = (desc.ddpfPixelFormat.dwRGBBitCount + 7) / 8; + BYTE* const pImage = static_cast(desc.lpSurface); + for (int i=0; i < desc.dwWidth; ++i) + { + for (int e = 0; e < desc.dwHeight; ++e) + { + memcpy(&pImage[e * desc.lPitch + i * bytes_per_pixel], &backcolor, bytes_per_pixel); + } + } + pSurface->Unlock(NULL); + } + + + + + HDC hDC; + if (pSurface->GetDC(&hDC) != DD_OK) + return; + + // Draw the string with all characters onto the surface + SelectObject(hDC, f); + SetBkMode(hDC, TRANSPARENT); + if (shadowCol != CLR_INVALID) + { + SetTextColor(hDC, shadowCol); + if (!TextOutA(hDC, 0, extent.cy, s.c_str(), s.size())) + return; + } + SetTextColor(hDC, col); + if (!TextOutA(hDC, 0, 0, s.c_str(), s.size())) + return; + + if (pSurface->ReleaseDC(hDC) != DD_OK) + return; + + // set transparency key to top left + FSunPackLib::SetColorKey(pSurface, CLR_INVALID); + + // Everything fine, pass ownership of surface to m_fontSurface + m_fontSurface.Attach(pSurface.Detach()); +} + +bool TextDrawer::isValid() const +{ + return m_fontSurface != nullptr; +} + +void TextDrawer::RenderText(IDirectDrawSurface4* target, int x, int y, const std::string& text, bool centered) const +{ + if (!isValid()) + return; + + auto shadowOffset = 1 + m_fontSizeInPixels / 32; + + const int lineOffset = m_charExtent.y / 4; + ProjectedVec cur(x, y); + const int cw = m_charExtent.x; + const int ch = m_charExtent.y; + + if (centered) + { + cur -= GetExtent(text) / 2; + } + + for (const auto c: text) + { + if (c == '\n') + { + cur.set(x, cur.y + ch + lineOffset); + } + else if (c >= 32 && c <= 126) + { + auto i = c - 32; + + + if (m_shadowCol != CLR_INVALID) + { + RECT s_shadow{ i * cw, ch, i * cw + cw, ch + ch }; + + target->BltFast(cur.x + 0 * shadowOffset, cur.y + 1 * shadowOffset, m_fontSurface, &s_shadow, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT); + target->BltFast(cur.x + 0 * shadowOffset, cur.y - 1 * shadowOffset, m_fontSurface, &s_shadow, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT); + target->BltFast(cur.x + 1 * shadowOffset, cur.y + 0 * shadowOffset, m_fontSurface, &s_shadow, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT); + target->BltFast(cur.x - 1 * shadowOffset, cur.y + 0 * shadowOffset, m_fontSurface, &s_shadow, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT); + + target->BltFast(cur.x + 1 * shadowOffset, cur.y + 1 * shadowOffset, m_fontSurface, &s_shadow, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT); + target->BltFast(cur.x - 1 * shadowOffset, cur.y + 1 * shadowOffset, m_fontSurface, &s_shadow, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT); + target->BltFast(cur.x + 1 * shadowOffset, cur.y - 1 * shadowOffset, m_fontSurface, &s_shadow, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT); + target->BltFast(cur.x - 1 * shadowOffset, cur.y - 1 * shadowOffset, m_fontSurface, &s_shadow, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT); + } + + RECT s{ i * cw, 0, i * cw + cw, ch }; + target->BltFast(cur.x, cur.y, m_fontSurface, &s, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT); + cur.x += cw; + } + } +} + +ProjectedVec TextDrawer::GetExtent(const std::string& text) const +{ + ProjectedVec cur(0, 0); + const int lineOffset = m_charExtent.y / 4; + const int cw = m_charExtent.x; + const int ch = m_charExtent.y; + ProjectedVec maxpos(0, 0); + for (const auto c : text) + { + if (c == '\n') + { + cur.set(0, cur.y + ch + lineOffset); + } + else if (c >= 32 && c <= 126) + { + cur.x += cw; + maxpos.set(max(maxpos.x, cur.x), max(maxpos.y, cur.y + ch)); + } + + } + return maxpos; +} diff --git a/MissionEditor/TextDrawer.h b/MissionEditor/TextDrawer.h new file mode 100644 index 0000000..99fdc86 --- /dev/null +++ b/MissionEditor/TextDrawer.h @@ -0,0 +1,47 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include "Vec2.h" + +// Very simple class that renders text through a prepared DirectDraw surface +// Only supports ASCII chars 32 to 126, only supports monospace font +// This is for rendering waypoint ids or credits on map without using GDI during rendering, nothing fancy +class TextDrawer +{ +public: + TextDrawer(IDirectDraw4* pDirectDraw, int fontSizeInPoints, COLORREF col, COLORREF shadowCol=CLR_INVALID); + + bool isValid() const; + + void RenderText(IDirectDrawSurface4* target, int x, int y, const std::string& text, bool centered=false) const; + + ProjectedVec GetExtent(const std::string& text) const; + +private: + CComPtr m_fontSurface; + ProjectedVec m_charExtent; + int m_fontSizeInPoints; + int m_fontSizeInPixels; + COLORREF m_col; + COLORREF m_shadowCol; +}; \ No newline at end of file diff --git a/MissionEditor/TileSetBrowserFrame.cpp b/MissionEditor/TileSetBrowserFrame.cpp new file mode 100644 index 0000000..fcdf219 --- /dev/null +++ b/MissionEditor/TileSetBrowserFrame.cpp @@ -0,0 +1,115 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// TileSetBrowserFrame.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "TileSetBrowserFrame.h" +#include "resource.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CTileSetBrowserFrame + +IMPLEMENT_DYNCREATE(CTileSetBrowserFrame, CFrameWnd) + +CTileSetBrowserFrame::CTileSetBrowserFrame() +{ +} + +CTileSetBrowserFrame::~CTileSetBrowserFrame() +{ +} + + +BEGIN_MESSAGE_MAP(CTileSetBrowserFrame, CFrameWnd) + //{{AFX_MSG_MAP(CTileSetBrowserFrame) + ON_WM_SIZE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CTileSetBrowserFrame + +void CTileSetBrowserFrame::PostNcDestroy() +{ + // TODO: Speziellen Code hier einfĂ¼gen und/oder Basisklasse aufrufen + delete this; + // CFrameWnd::PostNcDestroy(); +} + +BOOL CTileSetBrowserFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) +{ + ((CDialogBar*)&m_bar)->Create(this, IDD_TERRAINBAR, CBRS_TOP, 5); + m_bar.ShowWindow(SW_SHOW); + CRect r; + GetClientRect(r); + m_view.Create(NULL, NULL, WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE, r, this, 1, NULL); + + + RecalcLayout(TRUE); + + CSize sizeTotal; + GetClientRect(&r); + sizeTotal.cx = r.right; + sizeTotal.cy = m_view.m_bottom_needed; + m_view.SetScrollSizes(MM_TEXT, sizeTotal); + + m_view.ShowWindow(SW_SHOW); + + return CFrameWnd::OnCreateClient(lpcs, pContext); +} + +void CTileSetBrowserFrame::RecalcLayout(BOOL bNotify) +{ + + RECT r; + RECT rm; + GetClientRect(&rm); + m_bar.GetClientRect(&r); + + m_view.SetWindowPos(NULL, 0, r.bottom, rm.right, rm.bottom - r.bottom, SWP_NOZORDER); + + m_view.GetClientRect(&r); + CSize sizeTotal; + sizeTotal.cx = r.right; + sizeTotal.cy = m_view.m_bottom_needed; + m_view.SetScrollSizes(MM_TEXT, sizeTotal); + + CFrameWnd::RecalcLayout(bNotify); + + +} + +void CTileSetBrowserFrame::OnSize(UINT nType, int cx, int cy) +{ + CFrameWnd::OnSize(nType, cx, cy); + + RecalcLayout(); + +} + diff --git a/MissionEditor/TileSetBrowserFrame.h b/MissionEditor/TileSetBrowserFrame.h new file mode 100644 index 0000000..7b36572 --- /dev/null +++ b/MissionEditor/TileSetBrowserFrame.h @@ -0,0 +1,76 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_TILESETBROWSERFRAME_H__1FD3DBE1_7D2F_11D4_9C87_444553540000__INCLUDED_) +#define AFX_TILESETBROWSERFRAME_H__1FD3DBE1_7D2F_11D4_9C87_444553540000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// TileSetBrowserFrame.h : Header-Datei +// + +#include "TerrainDlg.h" +#include "TileSetBrowserView.h" // HinzugefĂ¼gt von der Klassenansicht + +///////////////////////////////////////////////////////////////////////////// +// Rahmen CTileSetBrowserFrame + +class CTileSetBrowserFrame : public CFrameWnd +{ + DECLARE_DYNCREATE(CTileSetBrowserFrame) +public: + CTileSetBrowserFrame(); // Dynamische Erstellung verwendet geschĂ¼tzten Konstruktor + +// Attribute +public: + +// Operationen +public: + CTerrainDlg m_bar; + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CTileSetBrowserFrame) + public: + virtual void RecalcLayout(BOOL bNotify = TRUE); + protected: + virtual void PostNcDestroy(); + virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext); + //}}AFX_VIRTUAL + +// Implementierung +public: + CTileSetBrowserView m_view; + virtual ~CTileSetBrowserFrame(); + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CTileSetBrowserFrame) + afx_msg void OnSize(UINT nType, int cx, int cy); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_TILESETBROWSERFRAME_H__1FD3DBE1_7D2F_11D4_9C87_444553540000__INCLUDED_ diff --git a/MissionEditor/TileSetBrowserView.cpp b/MissionEditor/TileSetBrowserView.cpp new file mode 100644 index 0000000..6b794d2 --- /dev/null +++ b/MissionEditor/TileSetBrowserView.cpp @@ -0,0 +1,1086 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// TileSetBrowserView.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "TileSetBrowserView.h" +#include "FinalSunDlg.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" + +extern ACTIONDATA AD; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CTileSetBrowserView + +IMPLEMENT_DYNCREATE(CTileSetBrowserView, CScrollView) + +CTileSetBrowserView::CTileSetBrowserView() +{ + m_lpDDS = NULL; + m_bottom_needed = 1000; + m_CurrentMode = 0; +} + +CTileSetBrowserView::~CTileSetBrowserView() +{ + if (m_lpDDS) + { + int i; + for (i = 0;i < m_tilecount;i++) + { + if (m_lpDDS[i]) m_lpDDS[i]->Release(); + } + delete[] m_lpDDS; + } + m_lpDDS = NULL; + +} + + +BEGIN_MESSAGE_MAP(CTileSetBrowserView, CScrollView) + //{{AFX_MSG_MAP(CTileSetBrowserView) + ON_WM_LBUTTONDOWN() + ON_WM_VSCROLL() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Zeichnung CTileSetBrowserView + +void CTileSetBrowserView::OnInitialUpdate() +{ + CScrollView::OnInitialUpdate(); + + +} + +// for fast overlay drawing use IsoView´s overlay table +extern PICDATA* ovrlpics[0xFF][max_ovrl_img]; + + + +void CTileSetBrowserView::OnDraw(CDC* pDC) +{ + //ReleaseDC(pDC); + + + + if (((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->b_IsLoading || ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->lpds == NULL || ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->lpds->IsLost() != DD_OK) + return; + + + RECT r; + GetClientRect(&r); + + if (tiledata == NULL || (*tiledata) == NULL) + return; + + if (m_tilecount == 0) + return; + + if (m_tile_width == 0) + return; // just to make sure I never divide through 0 here... + + int max_r = r.right / m_tile_width; + + int cur_y = 0; + int cur_x = 0; + + if (m_CurrentMode == 1) + { + DWORD dwID = GetTileID(m_currentTileSet, 0); + + int i; + for (i = 0;i < m_tilecount;i++) + { + char c[50]; + itoa(i, c, 10); + + int curwidth = (*tiledata)[dwID].rect.right - (*tiledata)[dwID].rect.left; + int curheight = GetAddedHeight(dwID) + (*tiledata)[dwID].rect.bottom - (*tiledata)[dwID].rect.top; + //pDC.TextOut(cur_x, cur_y, c); + +#ifdef RA2_MODE + if ((m_currentTileSet == 80 && Map->GetTheater() == "TEMPERATE") || (m_currentTileSet == 73 && Map->GetTheater() == "SNOW") || (m_currentTileSet == 101 && Map->GetTheater() == "URBAN")) + { + if (i == 10 || i == 15) + { + dwID++; // don´t forget this here, too + continue; + } + } +#endif + + if (!m_lpDDS[i]) continue; + + RECT r; + GetClientRect(&r); + if (cur_y + curheight + (m_tile_height - curheight) / 2 >= this->GetScrollPos(SB_VERT) && cur_y <= GetScrollPos(SB_VERT) + r.bottom) + { + + HDC hDC = NULL; + m_lpDDS[i]->GetDC(&hDC); + + + HDC hTmpDC = CreateCompatibleDC(hDC); + HBITMAP hBitmap = CreateCompatibleBitmap(hDC, curwidth, curheight); + SelectObject(hTmpDC, hBitmap); + + BitBlt(hTmpDC, 0, 0, curwidth, curheight, hDC, 0, 0, SRCCOPY); + + m_lpDDS[i]->ReleaseDC(hDC); + + + BitBlt(pDC->GetSafeHdc(), cur_x + (m_tile_width - curwidth) / 2, cur_y + (m_tile_height - curheight) / 2, curwidth, curheight, hTmpDC, 0, 0, SRCCOPY); + + + DeleteDC(hTmpDC); + DeleteObject(hBitmap); + + if (AD.mode == ACTIONMODE_SETTILE && AD.type == dwID) + { + CPen p; + CBrush b; + p.CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); + b.CreateStockObject(NULL_BRUSH); + + CPen* old = pDC->SelectObject(&p); + + pDC->SetBkMode(TRANSPARENT); + pDC->SelectObject(&b); + pDC->Rectangle(cur_x + 2, cur_y + 2, cur_x + m_tile_width - 2, cur_y + m_tile_height - 2); + + pDC->SelectObject(old); + } + } + + cur_x += m_tile_width; + if (max_r == 0) max_r = 1; + if (i % max_r == max_r - 1) + { + cur_y += m_tile_height; + cur_x = 0; + } + + + + dwID++; + } + } +#ifndef NOSURFACES + else if (m_CurrentMode == 2) + { + int i; + + for (i = 0;i < max_ovrl_img;i++) + { + PICDATA* p = ovrlpics[m_currentOverlay][i]; + if (p != NULL && p->pic != NULL) + { + + DDSURFACEDESC2 desc; + memset(&desc, 0, sizeof(DDSURFACEDESC2)); + desc.dwSize = sizeof(DDSURFACEDESC2); + desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; + p->pic->GetSurfaceDesc(&desc); + + int curwidth = desc.dwWidth; + int curheight = desc.dwHeight; + + HDC hDC = NULL; + p->pic->GetDC(&hDC); + + + HDC hTmpDC = CreateCompatibleDC(hDC); + HBITMAP hBitmap = CreateCompatibleBitmap(hDC, curwidth, curheight); + SelectObject(hTmpDC, hBitmap); + + BitBlt(hTmpDC, 0, 0, curwidth, curheight, hDC, 0, 0, SRCCOPY); + + p->pic->ReleaseDC(hDC); + + + BitBlt(pDC->GetSafeHdc(), cur_x + (m_tile_width - curwidth) / 2, cur_y + (m_tile_height - curheight) / 2, curwidth, curheight, hTmpDC, 0, 0, SRCCOPY); + + + DeleteDC(hTmpDC); + DeleteObject(hBitmap); + + if (AD.mode == ACTIONMODE_PLACE && AD.data2 == m_currentOverlay && AD.data3 == i && AD.data == 33 && AD.type == 6) + { + CPen p; + CBrush b; + p.CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); + b.CreateStockObject(NULL_BRUSH); + + CPen* old = pDC->SelectObject(&p); + + pDC->SetBkMode(TRANSPARENT); + pDC->SelectObject(&b); + pDC->Rectangle(cur_x + 2, cur_y + 2, cur_x + m_tile_width - 2, cur_y + m_tile_height - 2); + + pDC->SelectObject(old); + } + + cur_x += m_tile_width; + if (max_r == 0) max_r = 1; + if (i % max_r == max_r - 1) + { + cur_y += m_tile_height; + cur_x = 0; + } + } + } + } +#else + else if (m_CurrentMode == 2) + { + int i; + + for (i = 0;i < max_ovrl_img;i++) + { + PICDATA* p = ovrlpics[m_currentOverlay][i]; + if (p != NULL && p->pic != NULL) + { + + int curwidth = p->wMaxWidth; + int curheight = p->wMaxHeight; + + BITMAPINFO biinfo; + memset(&biinfo, 0, sizeof(BITMAPINFO)); + biinfo.bmiHeader.biBitCount = 24; + biinfo.bmiHeader.biWidth = curwidth; + biinfo.bmiHeader.biHeight = curheight; + biinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + biinfo.bmiHeader.biClrUsed = 0; + biinfo.bmiHeader.biPlanes = 1; + biinfo.bmiHeader.biCompression = BI_RGB; + biinfo.bmiHeader.biClrImportant = 0; + + int pitch = curwidth * 3; + if (pitch == 0) + continue; + + if (pitch % sizeof(DWORD)) + { + pitch += sizeof(DWORD) - (curwidth * 3) % sizeof(DWORD); + } + + BYTE* colors = new(BYTE[pitch * curheight]); + memset(colors, 255, pitch * (curheight)); + + RGBTRIPLE* pal = palIso; + if (p->pal == iPalTheater) + pal = palTheater; + if (p->pal == iPalUnit) + pal = palUnit; + + int k, l; + for (k = 0;k < curheight;k++) + { + for (l = 0;l < curwidth;l++) + { + if (((BYTE*)p->pic)[l + k * curwidth]) + { + memcpy(&colors[l * 3 + (curheight - k - 1) * pitch], &pal[((BYTE*)p->pic)[l + k * curwidth]], 3); + } + } + } + + StretchDIBits(pDC->GetSafeHdc(), cur_x + (m_tile_width - curwidth) / 2, cur_y + (m_tile_height - curheight) / 2, curwidth, curheight, + 0, 0, curwidth, curheight, colors, &biinfo, DIB_RGB_COLORS, SRCCOPY); + + delete[] colors; + + if (AD.mode == ACTIONMODE_PLACE && AD.data2 == m_currentOverlay && AD.data3 == i && AD.data == 33 && AD.type == 6) + { + CPen p; + CBrush b; + p.CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); + b.CreateStockObject(NULL_BRUSH); + + CPen* old = pDC->SelectObject(&p); + + pDC->SetBkMode(TRANSPARENT); + pDC->SelectObject(&b); + pDC->Rectangle(cur_x + 2, cur_y + 2, cur_x + m_tile_width - 2, cur_y + m_tile_height - 2); + + pDC->SelectObject(old); + } + + cur_x += m_tile_width; + if (max_r == 0) + max_r = 1; + if (i % max_r == max_r - 1) + { + cur_y += m_tile_height; + cur_x = 0; + } + } + } + } +#endif + + +} + +///////////////////////////////////////////////////////////////////////////// +// Diagnose CTileSetBrowserView + +#ifdef _DEBUG +void CTileSetBrowserView::AssertValid() const +{ + CScrollView::AssertValid(); +} + +void CTileSetBrowserView::Dump(CDumpContext& dc) const +{ + CScrollView::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CTileSetBrowserView + +void CTileSetBrowserView::PostNcDestroy() +{ + // TODO: Speziellen Code hier einfĂ¼gen und/oder Basisklasse aufrufen + + // CScrollView::PostNcDestroy(); +} + +DWORD CTileSetBrowserView::GetTileID(DWORD dwTileSet, DWORD dwType) +{ + int i, e; + DWORD tilecount = 0; + for (i = 0;i < 10000;i++) + { + CString tset; + char c[50]; + itoa(i, c, 10); + int e; + for (e = 0;e < 4 - strlen(c);e++) + tset += "0"; + tset += c; + CString sec = "TileSet"; + sec += tset; + + if (tiles->sections.find(sec) == tiles->sections.end()) + return 0xFFFFFFFF; + + + for (e = 0;e < atoi(tiles->sections[sec].values["TilesInSet"]);e++) + { + if (i == dwTileSet && e == dwType) + return tilecount; + tilecount++; + + } + + + } + + return tilecount; +} + +void CTileSetBrowserView::SetTileSet(DWORD dwTileSet, BOOL bOnlyRedraw) +{ + m_currentTileSet = dwTileSet; + m_CurrentMode = 1; + + char currentTileSet[50]; + itoa(m_currentTileSet, currentTileSet, 10); + CString tset; + + int e; + for (e = 0;e < 4 - strlen(currentTileSet);e++) + tset += "0"; + + tset += currentTileSet; + + m_tile_width = 0; + m_tile_height = 0; + + int i; + int max = atoi(tiles->sections[(CString)"TileSet" + tset].values["TilesInSet"]); + DWORD dwStartID = GetTileID(dwTileSet, 0); + if ((*tiledata)[dwStartID].wTileCount && (*tiledata)[dwStartID].tiles[0].pic) + { + if (!bOnlyRedraw) + { + AD.mode = ACTIONMODE_SETTILE; + AD.type = dwStartID; + AD.data = 0; + AD.data2 = 0; + AD.z_data = 0; + + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_settingsbar.m_BrushSize = 0; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_settingsbar.UpdateData(FALSE); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_x = 1; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_y = 1; + + int i; + for (i = 0;i < g_data.sections["StdBrushSize"].values.size();i++) + { + CString n = *g_data.sections["StdBrushSize"].GetValueName(i); + if ((*tiles).sections["General"].FindName(n) >= 0) + { + int tset = atoi((*tiles).sections["General"].values[n]); + if (tset == m_currentTileSet) + { + int bs = atoi(*g_data.sections["StdBrushSize"].GetValue(i)); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_settingsbar.m_BrushSize = bs - 1; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_settingsbar.UpdateData(FALSE); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_x = bs; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_y = bs; + } + } + } + } + } + DWORD dwID; + for (i = 0;i < max;i++) + { + CString str; + char c[50]; + itoa(i, c, 10); + for (e = 0;e < 2 - strlen(c);e++) + str += "0"; + str += c; + + dwID = dwStartID + i; // just faster than always calling GetTileID() + if (dwID < *tiledata_count) + { + if ((*tiledata)[dwID].rect.right - (*tiledata)[dwID].rect.left > m_tile_width) m_tile_width = (*tiledata)[dwID].rect.right - (*tiledata)[dwID].rect.left; + if (GetAddedHeight(dwID) + (*tiledata)[dwID].rect.bottom - (*tiledata)[dwID].rect.top > m_tile_height) m_tile_height = GetAddedHeight(dwID) + (*tiledata)[dwID].rect.bottom - (*tiledata)[dwID].rect.top; + } + } + + m_tile_width += 6; + m_tile_height += 6; + + if (m_lpDDS) + { + int i; + for (i = 0;i < m_tilecount;i++) + { + if (m_lpDDS[i]) m_lpDDS[i]->Release(); + } + delete[] m_lpDDS; + } + + m_tilecount = max; + + m_lpDDS = new(LPDIRECTDRAWSURFACE4[m_tilecount]); + for (i = 0;i < m_tilecount;i++) + { + m_lpDDS[i] = RenderTile(dwStartID + i); + } + + RECT r; + GetClientRect(&r); + int max_r = r.right / m_tile_width; + if (max_r <= 0) max_r = 1; + m_bottom_needed = m_tile_height * (1 + m_tilecount / max_r); + GetParentFrame()->RecalcLayout(TRUE); + + + RedrawWindow(); + + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->SetForegroundWindow(); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->SetFocus(); + + //DrawIt(); +} + + +#ifdef NOSURFACES + +struct BlitRect +{ + short left; + short top; + short right; + short bottom; +}; + +__forceinline void BlitTerrainTSB(void* dst, int x, int y, int dleft, int dtop, int dpitch, int dright, int dbottom, SUBTILE& st)//BYTE* src, int swidth, int sheight) +{ + BYTE* src = st.pic; + unsigned short& swidth = st.wWidth; + unsigned short& sheight = st.wHeight; + + + if (src == NULL || dst == NULL) + return; + + if (x + swidth < dleft || y + sheight < dtop) + return; + if (x >= dright || y >= dbottom) + return; + + + BlitRect blrect; + BlitRect srcRect; + srcRect.left = 0; + srcRect.top = 0; + srcRect.right = swidth; + srcRect.bottom = sheight; + blrect.left = x; + if (blrect.left < 0) + { + srcRect.left = 1 - blrect.left; + blrect.left = 1; + } + blrect.top = y; + if (blrect.top < 0) + { + srcRect.top = 1 - blrect.top; + blrect.top = 1; + } + blrect.right = (x + swidth); + if (x + swidth > dright) + { + srcRect.right = dright - x;//swidth-((x+swidth)-dright); + blrect.right = dright; + } + blrect.bottom = (y + sheight); + if (y + sheight > dbottom) + { + srcRect.bottom = dbottom - y;//sheight-((y+sheight)-dbottom); + blrect.bottom = dbottom; + } + + + short i, e; + + + +#ifdef NOSURFACES_EXTRACT + int pos = 0; + if (!st.bNotExtracted) + { + for (e = srcRect.top;e < srcRect.bottom;e++) + { + short& left = st.vborder[e].left; + short& right = st.vborder[e].right; + + if (right >= left) + { + void* dest = ((BYTE*)dst + (blrect.left + left) * bpp + (blrect.top + e) * dpitch); + + memcpy(dest, &st.pic[pos], bpp * (right - left + 1)); + pos += (right - left + 1) * bpp; + } + } + } + else + +#endif + + for (e = srcRect.top;e < srcRect.bottom;e++) + { + short& left = st.vborder[e].left; + short& right = st.vborder[e].right; + + for (i = left;i <= right;i++) + { + if (i < srcRect.left || i >= srcRect.right) + { + //dest+=bpp; + } + else + { + + BYTE& val = src[i + e * swidth]; + if (val) + { + void* dest = ((BYTE*)dst + (blrect.left + i) * bpp + (blrect.top + e) * dpitch); + + memcpy(dest, &iPalIso[val], bpp); + } + } + } + + } + + +} +#endif + + +LPDIRECTDRAWSURFACE4 CTileSetBrowserView::RenderTile(DWORD dwID) +{ + if (theApp.m_Options.bMarbleMadness) + { + if ((*tiledata)[dwID].wMarbleGround != 0xFFFF) + { + dwID = (*tiledata)[dwID].wMarbleGround; + } + } + + LPDIRECTDRAWSURFACE4 lpdds = NULL; + LPDIRECTDRAW4 lpdd = ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->dd; + + DDSURFACEDESC2 ddsd; + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + int added_height = GetAddedHeight(dwID); + ddsd.dwHeight = (*tiledata)[dwID].rect.bottom - (*tiledata)[dwID].rect.top + added_height; + ddsd.dwWidth = (*tiledata)[dwID].rect.right - (*tiledata)[dwID].rect.left; + if (lpdd->CreateSurface(&ddsd, &lpdds, NULL) != DD_OK) + { + return NULL; + } + + DDBLTFX ddfx; + memset(&ddfx, 0, sizeof(DDBLTFX)); + ddfx.dwSize = sizeof(DDBLTFX); + lpdds->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &ddfx); + + + int y_added = ddsd.dwHeight - ((*tiledata)[dwID].cx * f_y / 2 + (*tiledata)[dwID].cy * f_y / 2); + + int i, e, p = 0;; + for (i = 0;i < (*tiledata)[dwID].cx;i++) + { + for (e = 0;e < (*tiledata)[dwID].cy;e++) + { + int drawx = e * f_x / 2 - i * f_x / 2 - (*tiledata)[dwID].rect.left; + int drawy = e * f_y / 2 + i * f_y / 2 - (*tiledata)[dwID].rect.top; + + drawx += (*tiledata)[dwID].tiles[p].sX; + drawy += added_height + (*tiledata)[dwID].tiles[p].sY - (*tiledata)[dwID].tiles[p].bZHeight * f_y / 2; + //drawy+=y_added; + + if ((*tiledata)[dwID].tiles[p].pic) + { + RECT dest; + dest.left = drawx; + dest.top = drawy; + dest.right = drawx + (*tiledata)[dwID].tiles[p].wWidth; + dest.bottom = drawy + (*tiledata)[dwID].tiles[p].wHeight; + DDBLTFX fx; + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize = sizeof(DDBLTFX); + +#ifndef NOSURFACES + if (lpdds->Blt(&dest, (*tiledata)[dwID].tiles[p].pic, NULL, DDBLT_KEYSRC, &fx) != DD_OK) + TRACE("Blit failed\n"); +#else + DDSURFACEDESC2 ddsd; + ZeroMemory(&ddsd, sizeof(ddsd)); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; + + lpdds->GetSurfaceDesc(&ddsd); + + lpdds->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL); + + BlitTerrainTSB(ddsd.lpSurface, drawx, drawy, 0, 0, ddsd.lPitch, ddsd.dwWidth, ddsd.dwHeight, (*tiledata)[dwID].tiles[p]); + lpdds->Unlock(NULL); +#endif + + } + + p++; + } + } + + FSunPackLib::SetColorKey(lpdds, -1); + + return lpdds; +} + +void CTileSetBrowserView::DrawIt() +{ + CPaintDC myDC(this); + + +} + +void CTileSetBrowserView::OnLButtonDown(UINT nFlags, CPoint point) +{ + RECT r; + GetClientRect(&r); + + if (m_tilecount == 0) + return; + + SCROLLINFO scrinfo; + scrinfo.cbSize = sizeof(SCROLLINFO); + scrinfo.fMask = SIF_ALL; + GetScrollInfo(SB_HORZ, &scrinfo); + point.x += scrinfo.nPos; + GetScrollInfo(SB_VERT, &scrinfo); + point.y += scrinfo.nPos; + + + int max_r = r.right / m_tile_width; + + if (max_r == 0) max_r = 1; + + int cur_y = 0; + int cur_x = 0; + + int tile_width = m_tile_width; + int tile_height = m_tile_height; + + if (m_CurrentMode == 1) + { + DWORD dwID = GetTileID(m_currentTileSet, 0); + + + + int i; + for (i = 0;i < m_tilecount;i++) + { + int curwidth = (*tiledata)[dwID].rect.right - (*tiledata)[dwID].rect.left; + int curheight = (*tiledata)[dwID].rect.bottom - (*tiledata)[dwID].rect.top; + curwidth = m_tile_width; + curheight = m_tile_height; + +#ifdef RA2_MODE + if ((m_currentTileSet == 80 && Map->GetTheater() == "TEMPERATE") || (m_currentTileSet == 73 && Map->GetTheater() == "SNOW") || (m_currentTileSet == 101 && Map->GetTheater() == "URBAN")) + { + + if (i == 10 || i == 15) + { + dwID++; // don´t forget this + continue; + } + } +#endif + + int posaddedx = (m_tile_width - curwidth) / 2; + int posaddedy = (m_tile_height - curheight) / 2; + + if (point.x > cur_x + posaddedx && point.y > cur_y + posaddedy && point.x < cur_x + tile_width - posaddedx && point.y < cur_y + tile_height - posaddedy) + { + char c[50]; + itoa(GetAddedHeight(dwID), c, 10); + OutputDebugString(c); + + int oldmode = AD.mode; + int oldid = AD.type; + + AD.mode = ACTIONMODE_SETTILE; + AD.type = dwID; + AD.data = 0; + AD.data2 = 0; + AD.data3 = 0; + AD.z_data = 0; + + if (oldid > *tiledata_count) oldid = 0; + + if (oldmode != ACTIONMODE_SETTILE || (*tiledata)[oldid].wTileSet != m_currentTileSet) + { + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_settingsbar.m_BrushSize = 0; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_settingsbar.UpdateData(FALSE); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_x = 1; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_y = 1; + + int i; + for (i = 0;i < g_data.sections["StdBrushSize"].values.size();i++) + { + CString n = *g_data.sections["StdBrushSize"].GetValueName(i); + if ((*tiles).sections["General"].FindName(n) >= 0) + { + int tset = atoi((*tiles).sections["General"].values[n]); + if (tset == m_currentTileSet) + { + int bs = atoi(*g_data.sections["StdBrushSize"].GetValue(i)); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_settingsbar.m_BrushSize = bs - 1; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_settingsbar.UpdateData(FALSE); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_x = bs; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_y = bs; + } + } + } + } + + RedrawWindow(); + return; + } + + cur_x += tile_width; + if (i % max_r == max_r - 1) + { + cur_y += tile_height; + cur_x = 0; + } + + + + dwID++; + } + } + else if (m_CurrentMode == 2) + { + int i; + for (i = 0;i < max_ovrl_img;i++) + { + PICDATA* p = ovrlpics[m_currentOverlay][i]; + if (p != NULL && p->pic != NULL) + { + int curwidth = m_tile_width; + int curheight = m_tile_height; + + int posaddedx = (m_tile_width - curwidth) / 2; + int posaddedy = (m_tile_height - curheight) / 2; + + if (point.x > cur_x + posaddedx && point.y > cur_y + posaddedy && point.x < cur_x + tile_width - posaddedx && point.y < cur_y + tile_height - posaddedy) + { + AD.mode = ACTIONMODE_PLACE; + AD.type = 6; + AD.data = 33; + AD.data2 = m_currentOverlay; + AD.data3 = i; + RedrawWindow(); + return; + } + + cur_x += tile_width; + if (i % max_r == max_r - 1) + { + cur_y += tile_height; + cur_x = 0; + } + } + + } + } + + + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->SetForegroundWindow(); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->SetFocus(); + + CScrollView::OnLButtonDown(nFlags, point); +} + +// calculates additional height added to the top of a tile if needed +int CTileSetBrowserView::GetAddedHeight(DWORD dwID) +{ + + //int i; + int cur_added = 0; + //for(i=0;i<(*tiledata)[dwID].wTileCount;i++) + { + int i, e, p = 0;; + for (i = 0;i < (*tiledata)[dwID].cx;i++) + { + for (e = 0;e < (*tiledata)[dwID].cy;e++) + { + int drawy = e * f_y / 2 + i * f_y / 2 - (*tiledata)[dwID].rect.top; + + drawy += (*tiledata)[dwID].tiles[p].sY - (*tiledata)[dwID].tiles[p].bZHeight * f_y / 2; + + if (drawy < cur_added) cur_added = drawy; + + p++; + } + } + + + } + + + + return -cur_added; +} + +void CTileSetBrowserView::SetOverlay(DWORD dwID) +{ + int k; + int need_pos = -1; + int need_width = 0; + int need_height = 0; + // m_tilecount=0; + int iovrlcount = 0; + BOOL bFound = FALSE; + for (k = 0;k < max_ovrl_img;k++) + { + PICDATA* p = ovrlpics[dwID][k]; + if (p != NULL && p->pic != NULL) + { + bFound = TRUE; + } + } + if (!bFound) + { + theApp.m_loading->LoadOverlayGraphic(*rules.sections["OverlayTypes"].GetValue(dwID), dwID); + ((CFinalSunDlg*)(theApp.m_pMainWnd))->m_view.m_isoview->UpdateOverlayPictures(); + //p=ovrlpics[dwID][k]; + } + for (k = 0;k < max_ovrl_img;k++) + { + PICDATA* p = ovrlpics[dwID][k]; + if (p == NULL || p->pic == NULL) + { + //if(!p->bTried) + { + + } + } + if (p != NULL && p->pic != NULL) + { + iovrlcount++; + } + } + for (k = 0;k < max_ovrl_img;k++) + { + PICDATA* p = ovrlpics[dwID][k]; + if (p != NULL && p->pic != NULL) + { + need_pos = k; + need_width = p->wMaxWidth; + need_height = p->wMaxHeight; + break; + } + } + + if (need_pos < 0) + return; + + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_settingsbar.m_BrushSize = 0; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_settingsbar.UpdateData(FALSE); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_x = 1; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_y = 1; + + + + m_CurrentMode = 2; + m_tile_width = 0; + m_tile_height = 0; + m_currentOverlay = dwID; + + + + m_tile_width = need_width + 6; + m_tile_height = need_height + 6; + + + + RECT r; + GetClientRect(&r); + int max_r = r.right / m_tile_width; + if (max_r <= 0) max_r = 1; + m_bottom_needed = m_tile_height * (1 + (iovrlcount) / max_r); + GetParentFrame()->RecalcLayout(TRUE); + RedrawWindow(); + + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->SetForegroundWindow(); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->SetFocus(); + +} + +#ifdef IGNORETHIS +LPDIRECTDRAWSURFACE4 CTileSetBrowserView::RenderOverlay(DWORD dwType, DWORD dwData) +{ + LPDIRECTDRAWSURFACE4 lpdds = NULL; + LPDIRECTDRAW4 lpdd = ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->dd; + + DDSURFACEDESC2 ddsd; + memset(&ddsd, 0, sizeof(DDSURFACEDESC2)); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + int added_height = GetAddedHeight(dwID); + ddsd.dwHeight =//(*tiledata)[dwID].rect.bottom-(*tiledata)[dwID].rect.top+added_height; + ddsd.dwWidth = (*tiledata)[dwID].rect.right - (*tiledata)[dwID].rect.left; + if (lpdd->CreateSurface(&ddsd, &lpdds, NULL) != DD_OK) + { + return NULL; + } + + DDBLTFX ddfx; + memset(&ddfx, 0, sizeof(DDBLTFX)); + ddfx.dwSize = sizeof(DDBLTFX); + lpdds->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &ddfx); + + + int y_added = ddsd.dwHeight - ((*tiledata)[dwID].cx * f_y / 2 + (*tiledata)[dwID].cy * f_y / 2); + + int i, e, p = 0;; + for (i = 0;i < (*tiledata)[dwID].cx;i++) + { + for (e = 0;e < (*tiledata)[dwID].cy;e++) + { + int drawx = e * f_x / 2 - i * f_x / 2 - (*tiledata)[dwID].rect.left; + int drawy = e * f_y / 2 + i * f_y / 2 - (*tiledata)[dwID].rect.top; + + drawx += (*tiledata)[dwID].tiles[p].sX; + drawy += added_height + (*tiledata)[dwID].tiles[p].sY - (*tiledata)[dwID].tiles[p].bZHeight * f_y / 2; + //drawy+=y_added; + + if ((*tiledata)[dwID].tiles[p].pic) + { + RECT dest; + dest.left = drawx; + dest.top = drawy; + dest.right = drawx + (*tiledata)[dwID].tiles[p].wWidth; + dest.bottom = drawy + (*tiledata)[dwID].tiles[p].wHeight; + DDBLTFX fx; + memset(&fx, 0, sizeof(DDBLTFX)); + fx.dwSize = sizeof(DDBLTFX); + + + DDSURFACEDESC2 ddsd; + ZeroMemory(&ddsd, sizeof(ddsd)); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; + + lpdds->GetSurfaceDesc(&ddsd); + + lpdds->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL); + + BlitTerrainTSB(ddsd.lpSurface, drawx, drawy, 0, 0, ddsd.lPitch, ddsd.dwWidth, ddsd.dwHeight, (*tiledata)[dwID].tiles[p]); + lpdds->Unlock(NULL); + + + } + + p++; + } + } + + SetSurfaceColorKey(lpdds, -1); +} + +#endif + +void CTileSetBrowserView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) +{ + //RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + CScrollView::OnVScroll(nSBCode, nPos, pScrollBar); +} diff --git a/MissionEditor/TileSetBrowserView.h b/MissionEditor/TileSetBrowserView.h new file mode 100644 index 0000000..a641223 --- /dev/null +++ b/MissionEditor/TileSetBrowserView.h @@ -0,0 +1,90 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_TILESETBROWSERVIEW_H__3DD92021_7D37_11D4_9C87_97337B61A44A__INCLUDED_) +#define AFX_TILESETBROWSERVIEW_H__3DD92021_7D37_11D4_9C87_97337B61A44A__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// TileSetBrowserView.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Ansicht CTileSetBrowserView + +class CTileSetBrowserView : public CScrollView +{ +public: + CTileSetBrowserView(); // Dynamische Erstellung verwendet geschĂ¼tzten Konstruktor + DECLARE_DYNCREATE(CTileSetBrowserView) + +// Attribute +public: + +// Operationen +public: + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CTileSetBrowserView) + protected: + virtual void OnDraw(CDC* pDC); // Ăœberschrieben zum Zeichnen dieser Ansicht + virtual void OnInitialUpdate(); // Zum ersten Mal nach der Konstruktion + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + +// Implementierung +public: + void SetOverlay(DWORD dwID); + int m_currentOverlay; + int GetAddedHeight(DWORD dwID); + int m_bottom_needed; + void DrawIt(); + LPDIRECTDRAWSURFACE4* m_lpDDS; + void SetTileSet(DWORD dwTileSet, BOOL bOnlyRedraw=FALSE); + DWORD GetTileID(DWORD dwTileSet, DWORD dwType); + int m_currentTileSet; + virtual ~CTileSetBrowserView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CTileSetBrowserView) + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +protected: + int m_CurrentMode; + LPDIRECTDRAWSURFACE4 RenderTile(DWORD dwID); + int m_tilecount; + int m_tile_height; + int m_tile_width; +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_TILESETBROWSERVIEW_H__3DD92021_7D37_11D4_9C87_97337B61A44A__INCLUDED_ diff --git a/MissionEditor/TipDlg.cpp b/MissionEditor/TipDlg.cpp new file mode 100644 index 0000000..164d433 --- /dev/null +++ b/MissionEditor/TipDlg.cpp @@ -0,0 +1,266 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "stdafx.h" +#include "resource.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" + +#include +#include +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CTipDlg dialog field + +#define MAX_BUFLEN 1000 + +static const TCHAR szSection[] = _T("Tip"); +static const TCHAR szIntFilePos[] = _T("FilePos"); +static const TCHAR szTimeStamp[] = _T("TimeStamp"); +static const TCHAR szIntStartup[] = _T("StartUp"); + +extern char AppPath[]; + +CTipDlg::CTipDlg(CWnd* pParent /*=NULL*/) + : CDialog(IDD_TIP, pParent) +{ + //{{AFX_DATA_INIT(CTipDlg) + m_bStartup = TRUE; + //}}AFX_DATA_INIT + + CIniFile optini; + CString iniFile; + + iniFile=AppPath; +#ifndef RA2_MODE + iniFile+="\\FinalSun.ini"; +#else + iniFile+="\\FinalAlert.ini"; +#endif + optini.LoadFile(iniFile); + + CWinApp* pApp = AfxGetApp(); + m_bStartup = !atoi(optini.sections[szSection].values[szIntStartup]); + UINT iFilePos = atoi(optini.sections[szSection].values[szIntFilePos]); + + // try top open the tips file + CString tipsfile=AppPath; + tipsfile+="\\tips."; + tipsfile+=language.sections[theApp.m_Options.LanguageName+"Header"].values["ExtensionName"]; + + m_pStream = fopen(tipsfile, "r"); + if (m_pStream == NULL) + { + m_strTip=GetLanguageStringACP("CG_IDS_FILE_ABSENT"); + return; + } + + //now check if the tips file is changed! (check the date the tips file was created) + struct _stat buf; + _fstat(_fileno(m_pStream), &buf); + CString strCurrentTime = ctime(&buf.st_ctime); + strCurrentTime.TrimRight(); + CString strStoredTime = optini.sections[szSection].values[szTimeStamp]; + if (strCurrentTime != strStoredTime) + { + iFilePos = 0; + optini.sections[szSection].values[szTimeStamp]=(LPCTSTR)strCurrentTime; + + } + + if (fseek(m_pStream, iFilePos, SEEK_SET) != 0) + { + AfxMessageBox(GetLanguageStringACP("CG_IDP_FILE_CORRUPT")); + } + else + { + GetNextTipString(m_strTip); + } + + optini.SaveFile(iniFile); +} + +CTipDlg::~CTipDlg() +{ + if (m_pStream != NULL) + { + + CIniFile optini; + CString iniFile; + + iniFile=AppPath; +#ifndef RA2_MODE + iniFile+="\\FinalSun.ini"; +#else + iniFile+="\\FinalAlert.ini"; +#endif + optini.LoadFile(iniFile); + + char val[50]; + itoa(ftell(m_pStream),val, 10); + optini.sections[szSection].values[szIntFilePos]=val; + optini.SaveFile(iniFile); + fclose(m_pStream); + } +} + +void CTipDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTipDlg) + DDX_Check(pDX, IDC_STARTUP, m_bStartup); + DDX_Text(pDX, IDC_TIPSTRING, m_strTip); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CTipDlg, CDialog) + //{{AFX_MSG_MAP(CTipDlg) + ON_BN_CLICKED(IDC_NEXTTIP, OnNextTip) + ON_WM_CTLCOLOR() + ON_WM_PAINT() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CTipDlg - handlers + +void CTipDlg::OnNextTip() +{ + GetNextTipString(m_strTip); + UpdateData(FALSE); +} + +void CTipDlg::GetNextTipString(CString& strNext) +{ + LPTSTR lpsz = strNext.GetBuffer(MAX_BUFLEN); + + BOOL bStop = FALSE; + while (!bStop) + { + if (_fgetts(lpsz, MAX_BUFLEN, m_pStream) == NULL) + { + if (fseek(m_pStream, 0, SEEK_SET) != 0) + AfxMessageBox(GetLanguageStringACP("CG_IDP_FILE_CORRUPT")); + } + else + { + if (*lpsz != ' ' && *lpsz != '\t' && + *lpsz != '\n' && *lpsz != ';') + { + bStop = TRUE; + } + } + } + strNext.ReleaseBuffer(); +} + +HBRUSH CTipDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) +{ + if (pWnd->GetDlgCtrlID() == IDC_TIPSTRING) + return (HBRUSH)GetStockObject(WHITE_BRUSH); + + return CDialog::OnCtlColor(pDC, pWnd, nCtlColor); +} + +void CTipDlg::OnOK() +{ + CDialog::OnOK(); + + // actualize startup + CIniFile optini; + CString iniFile; + + iniFile=AppPath; +#ifndef RA2_MODE + iniFile+="\\FinalSun.ini"; +#else + iniFile+="\\FinalAlert.ini"; +#endif + + optini.LoadFile(iniFile); + + char val[50]; + itoa(!m_bStartup,val, 10); + optini.sections[szSection].values[szIntStartup]=val; + optini.SaveFile(iniFile); +} + +BOOL CTipDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // deactivate next tip if no tips are present + if (m_pStream == NULL) + GetDlgItem(IDC_NEXTTIP)->EnableWindow(FALSE); + + SetDlgItemText(IDC_STARTUP, GetLanguageStringACP("TipDialogShowAtStartup")); + SetDlgItemText(IDC_NEXTTIP, GetLanguageStringACP("TipDialogNext")); + SetDlgItemText(IDOK, GetLanguageStringACP("TipDialogClose")); + SetWindowText(GetLanguageStringACP("TipDialogCaption")); + + return TRUE; +} + +void CTipDlg::OnPaint() +{ + CPaintDC dc(this); + + // prepare draw area for the big static rectangle + CWnd* pStatic = GetDlgItem(IDC_TOOLTIPCENTER); + CRect rect; + pStatic->GetWindowRect(&rect); + ScreenToClient(&rect); + + // draw white background + CBrush brush; + brush.CreateStockObject(WHITE_BRUSH); + dc.FillRect(rect, &brush); + + // load bitmap + CBitmap bmp; + bmp.LoadBitmap(IDB_LIGHTBULB); + BITMAP bmpInfo; + bmp.GetBitmap(&bmpInfo); + + // draw bitmap in the left corner + CDC dcTmp; + dcTmp.CreateCompatibleDC(&dc); + dcTmp.SelectObject(&bmp); + rect.bottom = bmpInfo.bmHeight + rect.top; + dc.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), + &dcTmp, 0, 0, SRCCOPY); + + // draw "Did you know" in the correct language + CString strMessage; + strMessage=GetLanguageStringACP("CG_IDS_DIDYOUKNOW"); + rect.left += bmpInfo.bmWidth; + dc.DrawText(strMessage, rect, DT_VCENTER | DT_SINGLELINE); + + +} + diff --git a/MissionEditor/TipDlg.h b/MissionEditor/TipDlg.h new file mode 100644 index 0000000..bccf4a4 --- /dev/null +++ b/MissionEditor/TipDlg.h @@ -0,0 +1,69 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(TIPDLG_H_INCLUDED_) +#define TIPDLG_H_INCLUDED_ + +// CG: Diese Datei wurde von der Komponente "Tipps und Tricks" hinzugefĂ¼gt + +///////////////////////////////////////////////////////////////////////////// +// CTipDlg Dialogfeld + +class CTipDlg : public CDialog +{ +// Konstruktion +public: + CTipDlg(CWnd* pParent = NULL); // Standard-Konstruktor + +// Dialogfelddaten + //{{AFX_DATA(CTipDlg) + enum { IDD = IDD_TIP }; + BOOL m_bStartup; + CString m_strTip; + //}}AFX_DATA + + FILE* m_pStream; + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte Ăœberschreibungen virtueller Funktionen + //{{AFX_VIRTUAL(CTipDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +public: + virtual ~CTipDlg(); + +protected: + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CTipDlg) + afx_msg void OnNextTip(); + afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + afx_msg void OnPaint(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + void GetNextTipString(CString& strNext); +}; + +#endif // !defined(TIPDLG_H_INCLUDED_) diff --git a/MissionEditor/ToolSettingsBar.cpp b/MissionEditor/ToolSettingsBar.cpp new file mode 100644 index 0000000..d6a65e3 --- /dev/null +++ b/MissionEditor/ToolSettingsBar.cpp @@ -0,0 +1,142 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// ToolSettingsBar.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "ToolSettingsBar.h" +#include "FinalSunDlg.h" +#include "mapdata.h" +#include "variables.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CToolSettingsBar + + +CToolSettingsBar::CToolSettingsBar(CWnd* pParent /*=NULL*/) + : CDialogBar() +{ + //{{AFX_DATA_INIT(CToolSettingsBar) + m_BrushSize = 0; + //}}AFX_DATA_INIT +} + + +void CToolSettingsBar::DoDataExchange(CDataExchange* pDX) +{ + CDialogBar::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CToolSettingsBar) + DDX_CBIndex(pDX, IDC_BRUSHSIZE, m_BrushSize); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CToolSettingsBar, CDialogBar) + //{{AFX_MSG_MAP(CToolSettingsBar) + ON_CBN_SELCHANGE(IDC_BRUSHSIZE, OnSelchangeBrushsize) + ON_WM_SHOWWINDOW() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CToolSettingsBar + + + +void CToolSettingsBar::OnSelchangeBrushsize() +{ + + UpdateData(TRUE); + + int bx,by; + + switch(m_BrushSize) + { + case 0: + bx=1; + by=1; + break; + case 1: + bx=2; + by=2; + break; + case 2: + bx=3; + by=3; + break; + case 3: + bx=4; + by=4; + break; + case 4: + bx=5; + by=5; + break; + case 5: + bx=10; + by=10; + break; + case 6: + bx=1; + by=2; + break; + case 7: + bx=2; + by=1; + break; + case 8: + bx=1; + by=3; + break; + case 9: + bx=3; + by=1; + break; + } + + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_x=bx; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_y=by; +} + +BOOL CToolSettingsBar::OnInitDialog() +{ + m_BrushSize=0; + UpdateData(FALSE); + + ((CComboBox*)GetDlgItem(IDC_BRUSHSIZE))->SetCurSel(0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} + +void CToolSettingsBar::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialogBar::OnShowWindow(bShow, nStatus); + + UpdateData(FALSE); +} diff --git a/MissionEditor/ToolSettingsBar.h b/MissionEditor/ToolSettingsBar.h new file mode 100644 index 0000000..81daa98 --- /dev/null +++ b/MissionEditor/ToolSettingsBar.h @@ -0,0 +1,68 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_TOOLSETTINGSBAR_H__582DFEA1_7F44_11D4_9C87_F809D2CDBE4A__INCLUDED_) +#define AFX_TOOLSETTINGSBAR_H__582DFEA1_7F44_11D4_9C87_F809D2CDBE4A__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ToolSettingsBar.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CToolSettingsBar + +class CToolSettingsBar : public CDialogBar +{ +// Konstruktion +public: + CToolSettingsBar(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CToolSettingsBar) + enum { IDD = IDD_TOOLSETTINGS }; + int m_BrushSize; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CToolSettingsBar) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CToolSettingsBar) + afx_msg void OnSelchangeBrushsize(); + virtual BOOL OnInitDialog(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_TOOLSETTINGSBAR_H__582DFEA1_7F44_11D4_9C87_F809D2CDBE4A__INCLUDED_ diff --git a/MissionEditor/Trees.cpp b/MissionEditor/Trees.cpp new file mode 100644 index 0000000..d27c7c5 --- /dev/null +++ b/MissionEditor/Trees.cpp @@ -0,0 +1,275 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Trees.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "TiberianSun Mission Editor.h" +#include "Trees.h" +#include "pos.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Eigenschaftenseite CTrees + +IMPLEMENT_DYNCREATE(CTrees, CPropertyPage) + +CTrees::CTrees() : CPropertyPage(CTrees::IDD) +{ + //{{AFX_DATA_INIT(CTrees) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Elementinitialisierung ein + //}}AFX_DATA_INIT +} + +CTrees::~CTrees() +{ +} + +void CTrees::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTrees) + DDX_Control(pDX, IDC_POS, m_Pos); + DDX_Control(pDX, IDC_TYPE, m_Type); + DDX_Control(pDX, IDC_TREELIST, m_TreeList); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTrees, CPropertyPage) + //{{AFX_MSG_MAP(CTrees) + ON_LBN_SELCHANGE(IDC_TREELIST, OnSelchangeTreelist) + ON_CBN_EDITCHANGE(IDC_TYPE, OnEditchangeType) + ON_CBN_KILLFOCUS(IDC_TYPE, OnKillfocusType) + ON_WM_KILLFOCUS() + ON_WM_SHOWWINDOW() + ON_BN_CLICKED(IDC_DELETE, OnDelete) + ON_CBN_SELCHANGE(IDC_TYPE, OnEditchangeType) + ON_BN_CLICKED(IDC_NEW, OnNew) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CTrees + +void CTrees::UpdateDialog() +{ + m_TreeList.SetRedraw(FALSE); + + // first clear the list + while(m_TreeList.DeleteString(0)!=LB_ERR); + + // okay add all trees + + int i; + CIniFileSection& sec=ini.sections["Terrain"]; + + + for(i=0;idata(); + + int pos=atoi(str); + + str+=(CString)" "+ sec.GetValue(i)->data(); + int x,y,z; + GetXYPos((char*)sec.GetValueName(i)->data(), &x, &y); + char c[50]; + itoa(x, c, 10); + str+=" ("; + str+=c; + str+="/"; + itoa(y, c, 10); + str+=c; + + z=GetPos(x,y,0); + + itoa(z, c, 10); + str+="/"; + str+=c; + str+=")"; + + m_TreeList.InsertString(-1, str); + + } + + m_TreeList.SetRedraw(TRUE); + m_TreeList.RedrawWindow(); +} + +BOOL CTrees::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + // TODO: Zusätzliche Initialisierung hier einfĂ¼gen + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} + +void CTrees::OnSelchangeTreelist() +{ + int i=m_TreeList.GetCurSel(); + + CString str; + m_TreeList.GetText(i, str); + + str.SetAt(str.Find(" ", 0),0); + + m_Type.SetWindowText( ini.sections["Terrain"].values[ (char*)(LPCTSTR)str ].data() ); + + string pos; + int x,y,z; + GetXYPos((char*)ini.sections["Terrain"].GetValueName(i)->data(), &x, &y); + + char c[50]; + itoa(x, c, 10); + pos=c; + pos+="/"; + itoa(y, c, 10); + pos+=c; + pos+="/"; + itoa(z, c, 10); + pos+=c; + + m_Pos.SetWindowText(pos.data()); + +} + +void CTrees::OnEditchangeType() +{ + + + +} + +void CTrees::OnKillfocusType() +{ + int i=m_TreeList.GetCurSel(); + + if(i==-1) return; + + m_TreeList.SetRedraw(FALSE); + + CString str; + m_TreeList.GetText(i, str); + + str.SetAt(str.Find(" ", 0),0); + + + CString type; + m_Type.GetWindowText(type); + + if(ini.sections["Terrain"].values[(char*)(LPCTSTR)str]==(char*)(LPCTSTR)type) return; + + ini.sections["Terrain"].values[(char*)(LPCTSTR)str]=type; + + UpdateDialog(); + + m_TreeList.SetCurSel(i); + CTrees::OnSelchangeTreelist(); + + /*String str_=str; + //str_=ini.sections["Terrain"].GetValueName(i)->data(); + + //int pos=atoi(str_); + + str_+=(CString)" "+ ini.sections["Terrain"].values[(char*)(LPCTSTR)str].data(); + int x,y; + GetXYPos(atoi(str), x, y); + char c[50]; + itoa(x, c, 10); + str_+=" ("; + str_+=c; + str_+="/"; + itoa(y, c, 10); + str_+=c; + str_+=")"; + + m_TreeList.DeleteString(i); + m_TreeList.InsertString(i, str_);*/ + + + + m_TreeList.SetRedraw(TRUE); + m_TreeList.RedrawWindow(); + m_TreeList.SetCurSel(i); +} + +void CTrees::OnKillFocus(CWnd* pNewWnd) +{ + CPropertyPage::OnKillFocus(pNewWnd); + + + + +} + +void CTrees::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CPropertyPage::OnShowWindow(bShow, nStatus); + + OnKillfocusType(); +} + +void CTrees::OnDelete() +{ + int pos=m_TreeList.GetCurSel(); + if(pos==-1) return; + + CString cutree; + //m_TreeList.GetText(pos, cutree); + cutree=ini.sections["Terrain"].GetValueName(pos)->data(); + + ini.sections["Terrain"].values.erase((string)(char*)(LPCTSTR) cutree); + + //m_TreeList.SetRedraw(FALSE); + UpdateDialog(); + m_TreeList.SetCurSel(pos); + //m_TreeList.SetRedraw(TRUE); + + +} + +void CTrees::OnNew() +{ + int pos=m_TreeList.GetCurSel(); + + CPos p; + if(p.DoModal()==IDCANCEL) return; + + int h=GetPos(atoi(p.m_x), atoi(p.m_y), 0); + + char k[50]; + itoa(h, k, 10); + + ini.sections["Terrain"].values[k]="TREE01"; + + UpdateDialog(); + m_TreeList.SetCurSel(pos); + +} diff --git a/MissionEditor/Trees.h b/MissionEditor/Trees.h new file mode 100644 index 0000000..2c35dad --- /dev/null +++ b/MissionEditor/Trees.h @@ -0,0 +1,79 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_TREES_H__8ACDE600_72AB_11D3_99E1_95E76FDD1C05__INCLUDED_) +#define AFX_TREES_H__8ACDE600_72AB_11D3_99E1_95E76FDD1C05__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Trees.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTrees + +class CTrees : public CPropertyPage +{ + DECLARE_DYNCREATE(CTrees) + +// Konstruktion +public: + void UpdateDialog(); + CTrees(); + ~CTrees(); + +// Dialogfelddaten + //{{AFX_DATA(CTrees) + enum { IDD = IDD_TREES }; + CEdit m_Pos; + CComboBox m_Type; + CListBox m_TreeList; + //}}AFX_DATA + + +// Ăœberschreibungen + // Der Klassen-Assistent generiert virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CTrees) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CTrees) + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeTreelist(); + afx_msg void OnEditchangeType(); + afx_msg void OnKillfocusType(); + afx_msg void OnKillFocus(CWnd* pNewWnd); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + afx_msg void OnDelete(); + afx_msg void OnNew(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_TREES_H__8ACDE600_72AB_11D3_99E1_95E76FDD1C05__INCLUDED_ diff --git a/MissionEditor/TriggerActionsDlg.cpp b/MissionEditor/TriggerActionsDlg.cpp new file mode 100644 index 0000000..c1f2e20 --- /dev/null +++ b/MissionEditor/TriggerActionsDlg.cpp @@ -0,0 +1,567 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// TriggerActionsDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "TriggerActionsDlg.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" +#include "inlines.h" + +CString GetWaypoint(int n); +int GetWaypoint(const char* c); + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +BOOL IsWaypointFormat(CString s) +{ + if(s.GetLength()==0) return TRUE; + + if(s[0]>='A' && s[0]<='Z') + return TRUE; + + return FALSE; + +} + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTriggerActionsDlg + + +CTriggerActionsDlg::CTriggerActionsDlg(CWnd* pParent /*=NULL*/) + : CDialog(CTriggerActionsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CTriggerActionsDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Elementinitialisierung ein + //}}AFX_DATA_INIT +} + + +void CTriggerActionsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTriggerActionsDlg) + DDX_Control(pDX, IDC_PARAMVALUE, m_ParamValue); + DDX_Control(pDX, IDC_PARAMETER, m_Parameter); + DDX_Control(pDX, IDC_ACTIONTYPE, m_ActionType); + DDX_Control(pDX, IDC_ACTIONDESCRIPTION, m_ActionDescription); + DDX_Control(pDX, IDC_ACTION, m_Action); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTriggerActionsDlg, CDialog) + //{{AFX_MSG_MAP(CTriggerActionsDlg) + ON_CBN_SELCHANGE(IDC_ACTION, OnSelchangeAction) + ON_CBN_EDITCHANGE(IDC_ACTIONTYPE, OnEditchangeActiontype) + ON_LBN_SELCHANGE(IDC_PARAMETER, OnSelchangeParameter) + ON_CBN_EDITCHANGE(IDC_PARAMVALUE, OnEditchangeParamvalue) + ON_BN_CLICKED(IDC_NEWACTION, OnNewaction) + ON_BN_CLICKED(IDC_DELETEACTION, OnDeleteaction) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CTriggerActionsDlg + +void CTriggerActionsDlg::OnSelchangeAction() +{ + CIniFile& ini=Map->GetIniFile(); + + if(m_currentTrigger.GetLength()==0) return; + int selev=m_Action.GetCurSel(); + if(selev<0) return; + int curev=m_Action.GetItemData(selev); + + + int i; + + CString ActionData; + ActionData=ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger]; + + int startpos=1+curev*8; + CString ActionType=GetParam(ActionData,startpos); + m_ActionType.SetWindowText(ActionType); + for(i=0;iGetIniFile(); + + if(m_currentTrigger.GetLength()==0) return; + int selev=m_Action.GetCurSel(); + if(selev<0) return; + int curev=m_Action.GetItemData(selev); + + CString e1,e2; + while(m_Parameter.DeleteString(0)!=CB_ERR); + + + CString eventtype,eventdata; + m_ActionType.GetWindowText(eventtype); + TruncSpace(eventtype); + + if(eventtype.GetLength()==0) + { + eventtype="0"; + m_ActionType.SetWindowText(eventtype); + } + + + CString acsec="Actions"; +#ifdef RA2_MODE + acsec="ActionsRA2"; +#endif + + + int pos=1+8*curev; + + ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger]=SetParam(ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger], pos, (LPCTSTR)eventtype); + + if(g_data.sections[acsec].FindName(eventtype)<0) return; + + eventdata=g_data.sections[acsec].values[eventtype]; + +#ifdef RA2_MODE + if(g_data.sections["ActionsRA2"].FindName(eventtype)>=0) + eventdata=g_data.sections["ActionsRA2"].values[eventtype]; +#endif + + CString desc=GetParam(eventdata,10); + desc.Replace("%1",","); + m_ActionDescription.SetWindowText(desc); + + CString ptype[6]; + ptype[0]=GetParam(eventdata,1); + ptype[1]=GetParam(eventdata,2); + ptype[2]=GetParam(eventdata,3); + ptype[3]=GetParam(eventdata,4); + ptype[4]=GetParam(eventdata,5); + ptype[5]=GetParam(eventdata,6); + + int pListType[6]; + memset(pListType, 0, 6*sizeof(int)); + + if(atoi(ptype[0])>=0) pListType[0]=atoi(GetParam(g_data.sections["ParamTypes"].values[ptype[0]], 1)); + if(atoi(ptype[1])>=0) pListType[1]=atoi(GetParam(g_data.sections["ParamTypes"].values[ptype[1]], 1)); + if(atoi(ptype[2])>=0) pListType[2]=atoi(GetParam(g_data.sections["ParamTypes"].values[ptype[2]], 1)); + if(atoi(ptype[3])>=0) pListType[3]=atoi(GetParam(g_data.sections["ParamTypes"].values[ptype[3]], 1)); + if(atoi(ptype[4])>=0) pListType[4]=atoi(GetParam(g_data.sections["ParamTypes"].values[ptype[4]], 1)); + if(atoi(ptype[5])>=0) pListType[5]=atoi(GetParam(g_data.sections["ParamTypes"].values[ptype[5]], 1)); + + int i; + for(i=0;i<6;i++) + { + + if(atoi(ptype[i])>0) + { + CString paramname=GetParam(g_data.sections["ParamTypes"].values[ptype[i]], 0); + + m_Parameter.SetItemData(m_Parameter.AddString(paramname), i); + } + else if(atoi(ptype[i])<0) + { + char c[50]; + itoa(-atoi(ptype[i]),c,10); + ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger]=SetParam(ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger], pos+i+1,c ); + } + else + { + ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger]=SetParam(ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger], pos+i+1, "0"); + } + + } + + // MW fix for waypoint/number issue + CString code; + BOOL bNoWP=FALSE; + code=GetParam(ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger], pos+1); + if(g_data.sections["DontSaveAsWP"].FindValue(code)>=0) bNoWP=TRUE; + + // conversion below: + if(IsWaypointFormat(GetParam(ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger], pos+1+6)) && bNoWP) + { + int number=GetWaypoint(GetParam(ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger], pos+1+6)); + char c[50]; + itoa(number, c, 10); + ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger]=SetParam(ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger], pos+1+6, c); + } + else if(!IsWaypointFormat(GetParam(ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger], pos+1+6)) && !bNoWP) + { + int wp=atoi(GetParam(ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger], pos+1+6)); + CString s=GetWaypoint(wp); + ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger]=SetParam(ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger], pos+1+6, s); + + } + + + if(atoi(GetParam(eventdata, 7))==1) + { + if(bNoWP) + m_Parameter.SetItemData(m_Parameter.AddString(TranslateStringACP("Number")), -1); + else + m_Parameter.SetItemData(m_Parameter.AddString(TranslateStringACP("Waypoint")), -1); + } + + m_ParamValue.SetWindowText(""); + if(m_Parameter.GetCount()>0) { + m_Parameter.SetCurSel(0); + OnSelchangeParameter(); + } +} + +void CTriggerActionsDlg::OnSelchangeParameter() +{ + CIniFile& ini=Map->GetIniFile(); + + if(m_currentTrigger.GetLength()==0) return; + int selev=m_Action.GetCurSel(); + if(selev<0) return; + int curev=m_Action.GetItemData(selev); + + int curselparam=m_Parameter.GetCurSel(); + if(curselparam<0) + { + m_ParamValue.SetWindowText(""); + return; + } + + + + int curparam=m_Parameter.GetItemData(curselparam); + + + + CString ActionData; + ActionData=ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger]; + + + int startpos=1+curev*8; + + CString code; + BOOL bNoWP=FALSE; + code=GetParam(ActionData, startpos+1); + if(g_data.sections["DontSaveAsWP"].FindValue(code)>=0) bNoWP=TRUE; + + if(curparam>=0 && curparam<6) + { + CString ParamType=GetParam(g_data.sections["Actions"].values[GetParam(ActionData,startpos)],1+curparam); +#ifdef RA2_MODE + if(g_data.sections["ActionsRA2"].FindName(GetParam(ActionData, startpos))>=0) + { + ParamType=GetParam(g_data.sections["ActionsRA2"].values[GetParam(ActionData,startpos)],1+curparam); + } +#endif + if(atoi(ParamType)<0) + { + } + else + { + CString ListType=GetParam(g_data.sections["ParamTypes"].values[ParamType],1); + HandleParamList(m_ParamValue, atoi(ListType)); + m_ParamValue.SetWindowText(GetParam(ActionData,startpos+1+curparam)); + + int i; + BOOL bFound=FALSE; + for(i=0;iGetIniFile(); + + if(m_currentTrigger.GetLength()==0) return; + int selev=m_Action.GetCurSel(); + if(selev<0) return; + int curev=m_Action.GetItemData(selev); + + int curselparam=m_Parameter.GetCurSel(); + if(curselparam<0) + { + m_ParamValue.SetWindowText(""); + return; + } + + int curparam=m_Parameter.GetItemData(curselparam); + + CString ActionData; + ActionData=ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger]; + + int startpos=1+curev*8; + + + CString code; + BOOL bNoWP=FALSE; + code=GetParam(ActionData, startpos+1); + if(g_data.sections["DontSaveAsWP"].FindValue(code)>=0) bNoWP=TRUE; + + CString newVal; + m_ParamValue.GetWindowText(newVal); + TruncSpace(newVal); + newVal.TrimLeft(); + + if(newVal.Find(",",0)>=0) newVal.SetAt(newVal.Find(",",0), 0); + + if(curparam>=0) + { + ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger]=SetParam(ActionData, startpos+1+curparam, newVal); + } + else if(curparam==-1) // waypoint FIX MW: OR NUMBER!!! + { + int pos=1+8*curev+7; + + + CString waypoint=newVal; + + if(!bNoWP) waypoint=GetWaypoint(atoi(newVal)); + + ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger]=SetParam(ini.sections["Actions"].values[(LPCTSTR)m_currentTrigger], pos, (LPCTSTR)waypoint); + } + +} + +void CTriggerActionsDlg::OnNewaction() +{ + CIniFile& ini=Map->GetIniFile(); + + if(m_currentTrigger.GetLength()==0) return; + + + CIniFileSection& sec=ini.sections["Actions"]; + + int cval=atoi(GetParam(sec.values[(LPCTSTR)m_currentTrigger],0)); + cval++; + char c[50]; + itoa(cval,c,10); + + sec.values[(LPCTSTR)m_currentTrigger]=SetParam(sec.values[(LPCTSTR)m_currentTrigger],0,c); + sec.values[(LPCTSTR)m_currentTrigger]+=",0,0,0,0,0,0,0,A"; + + + UpdateDialog(); + + m_Action.SetCurSel(cval-1); + OnSelchangeAction(); +} + +void CTriggerActionsDlg::OnDeleteaction() +{ + CIniFile& ini=Map->GetIniFile(); + if(m_currentTrigger.GetLength()==0) return; + + int sel2=m_Action.GetCurSel(); + if(sel2<0) return; + int curev=m_Action.GetItemData(sel2); + if(MessageBox("Do you really want to delete this action?","Delete action", MB_YESNO)==IDNO) return; + + + CIniFileSection& sec=ini.sections["Actions"]; + + CString data; + data=sec.values[(LPCTSTR)m_currentTrigger]; + + int v=atoi(GetParam(data,0)); + char c[50]; + v--; + itoa(v,c,10); + data=SetParam(data,0, c); + + int pos=1+curev*8; + int posc=1+v*8; + int i; + for(i=0;i<8;i++) + data=SetParam(data,pos+i, GetParam(data,posc+i)); + + // MW April 17th, 2002: + // fixed: (char*)(LPCTSTR)data should not be modified directly, + // Instead, moving to a buffer + char* str_act=new(char[data.GetLength()+1]); + strcpy(str_act, (LPCSTR) data); + char* cupos=str_act;//(char*)(LPCTSTR)data; + for(i=0;iGetIniFile(); + + // 9.3.2001: Only support specified section +#ifndef RA2_MODE + CString sec="Actions"; +#else + CString sec="ActionsRA2"; +#endif + + while(m_ActionType.DeleteString(0)!=CB_ERR); + int i; + for(i=0;i=0) + eventdata=g_data.sections["ActionsRA2"].values[eventid]; +#endif*/ + CString text=eventid+" "+GetParam(eventdata,0); + text.Replace("%1",","); + +#ifdef RA2_MODE + if(GetParam(eventdata,12)=="1" && (yuri_mode || !isTrue(GetParam(eventdata, 14)))) + { +#else + if(GetParam(eventdata,11)=="1") + { +#endif + m_ActionType.AddString(text); + } + } + + int cur_sel=m_Action.GetCurSel(); + while(m_Action.DeleteString(0)!=CB_ERR); + + CString Data=ini.sections["Actions"].values[m_currentTrigger]; + int count=atoi(GetParam(Data,0)); + + for(i=0;i=count) cur_sel=count-1; + + m_Action.SetCurSel(cur_sel); + + + OnSelchangeAction(); +} + +// MW 07/20/01 +void CTriggerActionsDlg::Clear() +{ + m_ActionType.SetWindowText(""); + while(m_Parameter.DeleteString(0)!=LB_ERR); + m_ParamValue.SetWindowText(""); + m_ActionDescription.SetWindowText(""); +} diff --git a/MissionEditor/TriggerActionsDlg.h b/MissionEditor/TriggerActionsDlg.h new file mode 100644 index 0000000..ad213b8 --- /dev/null +++ b/MissionEditor/TriggerActionsDlg.h @@ -0,0 +1,78 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_TRIGGERACTIONSDLG_H__234BEB21_96D7_11D4_9C87_E6A6DF12E04A__INCLUDED_) +#define AFX_TRIGGERACTIONSDLG_H__234BEB21_96D7_11D4_9C87_E6A6DF12E04A__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// TriggerActionsDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTriggerActionsDlg + +class CTriggerActionsDlg : public CDialog +{ +// Konstruktion +public: + void Clear(); + void UpdateDialog(); + CString m_currentTrigger; + CTriggerActionsDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CTriggerActionsDlg) + enum { IDD = IDD_TRIGGERACTIONS }; + CMyComboBox m_ParamValue; + CListBox m_Parameter; + CMyComboBox m_ActionType; + CEdit m_ActionDescription; + CComboBox m_Action; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CTriggerActionsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CTriggerActionsDlg) + afx_msg void OnSelchangeAction(); + afx_msg void OnEditchangeActiontype(); + afx_msg void OnSelchangeParameter(); + afx_msg void OnEditchangeParamvalue(); + afx_msg void OnNewaction(); + afx_msg void OnDeleteaction(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_TRIGGERACTIONSDLG_H__234BEB21_96D7_11D4_9C87_E6A6DF12E04A__INCLUDED_ diff --git a/MissionEditor/TriggerEditorDlg.cpp b/MissionEditor/TriggerEditorDlg.cpp new file mode 100644 index 0000000..e50af2e --- /dev/null +++ b/MissionEditor/TriggerEditorDlg.cpp @@ -0,0 +1,355 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// TriggerEditorDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "TriggerEditorDlg.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" +#include "inlines.h" + +extern ACTIONDATA AD; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTriggerEditorDlg + + +CTriggerEditorDlg::CTriggerEditorDlg(CWnd* pParent /*=NULL*/) + : CDialog(CTriggerEditorDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CTriggerEditorDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Elementinitialisierung ein + //}}AFX_DATA_INIT +} + + +void CTriggerEditorDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTriggerEditorDlg) + DDX_Control(pDX, IDC_TRIGGER, m_Trigger); + DDX_Control(pDX, IDC_TRIGGERTAB, m_tab); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTriggerEditorDlg, CDialog) + //{{AFX_MSG_MAP(CTriggerEditorDlg) + ON_BN_CLICKED(IDC_NEWTRIGGER, OnNewtrigger) + ON_BN_CLICKED(IDC_DELETETRIGGER, OnDeletetrigger) + ON_CBN_SELCHANGE(IDC_TRIGGER, OnSelchangeTrigger) + ON_CBN_EDITCHANGE(IDC_TRIGGER, OnEditchangeTrigger) + ON_NOTIFY(TCN_SELCHANGE, IDC_TRIGGERTAB, OnSelchangeTriggertab) + ON_BN_CLICKED(IDC_PLACEONMAP, OnPlaceonmap) + ON_BN_CLICKED(IDC_CLONE, OnClone) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CTriggerEditorDlg + +void CTriggerEditorDlg::OnOK() +{ + +} + +void CTriggerEditorDlg::OnCancel() +{ + // TODO: Zusätzlichen Bereinigungscode hier einfĂ¼gen + + CDialog::OnCancel(); +} + +BOOL CTriggerEditorDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_tab.InsertItem(0, TranslateStringACP("Trigger options")); + m_tab.InsertItem(1, TranslateStringACP("Events")); + m_tab.InsertItem(2, TranslateStringACP("Actions")); + + m_TriggerOptions.Create(CTriggerOptionsDlg::IDD, &m_tab); + RECT r; + m_tab.GetItemRect(0, &r); + int top=m_tab.GetRowCount()*r.bottom+5; + m_tab.GetClientRect(&r); + int bottom=r.bottom-top-3; + m_TriggerOptions.SetWindowPos(NULL, 10, top, r.right-20, bottom, SWP_NOZORDER); + m_TriggerOptions.ShowWindow(SW_SHOW); + + m_TriggerEvents.Create(CTriggerEventsDlg::IDD, &m_tab); + m_TriggerEvents.SetWindowPos(NULL, 10, top, r.right-20, bottom, SWP_NOZORDER); + + m_TriggerActions.Create(CTriggerActionsDlg::IDD, &m_tab); + m_TriggerActions.SetWindowPos(NULL, 10, top, r.right-20, bottom, SWP_NOZORDER); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} + +void CTriggerEditorDlg::UpdateDialog() +{ + int i; + CIniFile& ini=Map->GetIniFile(); + + int curSel=m_Trigger.GetCurSel(); + int curData=-1; + if(curSel!=-1) + curData=m_Trigger.GetItemData(curSel); + + + while(m_Trigger.DeleteString(0)!=CB_ERR); + m_Trigger.SetWindowText(""); + + for(i=0;i=m_Trigger.GetCount()) curData=m_Trigger.GetCount()-1; + + if(ini.sections["Triggers"].values.size()) m_Trigger.SetCurSel(0); + + for(i=0;iGetIniFile(); + + CString ID_T=GetFreeID(); + ini.sections["Triggers"].values[ID_T]=Map->GetHouseID(0, TRUE)+",,New trigger,0,1,1,1,0"; + ini.sections["Events"].values[ID_T]="0"; + ini.sections["Actions"].values[ID_T]="0"; + + //if(MessageBox("Trigger created. If you want to create a simple tag now, press Yes. The tag will be called ""New tag"", you should name it like the trigger (after you have set up the trigger).","Trigger created",MB_YESNO)) + { + CString ID_TAG=GetFreeID(); + ini.sections["Tags"].values[ID_TAG]="0,New tag,"; + ini.sections["Tags"].values[ID_TAG]+=ID_T; + } + + ((CFinalSunDlg*)theApp.m_pMainWnd)->UpdateDialogs(TRUE); + + int i; + for(i=0;iGetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int curtrig=m_Trigger.GetItemData(sel); + + int res=MessageBox("If you want to delete all attached tags, too, press 'Yes'.\nIf you don´t want to delete these tags, press 'No'.\nIf you want to cancel deletion of the trigger, press 'Cancel'.\n\nNote: CellTags will never be deleted using this function","Delete trigger", MB_YESNOCANCEL); + if(res==IDCANCEL) return; + + CString trigger=*ini.sections["Triggers"].GetValueName(curtrig); + + if(res==IDYES) + { + int i; + for(i=0;iUpdateDialogs(TRUE); + +} + + + +void CTriggerEditorDlg::OnSelchangeTrigger() +{ + OnEditchangeTrigger(); +} + +void CTriggerEditorDlg::OnEditchangeTrigger() +{ + CIniFile& ini=Map->GetIniFile(); + + int curSel=m_Trigger.GetCurSel(); + if(curSel<0) + { + m_TriggerOptions.m_currentTrigger=""; + if(m_TriggerOptions.m_hWnd) m_TriggerOptions.UpdateDialog(); + m_TriggerEvents.m_currentTrigger=""; + if(m_TriggerEvents.m_hWnd) m_TriggerEvents.UpdateDialog(); + m_TriggerActions.m_currentTrigger=""; + if(m_TriggerActions.m_hWnd) m_TriggerActions.UpdateDialog(); + return; + } + + int curInd=m_Trigger.GetItemData(curSel); + + CString Trigger=*ini.sections["Triggers"].GetValueName(curInd); + + m_TriggerOptions.m_currentTrigger=Trigger; + if(m_TriggerOptions.m_hWnd) m_TriggerOptions.UpdateDialog(); + m_TriggerEvents.m_currentTrigger=Trigger; + if(m_TriggerEvents.m_hWnd) m_TriggerEvents.UpdateDialog(); + m_TriggerActions.m_currentTrigger=Trigger; + if(m_TriggerActions.m_hWnd) m_TriggerActions.UpdateDialog(); +} + +void CTriggerEditorDlg::OnSelchangeTriggertab(NMHDR* pNMHDR, LRESULT* pResult) +{ + m_TriggerEvents.ShowWindow(SW_HIDE); + m_TriggerOptions.ShowWindow(SW_HIDE); + m_TriggerActions.ShowWindow(SW_HIDE); + + switch(m_tab.GetCurSel()) + { + case 0: + m_TriggerOptions.ShowWindow(SW_SHOW); + m_TriggerOptions.UpdateDialog(); + break; + case 1: + m_TriggerEvents.ShowWindow(SW_SHOW); + m_TriggerEvents.UpdateDialog(); + break; + case 2: + m_TriggerActions.ShowWindow(SW_SHOW); + m_TriggerActions.UpdateData(); + break; + } + + *pResult = 0; +} + +void CTriggerEditorDlg::OnPlaceonmap() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int curtrig=m_Trigger.GetItemData(sel); + + CString trigger=*ini.sections["Triggers"].GetValueName(curtrig); + + int i; + CString tag; + for(i=0;iGetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int curtrig=m_Trigger.GetItemData(sel); + + CString trigger=*ini.sections["Triggers"].GetValueName(curtrig); + + CString ID_T=GetFreeID(); + ini.sections["Triggers"].values[ID_T]=ini.sections["Triggers"].values[trigger]; + ini.sections["Events"].values[ID_T]=ini.sections["Events"].values[trigger]; + ini.sections["Actions"].values[ID_T]=ini.sections["Actions"].values[trigger]; + + ini.sections["Triggers"].values[ID_T]=SetParam(ini.sections["Triggers"].values[ID_T], 2, GetParam(ini.sections["Triggers"].values[ID_T], 2) + " Clone"); + + { + CString ID_TAG=GetFreeID(); + ini.sections["Tags"].values[ID_TAG]=(CString)"0,"+GetParam(ini.sections["Triggers"].values[ID_T], 2)+","; + ini.sections["Tags"].values[ID_TAG]+=ID_T; + } + + ((CFinalSunDlg*)theApp.m_pMainWnd)->UpdateDialogs(TRUE); + + int i; + for(i=0;i. +*/ + +#if !defined(AFX_TRIGGEREDITORDLG_H__E9CA56E1_93E6_11D4_9C87_F3E3AC59A04A__INCLUDED_) +#define AFX_TRIGGEREDITORDLG_H__E9CA56E1_93E6_11D4_9C87_F3E3AC59A04A__INCLUDED_ + +#include "TriggerOptionsDlg.h" // HinzugefĂ¼gt von der Klassenansicht +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// TriggerEditorDlg.h : Header-Datei +// + +#include "MyComboBox.h" +#include "TriggerEventsDlg.h" // HinzugefĂ¼gt von der Klassenansicht +#include "TriggerActionsDlg.h" // HinzugefĂ¼gt von der Klassenansicht + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTriggerEditorDlg + +class CTriggerEditorDlg : public CDialog +{ +// Konstruktion +public: + void Clear(); + CTriggerActionsDlg m_TriggerActions; + CTriggerEventsDlg m_TriggerEvents; + CTriggerOptionsDlg m_TriggerOptions; + void UpdateDialog(); + CTriggerEditorDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CTriggerEditorDlg) + enum { IDD = IDD_TRIGGEREDITOR }; + CMyComboBox m_Trigger; + CTabCtrl m_tab; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CTriggerEditorDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CTriggerEditorDlg) + virtual void OnOK(); + virtual void OnCancel(); + virtual BOOL OnInitDialog(); + afx_msg void OnNewtrigger(); + afx_msg void OnDeletetrigger(); + afx_msg void OnSelchangeTrigger(); + afx_msg void OnEditchangeTrigger(); + afx_msg void OnSelchangeTriggertab(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnPlaceonmap(); + afx_msg void OnClone(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_TRIGGEREDITORDLG_H__E9CA56E1_93E6_11D4_9C87_F3E3AC59A04A__INCLUDED_ diff --git a/MissionEditor/TriggerEventsDlg.cpp b/MissionEditor/TriggerEventsDlg.cpp new file mode 100644 index 0000000..79a51c9 --- /dev/null +++ b/MissionEditor/TriggerEventsDlg.cpp @@ -0,0 +1,588 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// TriggerEventsDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "TriggerEventsDlg.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" +#include "inlines.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTriggerEventsDlg + + +CTriggerEventsDlg::CTriggerEventsDlg(CWnd* pParent /*=NULL*/) + : CDialog(CTriggerEventsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CTriggerEventsDlg) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Elementinitialisierung ein + //}}AFX_DATA_INIT +} + + +void CTriggerEventsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTriggerEventsDlg) + DDX_Control(pDX, IDC_PARAMVALUE, m_ParamValue); + DDX_Control(pDX, IDC_PARAMETER, m_Parameter); + DDX_Control(pDX, IDC_EVENTTYPE, m_EventType); + DDX_Control(pDX, IDC_EVENTDESCRIPTION, m_EventDescription); + DDX_Control(pDX, IDC_EVENT, m_Event); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTriggerEventsDlg, CDialog) + //{{AFX_MSG_MAP(CTriggerEventsDlg) + ON_BN_CLICKED(IDC_NEWEVENT, OnNewevent) + ON_BN_CLICKED(IDC_DELETEEVENT, OnDeleteevent) + ON_CBN_SELCHANGE(IDC_EVENT, OnSelchangeEvent) + ON_CBN_EDITCHANGE(IDC_EVENTTYPE, OnEditchangeEventtype) + ON_LBN_SELCHANGE(IDC_PARAMETER, OnSelchangeParameter) + ON_CBN_EDITCHANGE(IDC_PARAMVALUE, OnEditchangeParamvalue) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CTriggerEventsDlg + +// MW 07/23/01: Added this because startpos=1+curev*3 isn´t anymore valid for calculating the next event +int GetEventParamStart(CString& EventData, int param) +{ + int count=atoi(GetParam(EventData, 0)); + if(param>=count) return -1; + + int pos=1; + int i; + for(i=0;iGetIniFile(); + + if(m_currentTrigger.GetLength()==0) return; + + + CIniFileSection& sec=ini.sections["Events"]; + + int cval=atoi(GetParam(sec.values[(LPCTSTR)m_currentTrigger],0)); + cval++; + char c[50]; + itoa(cval,c,10); + + sec.values[(LPCTSTR)m_currentTrigger]=SetParam(sec.values[(LPCTSTR)m_currentTrigger],0,c); + sec.values[(LPCTSTR)m_currentTrigger]+=",0,0,0"; + + + UpdateDialog(); + + m_Event.SetCurSel(cval-1); + OnSelchangeEvent(); +} + +int FindTokenX(CString data, char token, int n) +{ + if(n<=0) return -1; + + int found=0; + int pos=0; + while(foundGetIniFile(); + if(m_currentTrigger.GetLength()==0) return; + + int sel2=m_Event.GetCurSel(); + if(sel2<0) return; + int curev=m_Event.GetItemData(sel2); + if(MessageBox("Do you really want to delete this event?","Delete event", MB_YESNO)==IDNO) return; + + + CIniFileSection& sec=ini.sections["Events"]; + + CString data; + data=sec.values[(LPCTSTR)m_currentTrigger]; + + CString orig_data=data; + + int v=atoi(GetParam(data,0)); + char c[50]; + v--; + itoa(v,c,10); + data=SetParam(data,0, c); + + int pos=GetEventParamStart(orig_data, curev);//1+curev*3; + //int posc=GetEventParamStart(orig_data, v);//1+v*3; + + // MW 07/23/01: + // NEW DELETE EVENT CODE... + + // Now check for those 2 param + code events... + BOOL bEvent1Needs4=FALSE; + + + if(GetParam(data, pos+1)=="2") bEvent1Needs4=TRUE; + + int count=3; + if(bEvent1Needs4) count=4; + + int del_start=FindTokenX(data, ',', pos); + int del_end=FindTokenX(data, ',', pos+count); + if(del_end<0) + { + // beyond end, so delete all... + del_end=data.GetLength(); + + } + data.Delete(del_start, del_end-del_start); + + /* + old delete event code, that used replacement. Not possible anymore because of 4 values/event sometimes now + + int i; + for(i=0;i<3;i++) + data=SetParam(data,pos+i, GetParam(data,posc+i)); + + char* cupos=(char*)(LPCTSTR)data; + for(i=0;iGetIniFile(); + + if(m_currentTrigger.GetLength()==0) return; + int selev=m_Event.GetCurSel(); + if(selev<0) return; + int curev=m_Event.GetItemData(selev); + + + int i; + + CString EventData; + EventData=ini.sections["Events"].values[(LPCTSTR)m_currentTrigger]; + + int startpos=GetEventParamStart(EventData, curev); //1+curev*3; + CString EventType=GetParam(EventData,startpos); + m_EventType.SetWindowText(EventType); + for(i=0;iGetIniFile(); + + if(m_currentTrigger.GetLength()==0) return; + int selev=m_Event.GetCurSel(); + if(selev<0) return; + int curev=m_Event.GetItemData(selev); + + CString e1,e2; + while(m_Parameter.DeleteString(0)!=CB_ERR); + + + CString eventtype,eventdata; + m_EventType.GetWindowText(eventtype); + TruncSpace(eventtype); + + if(eventtype.GetLength()==0) + { + eventtype="0"; + m_EventType.SetWindowText(eventtype); + } + + int pos=GetEventParamStart(ini.sections["Events"].values[(LPCTSTR)m_currentTrigger], curev); //1+3*curev; + + BOOL bAlready4=FALSE; + if(atoi(GetParam(ini.sections["Events"].values[(LPCTSTR)m_currentTrigger], pos+1))==2) + bAlready4=TRUE; + + ini.sections["Events"].values[(LPCTSTR)m_currentTrigger]=SetParam(ini.sections["Events"].values[(LPCTSTR)m_currentTrigger], pos, (LPCTSTR)eventtype); + + + CString evsec="Events"; +#ifdef RA2_MODE + evsec="EventsRA2"; +#endif + + + if(g_data.sections[evsec].FindName(eventtype)<0) return; + eventdata=g_data.sections[evsec].values[eventtype]; + +#ifdef RA2_MODE + if(g_data.sections["EventsRA2"].FindName(eventtype)>=0) + eventdata=g_data.sections["EventsRA2"].values[eventtype]; +#endif + + CString desc=GetParam(eventdata,5); + desc.Replace("%1",","); + m_EventDescription.SetWindowText(desc); + + CString ptype[2]; + ptype[0]=GetParam(eventdata,1); + ptype[1]=GetParam(eventdata,2); + + + int pListType[2]; + pListType[0]=atoi(GetParam(g_data.sections["ParamTypes"].values[ptype[0]], 1)); + pListType[1]=atoi(GetParam(g_data.sections["ParamTypes"].values[ptype[1]], 1)); + + int code=atoi(GetParam(g_data.sections["ParamTypes"].values[ptype[0]], 2)); // usually 0 + + // ************************************** + // MW ADD SUPPORT FOR 2 PARAMS+CODE + if(code==2) + { + // add code + event 0 ONLY IF THEY DO NOT ALREADY EXIST + if(!bAlready4) ini.sections["Events"].values[(LPCTSTR)m_currentTrigger]=SetParam(ini.sections["Events"].values[(LPCTSTR)m_currentTrigger], pos+1, "2,0"); + + } + else + { + // remove code + event 0 + char c[50]; + itoa(code, c, 10); + ini.sections["Events"].values[(LPCTSTR)m_currentTrigger]=SetParam(ini.sections["Events"].values[(LPCTSTR)m_currentTrigger], pos+1, c); + + if(bAlready4) + { + + CString& data=ini.sections["Events"].values[(LPCTSTR)m_currentTrigger]; + + int del_start=FindTokenX(data, ',', pos+2); + int del_end=FindTokenX(data, ',', pos+3); + if(del_end<0) + { + // beyond end, so delete all... + del_end=data.GetLength(); + + } + data.Delete(del_start, del_end-del_start); + } + + } + // ************************************** + + int i; + for(i=0;i<2;i++) + { + int add=0; + if(code==2) add=1; + + if(atoi(ptype[i])!=0 && atoi(ptype[i])>0 && atoi(ptype[i])!=47) + { + CString paramname=GetParam(g_data.sections["ParamTypes"].values[ptype[i]], 0); + + m_Parameter.SetItemData(m_Parameter.AddString(paramname), i+add); + } + + + } + + m_ParamValue.SetWindowText(""); + if(m_Parameter.GetCount()>0) { + m_Parameter.SetCurSel(0); + OnSelchangeParameter(); + } + + + + RepairTrigger(ini.sections["Triggers"].values[m_currentTrigger]); + +} + + + +void CTriggerEventsDlg::OnSelchangeParameter() +{ + CIniFile& ini=Map->GetIniFile(); + + if(m_currentTrigger.GetLength()==0) return; + int selev=m_Event.GetCurSel(); + if(selev<0) return; + int curev=m_Event.GetItemData(selev); + + int curselparam=m_Parameter.GetCurSel(); + if(curselparam<0) + { + m_ParamValue.SetWindowText(""); + return; + } + + + + int curparam=m_Parameter.GetItemData(curselparam); + + + CString EventData; + EventData=ini.sections["Events"].values[(LPCTSTR)m_currentTrigger]; + + int startpos=GetEventParamStart(EventData, curev);//1+curev*3; + + + // MW FIX FOR CODE!=0 + int original_cuparam=curparam; +#ifdef RA2_MODE + CString Param1=GetParam(g_data.sections["EventsRA2"].values[GetParam(EventData,startpos)],1); + CString Code=GetParam(g_data.sections["ParamTypes"].values[Param1],2); + //MessageBox(Param1, Code); + if(atoi(Code)!=0) curparam--; +#endif + // END FIx + + CString ParamType=GetParam(g_data.sections["Events"].values[GetParam(EventData,startpos)],1+curparam); +#ifdef RA2_MODE + if(g_data.sections["EventsRA2"].FindName(GetParam(EventData, startpos))>=0) ParamType=GetParam(g_data.sections["EventsRA2"].values[GetParam(EventData,startpos)],1+curparam); +#endif + + if(atoi(ParamType)<0) + { + } + else + { + CString ListType=GetParam(g_data.sections["ParamTypes"].values[ParamType],1); + + HandleParamList(m_ParamValue, atoi(ListType)); + m_ParamValue.SetWindowText(GetParam(EventData,startpos+1+original_cuparam)); + + int i; + BOOL bFound=FALSE; + for(i=0;iGetIniFile(); + + if(m_currentTrigger.GetLength()==0) return; + int selev=m_Event.GetCurSel(); + if(selev<0) return; + int curev=m_Event.GetItemData(selev); + + int curselparam=m_Parameter.GetCurSel(); + if(curselparam<0) + { + m_ParamValue.SetWindowText(""); + return; + } + + int curparam=m_Parameter.GetItemData(curselparam); + + CString EventData; + EventData=ini.sections["Events"].values[(LPCTSTR)m_currentTrigger]; + + int startpos=GetEventParamStart(EventData, curev);// 1+curev*3; + + + CString newVal; + m_ParamValue.GetWindowText(newVal); + TruncSpace(newVal); + newVal.TrimLeft(); + + if(newVal.Find(",",0)>=0) newVal.SetAt(newVal.Find(",",0), 0); + + ini.sections["Events"].values[(LPCTSTR)m_currentTrigger]=SetParam(EventData, startpos+1+curparam, newVal); +} + +void CTriggerEventsDlg::UpdateDialog() +{ + // MW 07/20/01 + Clear(); + + if(m_currentTrigger.GetLength()==0) + { + while(m_Event.DeleteString(0)!=CB_ERR); + return; + } + CIniFile& ini=Map->GetIniFile(); + + while(m_EventType.DeleteString(0)!=CB_ERR); + int i; + + //9.3.2001: Only use specified section, do not merge +#ifndef RA2_MODE + CString sec="Events"; +#else + CString sec="EventsRA2"; +#endif + + for(i=0;i=0) + eventdata=g_data.sections["EventsRA2"].values[eventid]; +#endif*/ + + CString text=eventid+" "+GetParam(eventdata,0); + text.Replace("%1",","); +#ifdef RA2_MODE + // MW 07/18/01 + // for yuri mode, only check if it´s for RA2, else support it only if YR isnt´needed... + if(GetParam(eventdata, 7)=="1" && ( yuri_mode || !atoi(GetParam(eventdata,9)) ) ) + { + + +#else + if(GetParam(eventdata, 6)=="1") + { +#endif + m_EventType.AddString(text); + } + } + + + + int cur_sel=m_Event.GetCurSel(); + while(m_Event.DeleteString(0)!=CB_ERR); + + CString Data=ini.sections["Events"].values[m_currentTrigger]; + int count=atoi(GetParam(Data,0)); + + for(i=0;i=count) cur_sel=count-1; + + m_Event.SetCurSel(cur_sel); + + + OnSelchangeEvent(); +} + +// MW 07/20/01 +void CTriggerEventsDlg::Clear() +{ + m_EventType.SetWindowText(""); + while(m_Parameter.DeleteString(0)!=LB_ERR); + m_ParamValue.SetWindowText(""); + m_EventDescription.SetWindowText(""); +} diff --git a/MissionEditor/TriggerEventsDlg.h b/MissionEditor/TriggerEventsDlg.h new file mode 100644 index 0000000..5345a04 --- /dev/null +++ b/MissionEditor/TriggerEventsDlg.h @@ -0,0 +1,80 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_TRIGGEREVENTSDLG_H__13CDEBA1_961C_11D4_9C87_BD9803B9B54A__INCLUDED_) +#define AFX_TRIGGEREVENTSDLG_H__13CDEBA1_961C_11D4_9C87_BD9803B9B54A__INCLUDED_ + +#include "resource.h" + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// TriggerEventsDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTriggerEventsDlg + +class CTriggerEventsDlg : public CDialog +{ +// Konstruktion +public: + void Clear(); + CString m_currentTrigger; + void UpdateDialog(); + CTriggerEventsDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CTriggerEventsDlg) + enum { IDD = IDD_TRIGGEREVENTS }; + CMyComboBox m_ParamValue; + CListBox m_Parameter; + CMyComboBox m_EventType; + CEdit m_EventDescription; + CComboBox m_Event; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CTriggerEventsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CTriggerEventsDlg) + afx_msg void OnNewevent(); + afx_msg void OnDeleteevent(); + afx_msg void OnSelchangeEvent(); + afx_msg void OnEditchangeEventtype(); + afx_msg void OnSelchangeParameter(); + afx_msg void OnEditchangeParamvalue(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_TRIGGEREVENTSDLG_H__13CDEBA1_961C_11D4_9C87_BD9803B9B54A__INCLUDED_ diff --git a/MissionEditor/TriggerOptionsDlg.cpp b/MissionEditor/TriggerOptionsDlg.cpp new file mode 100644 index 0000000..3c40214 --- /dev/null +++ b/MissionEditor/TriggerOptionsDlg.cpp @@ -0,0 +1,357 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// TriggerOptionsDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "TriggerOptionsDlg.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" +#include "inlines.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTriggerOptionsDlg + + +CTriggerOptionsDlg::CTriggerOptionsDlg(CWnd* pParent /*=NULL*/) + : CDialog(CTriggerOptionsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CTriggerOptionsDlg) + //}}AFX_DATA_INIT +} + + +void CTriggerOptionsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTriggerOptionsDlg) + DDX_Control(pDX, IDC_MEDIUM, m_Medium); + DDX_Control(pDX, IDC_HARD, m_Hard); + DDX_Control(pDX, IDC_EASY, m_Easy); + DDX_Control(pDX, IDC_DISABLED, m_Disabled); + DDX_Control(pDX, IDC_TRIGGERTYPE, m_TriggerType); + DDX_Control(pDX, IDC_NAME, m_Name); + DDX_Control(pDX, IDC_HOUSE, m_House); + DDX_Control(pDX, IDC_ATTACHEDTRIGGER, m_AttachedTrigger); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTriggerOptionsDlg, CDialog) + //{{AFX_MSG_MAP(CTriggerOptionsDlg) + ON_EN_CHANGE(IDC_NAME, OnChangeName) + ON_CBN_EDITCHANGE(IDC_HOUSE, OnEditchangeHouse) + ON_CBN_EDITCHANGE(IDC_ATTACHEDTRIGGER, OnEditchangeAttachedtrigger) + ON_EN_KILLFOCUS(IDC_NAME, OnKillfocusName) + ON_WM_KILLFOCUS() + ON_CBN_EDITCHANGE(IDC_TRIGGERTYPE, OnEditchangeTriggertype) + ON_BN_CLICKED(IDC_DISABLED, OnDisabled) + ON_BN_CLICKED(IDC_EASY, OnEasy) + ON_BN_CLICKED(IDC_MEDIUM, OnMedium) + ON_BN_CLICKED(IDC_HARD, OnHard) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CTriggerOptionsDlg + +void CTriggerOptionsDlg::UpdateDialog() +{ + // MW 07/20/01 + + CIniFile& ini=Map->GetIniFile(); + if(m_currentTrigger.GetLength()==0) return; + + ListHouses(m_House, FALSE, TRUE, FALSE); + ListTriggers(m_AttachedTrigger); + m_AttachedTrigger.InsertString(0, ""); + + RepairTrigger(ini.sections["Triggers"].values[m_currentTrigger]); + + m_Name.SetWindowText(GetParam(ini.sections["Triggers"].values[m_currentTrigger],2)); + m_House.SetWindowText(TranslateHouse(GetParam(ini.sections["Triggers"].values[m_currentTrigger],0), TRUE)); + CString attachedTrigger=GetParam(ini.sections["Triggers"].values[m_currentTrigger],1); + m_AttachedTrigger.SetWindowText(attachedTrigger); + + m_Disabled.SetCheck((atoi(GetParam(ini.sections["Triggers"].values[m_currentTrigger],3)))); + m_Easy.SetCheck((atoi(GetParam(ini.sections["Triggers"].values[m_currentTrigger],4)))); + m_Medium.SetCheck((atoi(GetParam(ini.sections["Triggers"].values[m_currentTrigger],5)))); + m_Hard.SetCheck((atoi(GetParam(ini.sections["Triggers"].values[m_currentTrigger],6)))); + + int i; + for(i=0;iGetIniFile(); + + if(ini.sections["Triggers"].FindName(m_currentTrigger)<0 || m_currentTrigger.GetLength()==0) return; + + CString newName; + m_Name.GetWindowText(newName); + + if(newName.GetLength()==0) newName=" "; + + if(newName.Find(",",0)>=0) + {//newName.SetAt(newName.Find(",",0), 0); + newName=newName.Left(newName.Find(",",0)); + + m_Name.SetWindowText(newName);} + + + + ini.sections["Triggers"].values[m_currentTrigger]=SetParam(ini.sections["Triggers"].values[m_currentTrigger], 2, newName); + + int i; + int p=0; + for(i=0;iGetIniFile(); + + if(ini.sections["Triggers"].FindName(m_currentTrigger)<0 || m_currentTrigger.GetLength()==0) return; + + CString newHouse; + m_House.GetWindowText(newHouse); + + + + newHouse=TranslateHouse(newHouse); + + newHouse.TrimLeft(); + TruncSpace(newHouse); + if(newHouse.Find(",",0)>=0) newHouse.SetAt(newHouse.Find(",",0), 0); + + + + ini.sections["Triggers"].values[m_currentTrigger]=SetParam(ini.sections["Triggers"].values[m_currentTrigger], 0, newHouse); + + RepairTrigger(ini.sections["Triggers"].values[m_currentTrigger]); + +} + +void CTriggerOptionsDlg::OnEditchangeAttachedtrigger() +{ + CIniFile& ini=Map->GetIniFile(); + + if(ini.sections["Triggers"].FindName(m_currentTrigger)<0 || m_currentTrigger.GetLength()==0) return; + + CString newTrigger; + m_AttachedTrigger.GetWindowText(newTrigger); + newTrigger.TrimLeft(); + TruncSpace(newTrigger); + + if(newTrigger.Find(",",0)>=0) newTrigger.SetAt(newTrigger.Find(",",0), 0); + + + ini.sections["Triggers"].values[m_currentTrigger]=SetParam(ini.sections["Triggers"].values[m_currentTrigger], 1, newTrigger); + + + +} + +void CTriggerOptionsDlg::OnKillfocusName() +{ + ((CTriggerEditorDlg*)(this->GetOwner()->GetOwner()))->UpdateDialog(); +} + +void CTriggerOptionsDlg::OnKillFocus(CWnd* pNewWnd) +{ + CDialog::OnKillFocus(pNewWnd); + + ((CTriggerEditorDlg*)(this->GetOwner()->GetOwner()))->UpdateDialog(); +} + +void CTriggerOptionsDlg::OnEditchangeTriggertype() +{ + CIniFile& ini=Map->GetIniFile(); + + if(ini.sections["Triggers"].FindName(m_currentTrigger)<0 || m_currentTrigger.GetLength()==0) return; + + + CString newType; + m_TriggerType.GetWindowText(newType); + TruncSpace(newType); + + int i; + for(i=0;iGetIniFile(); + + if(ini.sections["Triggers"].FindName(m_currentTrigger)<0 || m_currentTrigger.GetLength()==0) return; + + BOOL bDisabled=FALSE; + if(m_Disabled.GetCheck()==0) bDisabled=FALSE; + else + bDisabled=TRUE; + + if(bDisabled) + ini.sections["Triggers"].values[m_currentTrigger]=SetParam(ini.sections["Triggers"].values[m_currentTrigger], 3, "1"); + else + ini.sections["Triggers"].values[m_currentTrigger]=SetParam(ini.sections["Triggers"].values[m_currentTrigger], 3, "0"); + + + +} + +void CTriggerOptionsDlg::OnEasy() +{ + CIniFile& ini=Map->GetIniFile(); + + if(ini.sections["Triggers"].FindName(m_currentTrigger)<0 || m_currentTrigger.GetLength()==0) return; + + BOOL bEasy=FALSE; + if(m_Easy.GetCheck()==0) bEasy=FALSE; + else + bEasy=TRUE; + + if(bEasy) + ini.sections["Triggers"].values[m_currentTrigger]=SetParam(ini.sections["Triggers"].values[m_currentTrigger], 4, "1"); + else + ini.sections["Triggers"].values[m_currentTrigger]=SetParam(ini.sections["Triggers"].values[m_currentTrigger], 4, "0"); + + +} + +void CTriggerOptionsDlg::OnMedium() +{ + CIniFile& ini=Map->GetIniFile(); + + if(ini.sections["Triggers"].FindName(m_currentTrigger)<0 || m_currentTrigger.GetLength()==0) return; + + BOOL bMedium=FALSE; + if(m_Medium.GetCheck()==0) bMedium=FALSE; + else + bMedium=TRUE; + + if(bMedium) + ini.sections["Triggers"].values[m_currentTrigger]=SetParam(ini.sections["Triggers"].values[m_currentTrigger], 5, "1"); + else + ini.sections["Triggers"].values[m_currentTrigger]=SetParam(ini.sections["Triggers"].values[m_currentTrigger], 5, "0"); + +} + +void CTriggerOptionsDlg::OnHard() +{ + CIniFile& ini=Map->GetIniFile(); + + if(ini.sections["Triggers"].FindName(m_currentTrigger)<0 || m_currentTrigger.GetLength()==0) return; + + BOOL bHard=FALSE; + if(m_Hard.GetCheck()==0) bHard=FALSE; + else + bHard=TRUE; + + if(bHard) + ini.sections["Triggers"].values[m_currentTrigger]=SetParam(ini.sections["Triggers"].values[m_currentTrigger], 6, "1"); + else + ini.sections["Triggers"].values[m_currentTrigger]=SetParam(ini.sections["Triggers"].values[m_currentTrigger], 6, "0"); + +} + +//MW 07/20/01 +void CTriggerOptionsDlg::Clear() +{ + +} diff --git a/MissionEditor/TriggerOptionsDlg.h b/MissionEditor/TriggerOptionsDlg.h new file mode 100644 index 0000000..b9641fd --- /dev/null +++ b/MissionEditor/TriggerOptionsDlg.h @@ -0,0 +1,88 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_TRIGGEROPTIONSDLG_H__FA26A541_949D_11D4_9C87_CBD54CC4BF4A__INCLUDED_) +#define AFX_TRIGGEROPTIONSDLG_H__FA26A541_949D_11D4_9C87_CBD54CC4BF4A__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// TriggerOptionsDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTriggerOptionsDlg + +class CTriggerOptionsDlg : public CDialog +{ +// Konstruktion +public: + void Clear(); + virtual BOOL PreTranslateMessage(MSG* pMsg); + void UpdateDialog(); + CString m_currentTrigger; + CTriggerOptionsDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CTriggerOptionsDlg) + enum { IDD = IDD_TRIGGEROPTIONS }; + CButton m_Medium; + CButton m_Hard; + CButton m_Easy; + CButton m_Disabled; + CMyComboBox m_TriggerType; + CEdit m_Name; + CMyComboBox m_House; + CMyComboBox m_AttachedTrigger; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CTriggerOptionsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + CToolTipCtrl m_tooltip; + virtual BOOL OnInitDialog(); + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CTriggerOptionsDlg) + afx_msg void OnChangeName(); + afx_msg void OnEditchangeHouse(); + afx_msg void OnEditchangeAttachedtrigger(); + afx_msg void OnKillfocusName(); + afx_msg void OnKillFocus(CWnd* pNewWnd); + afx_msg void OnEditchangeTriggertype(); + afx_msg void OnDisabled(); + afx_msg void OnEasy(); + afx_msg void OnMedium(); + afx_msg void OnHard(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_TRIGGEROPTIONSDLG_H__FA26A541_949D_11D4_9C87_CBD54CC4BF4A__INCLUDED_ diff --git a/MissionEditor/Triggers.cpp b/MissionEditor/Triggers.cpp new file mode 100644 index 0000000..bd8137d --- /dev/null +++ b/MissionEditor/Triggers.cpp @@ -0,0 +1,1458 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Triggers.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "Triggers.h" +#include "FinalSunDlg.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" +#include "inlines.h" + +CString GetWaypoint(int n); +int GetWaypoint(const char* c); + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Eigenschaftenseite CTriggers + +IMPLEMENT_DYNCREATE(CTriggers, CDialog) + + +CTriggers::CTriggers() : CDialog(CTriggers::IDD) +{ + //{{AFX_DATA_INIT(CTriggers) + m_F1 = _T(""); + m_F2 = _T(""); + m_F3 = _T(""); + m_F4 = _T(""); + m_F5 = _T(""); + m_LA1 = _T(""); + m_LA2 = _T(""); + m_LA3 = _T(""); + m_LA4 = _T(""); + m_LA5 = _T(""); + m_LA6 = _T(""); + m_LE1 = _T(""); + m_LE2 = _T(""); + m_Name = _T(""); + m_LAW = _T(""); + //}}AFX_DATA_INIT +} + +CTriggers::~CTriggers() +{ +} + +void CTriggers::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTriggers) + DDX_Control(pDX, IDC_EVENTPARAM2, m_E2); + DDX_Control(pDX, IDC_EVENTPARAM1, m_E1); + DDX_Control(pDX, IDC_ACTIONPARAM6, m_A6); + DDX_Control(pDX, IDC_ACTIONPARAM5, m_A5); + DDX_Control(pDX, IDC_ACTIONPARAM4, m_A4); + DDX_Control(pDX, IDC_ACTIONPARAM3, m_A3); + DDX_Control(pDX, IDC_ACTIONPARAM2, m_A2); + DDX_Control(pDX, IDC_ACTIONPARAM1, m_A1); + DDX_Control(pDX, IDC_HOUSE, m_House); + DDX_Control(pDX, IDC_TRIGGER2, m_Trigger2); + DDX_Control(pDX, IDC_TRIGGER, m_Trigger); + DDX_Control(pDX, IDC_EVENTTYPE, m_EventType); + DDX_Control(pDX, IDC_EVENT, m_Event); + DDX_Control(pDX, IDC_ACTIONWAYPOINT, m_ActionWaypoint); + DDX_Control(pDX, IDC_ACTIONTYPE, m_ActionType); + DDX_Control(pDX, IDC_ACTION, m_Action); + DDX_Text(pDX, IDC_FLAG1, m_F1); + DDX_Text(pDX, IDC_FLAG2, m_F2); + DDX_Text(pDX, IDC_FLAG3, m_F3); + DDX_Text(pDX, IDC_FLAG4, m_F4); + DDX_Text(pDX, IDC_FLAG5, m_F5); + DDX_Text(pDX, IDC_LABEL_A1, m_LA1); + DDX_Text(pDX, IDC_LABEL_A2, m_LA2); + DDX_Text(pDX, IDC_LABEL_A3, m_LA3); + DDX_Text(pDX, IDC_LABEL_A4, m_LA4); + DDX_Text(pDX, IDC_LABEL_A5, m_LA5); + DDX_Text(pDX, IDC_LABEL_A6, m_LA6); + DDX_Text(pDX, IDC_LABEL_E1, m_LE1); + DDX_Text(pDX, IDC_LABEL_E2, m_LE2); + DDX_Text(pDX, IDC_NAME, m_Name); + DDX_Text(pDX, IDC_WAYPOINT, m_LAW); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTriggers, CDialog) + //{{AFX_MSG_MAP(CTriggers) + ON_CBN_SELCHANGE(IDC_TRIGGER, OnSelchangeTrigger) + ON_CBN_SELCHANGE(IDC_EVENT, OnSelchangeEvent) + ON_CBN_SELCHANGE(IDC_ACTION, OnSelchangeAction) + ON_CBN_EDITCHANGE(IDC_HOUSE, OnEditchangeHouse) + ON_CBN_SELCHANGE(IDC_HOUSE, OnSelchangeHouse) + ON_EN_CHANGE(IDC_NAME, OnChangeName) + ON_EN_CHANGE(IDC_FLAG1, OnChangeFlag1) + ON_EN_CHANGE(IDC_FLAG2, OnChangeFlag2) + ON_EN_CHANGE(IDC_FLAG3, OnChangeFlag3) + ON_EN_CHANGE(IDC_FLAG4, OnChangeFlag4) + ON_EN_CHANGE(IDC_FLAG5, OnChangeFlag5) + ON_CBN_EDITCHANGE(IDC_TRIGGER2, OnEditchangeTrigger2) + ON_CBN_SELCHANGE(IDC_TRIGGER2, OnSelchangeTrigger2) + ON_CBN_EDITCHANGE(IDC_EVENTTYPE, OnEditchangeEventtype) + ON_CBN_SELCHANGE(IDC_EVENTTYPE, OnSelchangeEventtype) + ON_CBN_EDITCHANGE(IDC_EVENTPARAM1, OnEditchangeEventparam1) + ON_CBN_SELCHANGE(IDC_EVENTPARAM1, OnSelchangeEventparam1) + ON_CBN_EDITCHANGE(IDC_EVENTPARAM2, OnEditchangeEventparam2) + ON_CBN_SELCHANGE(IDC_EVENTPARAM2, OnSelchangeEventparam2) + ON_CBN_EDITCHANGE(IDC_ACTIONTYPE, OnEditchangeActiontype) + ON_CBN_SELCHANGE(IDC_ACTIONTYPE, OnSelchangeActiontype) + ON_CBN_EDITCHANGE(IDC_ACTIONWAYPOINT, OnEditchangeActionwaypoint) + ON_CBN_SELCHANGE(IDC_ACTIONWAYPOINT, OnSelchangeActionwaypoint) + ON_CBN_EDITCHANGE(IDC_ACTIONPARAM1, OnEditchangeActionparam1) + ON_CBN_SELCHANGE(IDC_ACTIONPARAM1, OnSelchangeActionparam1) + ON_CBN_EDITCHANGE(IDC_ACTIONPARAM2, OnEditchangeActionparam2) + ON_CBN_SELCHANGE(IDC_ACTIONPARAM2, OnSelchangeActionparam2) + ON_CBN_EDITCHANGE(IDC_ACTIONPARAM3, OnEditchangeActionparam3) + ON_CBN_SELCHANGE(IDC_ACTIONPARAM3, OnSelchangeActionparam3) + ON_CBN_EDITCHANGE(IDC_ACTIONPARAM4, OnEditchangeActionparam4) + ON_CBN_SELCHANGE(IDC_ACTIONPARAM4, OnSelchangeActionparam4) + ON_CBN_EDITCHANGE(IDC_ACTIONPARAM5, OnEditchangeActionparam5) + ON_CBN_SELCHANGE(IDC_ACTIONPARAM5, OnSelchangeActionparam5) + ON_CBN_EDITCHANGE(IDC_ACTIONPARAM6, OnEditchangeActionparam6) + ON_CBN_SELCHANGE(IDC_ACTIONPARAM6, OnSelchangeActionparam6) + ON_BN_CLICKED(IDC_ADDEVENT, OnAddevent) + ON_BN_CLICKED(IDC_DELETEEVENT, OnDeleteevent) + ON_BN_CLICKED(IDC_ADDACTION, OnAddaction) + ON_BN_CLICKED(IDC_DELETEACTION, OnDeleteaction) + ON_BN_CLICKED(IDC_DELETETRIGGER, OnDeletetrigger) + ON_BN_CLICKED(IDC_ADDTRIGGER, OnAddtrigger) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CTriggers + + +void CTriggers::UpdateDialog() +{ + CIniFile& ini=Map->GetIniFile(); + + + int sel=m_Trigger.GetCurSel(); + int selat=m_Action.GetCurSel(); + int selev=m_Event.GetCurSel(); + + while(m_Trigger.DeleteString(0)!=CB_ERR); + while(m_Trigger2.DeleteString(0)!=CB_ERR); + while(m_Action.DeleteString(0)!=CB_ERR); + while(m_Event.DeleteString(0)!=CB_ERR); + while(m_ActionWaypoint.DeleteString(0)!=CB_ERR); + while(m_House.DeleteString(0)!=CB_ERR); + while(m_ActionType.DeleteString(0)!=CB_ERR); + while(m_EventType.DeleteString(0)!=CB_ERR); + + m_LE1="Parameter 1"; + m_LE2="Parameter 2"; + m_LA1="Param1"; + m_LA2="Param2"; + m_LA3="Param3"; + m_LA4="Param4"; + m_LA5="Param5"; + m_LA6="Param6"; + + int i; + + m_Trigger2.AddString(""); + for(i=0;iDeleteString(0)!=CB_ERR); + if(ini.sections.find("Waypoints")!=ini.sections.end()) + { + for(i=0;iAddString(*ini.sections["Waypoints"].GetValueName(i)); + } + } + + + if(sel==-1 || m_Trigger.SetCurSel(sel)==FALSE) + { + m_Trigger.SetCurSel(0); + } + if(selat==-1 || m_Trigger.SetCurSel(selat)==FALSE) + { + m_Action.SetCurSel(0); + } + if(selev==-1 || m_Trigger.SetCurSel(selev)==FALSE) + { + m_Event.SetCurSel(0); + } + + OnSelchangeTrigger(); + +} + +void CTriggers::OnSelchangeTrigger() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + + while(m_Action.DeleteString(0)!=CB_ERR); + while(m_Event.DeleteString(0)!=CB_ERR); + + CString TriggerData, EventData, ActionData; + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + TriggerData=ini.sections["Triggers"].values[CurrentTrigger]; + EventData=ini.sections["Events"].values[CurrentTrigger]; + ActionData=ini.sections["Actions"].values[CurrentTrigger]; + + m_Name=GetParam(TriggerData, 2); + m_House.SetWindowText(TranslateHouse(GetParam(TriggerData,0), TRUE)); + + + CString trig2=GetParam(TriggerData,1); + if(ini.sections["Triggers"].values.find(trig2)!=ini.sections["Triggers"].values.end()) + { + trig2+=" ("; + trig2+=GetParam( ini.sections["Triggers"].values[GetParam(TriggerData,1)],2); + trig2+=")"; + } + m_Trigger2.SetWindowText(trig2); + + m_F1=GetParam(TriggerData,3); + m_F2=GetParam(TriggerData,4); + m_F3=GetParam(TriggerData,5); + m_F4=GetParam(TriggerData,6); + m_F5=GetParam(TriggerData,7); + + + // okay, now list all events and actions + // ------------------------------------- + int i; + + // events + for(i=0;iGetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int selev=m_Event.GetCurSel(); + if(selev<0) return; + + + int i; + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + + CString EventData; + EventData=ini.sections["Events"].values[(LPCTSTR)CurrentTrigger]; + + int startpos=1+selev*3; + CString EventType=GetParam(EventData,startpos); + m_EventType.SetWindowText(EventType); + for(i=0;iGetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int selac=m_Action.GetCurSel(); + if(selac<0) return; + + int i; + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CString ActionData; + ActionData=ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger]; + + int startpos=1+selac*8; + CString ActionType=GetParam(ActionData,startpos); + m_ActionType.SetWindowText(ActionType); + for(i=0;iGetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CString house; + m_House.GetWindowText(house); + + house=TranslateHouse(house); + + ini.sections["Triggers"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Triggers"].values[(LPCTSTR)CurrentTrigger], 0, (LPCTSTR)house); +} + +void CTriggers::OnSelchangeHouse() +{ + CIniFile& ini=Map->GetIniFile(); + + int csel=m_House.GetCurSel(); + CString house; + m_House.GetLBText(csel,house); + m_House.SetWindowText(house); + + OnEditchangeHouse(); +} + +void CTriggers::OnChangeName() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(); + + CEdit& name=*(CEdit*)GetDlgItem(IDC_NAME); + + int esel=name.GetSel(); + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + + ini.sections["Triggers"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Triggers"].values[(LPCTSTR)CurrentTrigger], 2, (LPCTSTR)m_Name); + + UpdateDialog(); + + m_Trigger.SetCurSel(sel); + OnSelchangeTrigger(); + name.SetSel(esel); +} + +void CTriggers::OnChangeFlag1() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + + ini.sections["Triggers"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Triggers"].values[(LPCTSTR)CurrentTrigger], 3, (LPCTSTR)m_F1); + +} + +void CTriggers::OnChangeFlag2() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + + ini.sections["Triggers"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Triggers"].values[(LPCTSTR)CurrentTrigger], 4, (LPCTSTR)m_F2); + +} + +void CTriggers::OnChangeFlag3() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + + ini.sections["Triggers"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Triggers"].values[(LPCTSTR)CurrentTrigger], 5, (LPCTSTR)m_F3); + + +} + +void CTriggers::OnChangeFlag4() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + + ini.sections["Triggers"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Triggers"].values[(LPCTSTR)CurrentTrigger], 6, (LPCTSTR)m_F4); + +} + +void CTriggers::OnChangeFlag5() +{ + CIniFile& ini=Map->GetIniFile(); + + UpdateData(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + + ini.sections["Triggers"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Triggers"].values[(LPCTSTR)CurrentTrigger], 7, (LPCTSTR)m_F5); + +} + +void CTriggers::OnEditchangeTrigger2() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CString trg; + m_Trigger2.GetWindowText(trg); + TruncSpace(trg); + + ini.sections["Triggers"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Triggers"].values[(LPCTSTR)CurrentTrigger], 1, (LPCTSTR)trg); +} + +void CTriggers::OnSelchangeTrigger2() +{ + CIniFile& ini=Map->GetIniFile(); + + int csel=m_Trigger2.GetCurSel(); + CString trg; + m_Trigger2.GetLBText(csel,trg); + m_Trigger2.SetWindowText(trg); + OnEditchangeTrigger2(); +} + +void CTriggers::OnEditchangeEventtype() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int sel2=m_Event.GetCurSel(); + if(sel2<0) return; + + CString e1,e2; + m_E1.GetWindowText(e1); + m_E2.GetWindowText(e2); + while(m_E2.DeleteString(0)!=CB_ERR); + while(m_E1.DeleteString(0)!=CB_ERR); + m_E1.SetWindowText(e1); + m_E2.SetWindowText(e2); + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CString eventtype; + m_EventType.GetWindowText(eventtype); + TruncSpace(eventtype); + + int pos=1+3*sel2; + + ini.sections["Events"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Events"].values[(LPCTSTR)CurrentTrigger], pos, (LPCTSTR)eventtype); + + if(g_data.sections["Events"].FindName(eventtype)<0) return; + + + CString ptype[2]; + ptype[0]=GetParam(g_data.sections["Events"].values[eventtype],1); + ptype[1]=GetParam(g_data.sections["Events"].values[eventtype],2); + + int pListType[2]; + pListType[0]=atoi(GetParam(g_data.sections["ParamTypes"].values[ptype[0]], 1)); + pListType[1]=atoi(GetParam(g_data.sections["ParamTypes"].values[ptype[1]], 1)); + + int i; + for(i=0;i<2;i++) + { + CString* label; + if(i==0) label=&m_LE1; + if(i==1) label=&m_LE2; + CComboBox* cb; + if(i==0) cb=&m_E1; + if(i==1) cb=&m_E2; + + CString old_sel; + cb->GetWindowText(old_sel); + TruncSpace(old_sel); + + if(atoi(ptype[i])<0) + { + char c[50]; + itoa(abs(atoi(ptype[i])), c, 10); + cb->SetWindowText(c); + *label="Static"; + continue; + } + + *label=GetParam(g_data.sections["ParamTypes"].values[ptype[i]], 0); + + + + HandleParamList(*cb, pListType[i]); + + cb->SetWindowText(old_sel); + + int e; + for(e=0;eGetCount();e++) + { + CString tmp; + cb->GetLBText(e,tmp); + TruncSpace(tmp); + if(tmp==old_sel) + cb->SetCurSel(e); + } + + } + + + + + UpdateData(FALSE); + +} + + + +void CTriggers::OnSelchangeEventtype() +{ + int csel=m_EventType.GetCurSel(); + CString trg; + m_EventType.GetLBText(csel,trg); + m_EventType.SetWindowText(trg); + OnEditchangeEventtype(); + + +} + +void CTriggers::OnEditchangeEventparam1() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int sel2=m_Event.GetCurSel(); + if(sel2<0) return; + + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CString param1; + m_E1.GetWindowText(param1); + TruncSpace(param1); + + int pos=1+3*sel2+1; + + ini.sections["Events"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Events"].values[(LPCTSTR)CurrentTrigger], pos, (LPCTSTR)param1); + +} + +void CTriggers::OnSelchangeEventparam1() +{ + int csel=m_E1.GetCurSel(); + CString trg; + m_E1.GetLBText(csel,trg); + m_E1.SetWindowText(trg); + OnEditchangeEventparam1(); +} + +void CTriggers::OnEditchangeEventparam2() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int sel2=m_Event.GetCurSel(); + if(sel2<0) return; + + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CString param2; + m_E2.GetWindowText(param2); + TruncSpace(param2); + + int pos=1+3*sel2+2; + + ini.sections["Events"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Events"].values[(LPCTSTR)CurrentTrigger], pos, (LPCTSTR)param2); + +} + +void CTriggers::OnSelchangeEventparam2() +{ + int csel=m_E2.GetCurSel(); + CString trg; + m_E2.GetLBText(csel,trg); + m_E2.SetWindowText(trg); + OnEditchangeEventparam2(); +} + +void CTriggers::OnEditchangeActiontype() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int sel2=m_Action.GetCurSel(); + if(sel2<0) return; + + CString a; + m_A1.GetWindowText(a); + while(m_A1.DeleteString(0)!=CB_ERR); + m_A1.SetWindowText(a); + m_A2.GetWindowText(a); + while(m_A2.DeleteString(0)!=CB_ERR); + m_A2.SetWindowText(a); + m_A3.GetWindowText(a); + while(m_A3.DeleteString(0)!=CB_ERR); + m_A3.SetWindowText(a); + m_A4.GetWindowText(a); + while(m_A4.DeleteString(0)!=CB_ERR); + m_A4.SetWindowText(a); + m_A5.GetWindowText(a); + while(m_A5.DeleteString(0)!=CB_ERR); + m_A5.SetWindowText(a); + m_A6.GetWindowText(a); + while(m_A6.DeleteString(0)!=CB_ERR); + m_A6.SetWindowText(a); + + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CString actiontype; + m_ActionType.GetWindowText(actiontype); + TruncSpace(actiontype); + + int pos=1+8*sel2; + + ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger], pos, (LPCTSTR)actiontype); + + if(g_data.sections["Actions"].FindName(actiontype)<0) return; + + + CString ptype[6]; + ptype[0]=GetParam(g_data.sections["Actions"].values[actiontype],1); + ptype[1]=GetParam(g_data.sections["Actions"].values[actiontype],2); + ptype[2]=GetParam(g_data.sections["Actions"].values[actiontype],3); + ptype[3]=GetParam(g_data.sections["Actions"].values[actiontype],4); + ptype[4]=GetParam(g_data.sections["Actions"].values[actiontype],5); + ptype[5]=GetParam(g_data.sections["Actions"].values[actiontype],6); + + if(GetParam(g_data.sections["Actions"].values[actiontype],7)=="0") + m_LAW="Unused"; + else + m_LAW="Waypoint:"; + + int pListType[6]; + pListType[0]=atoi(GetParam(g_data.sections["ParamTypes"].values[ptype[0]], 1)); + pListType[1]=atoi(GetParam(g_data.sections["ParamTypes"].values[ptype[1]], 1)); + + + + int i; + for(i=0;i<6;i++) + { + CString* label; + if(i==0) label=&m_LA1; + if(i==1) label=&m_LA2; + if(i==2) label=&m_LA3; + if(i==3) label=&m_LA4; + if(i==4) label=&m_LA5; + if(i==5) label=&m_LA6; + CComboBox* cb; + if(i==0) cb=&m_A1; + if(i==1) cb=&m_A2; + if(i==2) cb=&m_A3; + if(i==3) cb=&m_A4; + if(i==4) cb=&m_A5; + if(i==5) cb=&m_A6; + + CString old_sel; + cb->GetWindowText(old_sel); + TruncSpace(old_sel); + + if(atoi(ptype[i])<0) + { + char c[50]; + itoa(abs(atoi(ptype[i])), c, 10); + cb->SetWindowText(c); + *label="Static"; + continue; + } + + *label = GetParam(g_data.sections["ParamTypes"].values[ptype[i]], 0); + + + + HandleParamList(*cb, pListType[i]); + + cb->SetWindowText(old_sel); + + int e; + for(e=0;eGetCount();e++) + { + CString tmp; + cb->GetLBText(e,tmp); + TruncSpace(tmp); + if(tmp==old_sel) + cb->SetCurSel(e); + } + + } +/* + + switch(atoi(actiontype)) + { + case 0: + case 23: + case 24: + case 46: + case 47: + m_LA1="Unused:"; + m_LA2="Unused:"; + m_LA3="Unused:"; + m_LA4="Unused:"; + m_LA5="Unused:"; + m_LA6="Unused:"; + break; + case 1: + case 2: + case 3: + case 6: + case 36: + case 74: + m_LA1="Unused:"; + m_LA2="House:"; + m_LA3="Unused:"; + m_LA4="Unused:"; + m_LA5="Unused:"; + m_LA6="Unused:"; + ListHouses(m_A2); + break; + + case 4: + m_LA1="Unknown =1:"; + m_LA2="TeamType:"; + m_LA3="Unused:"; + m_LA4="Unused:"; + m_LA5="Unused:"; + m_LA6="Unused:"; + m_A1.SetWindowText("1"); + OnEditchangeActionparam1(); + ListTeamTypes(m_A2); + break; + case 5: + m_LA1="Unused?:"; + m_LA2="TeamType:"; + m_LA3="Unused:"; + m_LA4="Unused:"; + m_LA5="Unused:"; + m_LA6="Unused:"; + ListTeamTypes(m_A2); + break; + + case 7: + m_LA1="Unknown =1:"; + m_LA2="TeamType:"; + m_LA3="Unused:"; + m_LA4="Unused:"; + m_LA5="Unused:"; + m_LA6="Unused:"; + m_A1.SetWindowText("1"); + OnEditchangeActionparam1(); + ListTeamTypes(m_A2); + break; + case 8: + case 17: + case 18: + m_LA1="Unused:"; + m_LA2="Waypoint:"; + m_LA3="Unused:"; + m_LA4="Unused:"; + m_LA5="Unused:"; + m_LA6="Unused:"; + ListWaypoints(m_A2); + break; + + case 27: + m_LA1="Unused:"; + m_LA2="Duration:"; + m_LA3="Unused:"; + m_LA4="Unused:"; + m_LA5="Unused:"; + m_LA6="Unused:"; + break; + case 43: + m_LA1="Unused:"; + m_LA2="Unknown:"; + m_LA3="Unused:"; + m_LA4="Unused:"; + m_LA5="Unused:"; + m_LA6="Unused:"; + m_A2.SetWindowText("7"); + OnEditchangeActionparam2(); + break; + case 44: + m_LA1="Unused:"; + m_LA2="Duration:"; + m_LA3="Unused:"; + m_LA4="Unused:"; + m_LA5="Unused:"; + m_LA6="Unused:"; + break; + case 48: + m_LA1="Unused:"; + m_LA2="Speed:"; + m_LA3="Unused:"; + m_LA4="Unused:"; + m_LA5="Unused:"; + m_LA6="Unused:"; + break; + case 55: + m_LA1="Unused:"; + m_LA2="Unknown:"; + m_LA3="Unused:"; + m_LA4="Unused:"; + m_LA5="Unused:"; + m_LA6="Unused:"; + m_A2.SetWindowText("1"); + OnEditchangeActionparam2(); + break; + case 56: + m_LA1="Unused:"; + m_LA2="Global:"; + m_LA3="Unused:"; + m_LA4="Unused:"; + m_LA5="Unused:"; + m_LA6="Unused:"; + break; + case 58: + m_LA1="Unused:"; + m_LA2="Size:"; + m_LA3="Unused:"; + m_LA4="Unused:"; + m_LA5="Unused:"; + m_LA6="Unused:"; + break; + default: + m_LA1="Param1:"; + m_LA2="Param2:"; + m_LA3="Param3:"; + m_LA4="Param4:"; + m_LA5="Param5:"; + m_LA6="Param6:"; + } +*/ + + UpdateData(FALSE); + +} + +void CTriggers::OnSelchangeActiontype() +{ + int csel=m_ActionType.GetCurSel(); + CString trg; + m_ActionType.GetLBText(csel,trg); + m_ActionType.SetWindowText(trg); + OnEditchangeActiontype(); +} + +void CTriggers::OnEditchangeActionwaypoint() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int sel2=m_Action.GetCurSel(); + if(sel2<0) return; + + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CString waypoint; + m_ActionWaypoint.GetWindowText(waypoint); + TruncSpace(waypoint); + + waypoint=GetWaypoint(atoi(waypoint)); + + int pos=1+8*sel2+7; + + ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger], pos, (LPCTSTR)waypoint); + +} + +void CTriggers::OnSelchangeActionwaypoint() +{ + int csel=m_ActionWaypoint.GetCurSel(); + CString trg; + m_ActionWaypoint.GetLBText(csel,trg); + m_ActionWaypoint.SetWindowText(trg); + OnEditchangeActionwaypoint(); +} + +void CTriggers::OnEditchangeActionparam1() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int sel2=m_Action.GetCurSel(); + if(sel2<0) return; + + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CString p1; + m_A1.GetWindowText(p1); + TruncSpace(p1); + + int pos=1+8*sel2+1; + + ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger], pos, (LPCTSTR)p1); + +} + +void CTriggers::OnSelchangeActionparam1() +{ + int csel=m_A1.GetCurSel(); + CString trg; + m_A1.GetLBText(csel,trg); + m_A1.SetWindowText(trg); + OnEditchangeActionparam1(); +} + +void CTriggers::OnEditchangeActionparam2() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int sel2=m_Action.GetCurSel(); + if(sel2<0) return; + + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CString p2; + m_A2.GetWindowText(p2); + TruncSpace(p2); + + int pos=1+8*sel2+2; + + ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger], pos, (LPCTSTR)p2); + +} + +void CTriggers::OnSelchangeActionparam2() +{ + int csel=m_A2.GetCurSel(); + CString trg; + m_A2.GetLBText(csel,trg); + m_A2.SetWindowText(trg); + OnEditchangeActionparam2(); +} + +void CTriggers::OnEditchangeActionparam3() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int sel2=m_Action.GetCurSel(); + if(sel2<0) return; + + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CString p3; + m_A3.GetWindowText(p3); + TruncSpace(p3); + + int pos=1+8*sel2+3; + + ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger], pos, (LPCTSTR)p3); + +} + +void CTriggers::OnSelchangeActionparam3() +{ + int csel=m_A3.GetCurSel(); + CString trg; + m_A3.GetLBText(csel,trg); + m_A3.SetWindowText(trg); + OnEditchangeActionparam3(); +} + +void CTriggers::OnEditchangeActionparam4() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int sel2=m_Action.GetCurSel(); + if(sel2<0) return; + + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CString p4; + m_A4.GetWindowText(p4); + TruncSpace(p4); + + int pos=1+8*sel2+4; + + ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger], pos, (LPCTSTR)p4); + +} + +void CTriggers::OnSelchangeActionparam4() +{ + int csel=m_A4.GetCurSel(); + CString trg; + m_A4.GetLBText(csel,trg); + m_A4.SetWindowText(trg); + OnEditchangeActionparam4(); +} + +void CTriggers::OnEditchangeActionparam5() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int sel2=m_Action.GetCurSel(); + if(sel2<0) return; + + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CString p5; + m_A5.GetWindowText(p5); + TruncSpace(p5); + + int pos=1+8*sel2+5; + + ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger], pos, (LPCTSTR)p5); + +} + +void CTriggers::OnSelchangeActionparam5() +{ + int csel=m_A5.GetCurSel(); + CString trg; + m_A5.GetLBText(csel,trg); + m_A5.SetWindowText(trg); + OnEditchangeActionparam5(); +} + +void CTriggers::OnEditchangeActionparam6() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int sel2=m_Action.GetCurSel(); + if(sel2<0) return; + + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CString p6; + m_A6.GetWindowText(p6); + TruncSpace(p6); + + int pos=1+8*sel2+6; + + ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger]=SetParam(ini.sections["Actions"].values[(LPCTSTR)CurrentTrigger], pos, (LPCTSTR)p6); + +} + +void CTriggers::OnSelchangeActionparam6() +{ + int csel=m_A6.GetCurSel(); + CString trg; + m_A6.GetLBText(csel,trg); + m_A6.SetWindowText(trg); + OnEditchangeActionparam6(); +} + +void CTriggers::OnAddevent() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CIniFileSection& sec=ini.sections["Events"]; + + int cval=atoi(GetParam(sec.values[(LPCTSTR)CurrentTrigger],0)); + cval++; + char c[50]; + itoa(cval,c,10); + + sec.values[(LPCTSTR)CurrentTrigger]=SetParam(sec.values[(LPCTSTR)CurrentTrigger],0,c); + sec.values[(LPCTSTR)CurrentTrigger]+=",13,0,0"; + + + UpdateDialog(); + + m_Trigger.SetCurSel(sel); + OnSelchangeTrigger(); + m_Event.SetCurSel(cval-1); + OnSelchangeEvent(); + +} + +void CTriggers::OnDeleteevent() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int sel2=m_Event.GetCurSel(); + if(sel2<0) return; + if(MessageBox("Do you really want to delete this event?","Delete event", MB_YESNO)==IDNO) return; + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CIniFileSection& sec=ini.sections["Events"]; + + CString data; + data=sec.values[(LPCTSTR)CurrentTrigger]; + + int v=atoi(GetParam(data,0)); + char c[50]; + v--; + itoa(v,c,10); + data=SetParam(data,0, c); + + int pos=1+sel2*3; + int posc=1+v*3; + int i; + for(i=0;i<3;i++) + data=SetParam(data,pos+i, GetParam(data,posc+i)); + + char* cupos=(char*)(LPCTSTR)data; + for(i=0;iGetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CIniFileSection& sec=ini.sections["Actions"]; + + int cval=atoi(GetParam(sec.values[(LPCTSTR)CurrentTrigger],0)); + cval++; + char c[50]; + itoa(cval,c,10); + + sec.values[(LPCTSTR)CurrentTrigger]=SetParam(sec.values[(LPCTSTR)CurrentTrigger],0,c); + sec.values[(LPCTSTR)CurrentTrigger]+=",0,0,0,0,0,0,0,A"; + + + UpdateDialog(); + + m_Trigger.SetCurSel(sel); + OnSelchangeTrigger(); + m_Action.SetCurSel(cval-1); + OnSelchangeAction(); +} + +void CTriggers::OnDeleteaction() +{ + CIniFile& ini=Map->GetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + int sel2=m_Action.GetCurSel(); + if(sel2<0) return; + if(MessageBox("Do you really want to delete this action?","Delete action", MB_YESNO)==IDNO) return; + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + CIniFileSection& sec=ini.sections["Actions"]; + + CString data; + data=sec.values[(LPCTSTR)CurrentTrigger]; + + int v=atoi(GetParam(data,0)); + char c[50]; + v--; + itoa(v,c,10); + data=SetParam(data,0, c); + + int pos=1+sel2*8; + int posc=1+v*8; + int i; + for(i=0;i<3;i++) + data=SetParam(data,pos+i, GetParam(data,posc+i)); + + char* cupos=(char*)(LPCTSTR)data; + for(i=0;iGetIniFile(); + + int sel=m_Trigger.GetCurSel(); + if(sel<0) return; + + if(MessageBox("Do you really want to delete this trigger? Don´t forget to delete the attached tag (important!)","Delete trigger", MB_YESNO)==IDNO) return; + + CString CurrentTrigger; + m_Trigger.GetLBText(sel, CurrentTrigger); + TruncSpace(CurrentTrigger); + + ini.sections["Triggers"].values.erase((LPCTSTR)CurrentTrigger); + ini.sections["Events"].values.erase((LPCTSTR)CurrentTrigger); + ini.sections["Actions"].values.erase((LPCTSTR)CurrentTrigger); + + //UpdateDialog(); + ((CFinalSunDlg*)theApp.m_pMainWnd)->UpdateDialogs(TRUE); +} + +void CTriggers::OnAddtrigger() +{ + CIniFile& ini=Map->GetIniFile(); + + CString ID_T=GetFreeID(); + ini.sections["Triggers"].values[ID_T]="GDI,,New trigger,0,1,1,1,0"; + ini.sections["Events"].values[ID_T]="0"; + ini.sections["Actions"].values[ID_T]="0"; + + if(MessageBox("Trigger created. If you want to create a simple tag now, press Yes. The tag will be called ""New tag"", you should name it like the trigger (after you have set up the trigger).","Trigger created",MB_YESNO)) + { + CString ID_TAG=GetFreeID(); + ini.sections["Tags"].values[ID_TAG]="0,New tag,"; + ini.sections["Tags"].values[ID_TAG]+=ID_T; + } + + //UpdateDialog(); + ((CFinalSunDlg*)theApp.m_pMainWnd)->UpdateDialogs(TRUE); + +} + + diff --git a/MissionEditor/Triggers.h b/MissionEditor/Triggers.h new file mode 100644 index 0000000..451e6dd --- /dev/null +++ b/MissionEditor/Triggers.h @@ -0,0 +1,140 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_TRIGGERS_H__1E811180_939D_11D3_B63B_F94AB129C441__INCLUDED_) +#define AFX_TRIGGERS_H__1E811180_939D_11D3_B63B_F94AB129C441__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Triggers.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CTriggers + +class CTriggers : public CDialog +{ + DECLARE_DYNCREATE(CTriggers) + +// Konstruktion +public: + void UpdateDialog(); + CTriggers(); + ~CTriggers(); + +// Dialogfelddaten + //{{AFX_DATA(CTriggers) + enum { IDD = IDD_TRIGGERS }; + CComboBox m_E2; + CComboBox m_E1; + CComboBox m_A6; + CComboBox m_A5; + CComboBox m_A4; + CComboBox m_A3; + CComboBox m_A2; + CComboBox m_A1; + CComboBox m_House; + CComboBox m_Trigger2; + CComboBox m_Trigger; + CComboBox m_EventType; + CComboBox m_Event; + CComboBox m_ActionWaypoint; + CComboBox m_ActionType; + CComboBox m_Action; + CString m_F1; + CString m_F2; + CString m_F3; + CString m_F4; + CString m_F5; + CString m_LA1; + CString m_LA2; + CString m_LA3; + CString m_LA4; + CString m_LA5; + CString m_LA6; + CString m_LE1; + CString m_LE2; + CString m_Name; + CString m_LAW; + //}}AFX_DATA + + +// Ăœberschreibungen + // Der Klassen-Assistent generiert virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CTriggers) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CTriggers) + afx_msg void OnSelchangeTrigger(); + afx_msg void OnSelchangeEvent(); + afx_msg void OnSelchangeAction(); + afx_msg void OnEditchangeHouse(); + afx_msg void OnSelchangeHouse(); + afx_msg void OnChangeName(); + afx_msg void OnChangeFlag1(); + afx_msg void OnChangeFlag2(); + afx_msg void OnChangeFlag3(); + afx_msg void OnChangeFlag4(); + afx_msg void OnChangeFlag5(); + afx_msg void OnEditchangeTrigger2(); + afx_msg void OnSelchangeTrigger2(); + afx_msg void OnEditchangeEventtype(); + afx_msg void OnSelchangeEventtype(); + afx_msg void OnEditchangeEventparam1(); + afx_msg void OnSelchangeEventparam1(); + afx_msg void OnEditchangeEventparam2(); + afx_msg void OnSelchangeEventparam2(); + afx_msg void OnEditchangeActiontype(); + afx_msg void OnSelchangeActiontype(); + afx_msg void OnEditchangeActionwaypoint(); + afx_msg void OnSelchangeActionwaypoint(); + afx_msg void OnEditchangeActionparam1(); + afx_msg void OnSelchangeActionparam1(); + afx_msg void OnEditchangeActionparam2(); + afx_msg void OnSelchangeActionparam2(); + afx_msg void OnEditchangeActionparam3(); + afx_msg void OnSelchangeActionparam3(); + afx_msg void OnEditchangeActionparam4(); + afx_msg void OnSelchangeActionparam4(); + afx_msg void OnEditchangeActionparam5(); + afx_msg void OnSelchangeActionparam5(); + afx_msg void OnEditchangeActionparam6(); + afx_msg void OnSelchangeActionparam6(); + afx_msg void OnAddevent(); + afx_msg void OnDeleteevent(); + afx_msg void OnAddaction(); + afx_msg void OnDeleteaction(); + afx_msg void OnDeletetrigger(); + afx_msg void OnAddtrigger(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_TRIGGERS_H__1E811180_939D_11D3_B63B_F94AB129C441__INCLUDED_ diff --git a/MissionEditor/Tube.cpp b/MissionEditor/Tube.cpp new file mode 100644 index 0000000..dfa5a40 --- /dev/null +++ b/MissionEditor/Tube.cpp @@ -0,0 +1,363 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "StdAfx.h" +#include "Tube.h" +#include + +#include "inlines.h" + +#ifndef __INTELLISENSE__ +// This file had problems with Intellisense. Until this is fixed, deactivate intellisense parsing here. + +int sgn(int v) +{ + if (v < 0) return -1; + return v > 0 ? 1 : 0; +} + +CTube::CTube(std::uint16_t tubeID, std::uint16_t startX, std::uint16_t startY, ETubeDirection direction, std::uint16_t endX, std::uint16_t endY, const std::vector& tubeParts): + CTube(startX, startY, direction, endX, endY, tubeParts) +{ + m_tubeId = tubeID; +} + +CTube::CTube(const std::uint16_t startX, const std::uint16_t startY, const ETubeDirection direction, const std::uint16_t endX, const std::uint16_t endY, const std::vector& tubeParts): + CTube() +{ + m_startX = startX; + m_startY = startY; + m_direction = direction; + m_endX = endX; + m_endY = endY; + m_tubeParts = tubeParts; +} + +CTube::CTube(std::uint16_t tubeId, const std::string& value): + m_tubeId(tubeId) +{ + m_startY = stoi(GetParam(value, 0)); + m_startX = stoi(GetParam(value, 1)); + m_direction = ToTubeDirection(stoi(GetParam(value, 2))); + m_endY = stoi(GetParam(value, 3)); + m_endX = stoi(GetParam(value, 4)); + + std::string readDirS; + for (std::size_t e = 5; !(readDirS = GetParam(value, e)).empty(); ++e) + { + const auto readDir = stoi(readDirS); + m_tubeParts.push_back(ToTubeDirection(readDir)); + } + if (m_tubeParts.empty() || m_tubeParts.back() != ETubeDirection::Undefined) + m_tubeParts.push_back(ETubeDirection::Undefined); +} + +bool CTube::isValid() const +{ + return m_direction != ETubeDirection::Undefined && m_tubeParts.size() > 1; +} + +CTube CTube::reverse(std::uint16_t newTubeID) const +{ + CTube ti2; + + ti2.m_tubeId = newTubeID; + + ti2.m_startX = m_endX; + ti2.m_startY = m_endY; + ti2.m_endX = m_startX; + ti2.m_endY = m_startY; + + const auto last_d = getLastDirection(); + ti2.m_direction = opposite_dir(last_d); + + auto x = m_startX; + auto y = m_startY; + + // reverse direction tube parts + auto reversed = m_tubeParts | + std::views::reverse | + std::views::transform([](auto dir) {return opposite_dir(dir);}) | + std::views::common; + + // find the first defined direction in the reversed list + auto reversedFirst = std::find_if(reversed.begin(), reversed.end(), [](ETubeDirection dir) { return dir != ETubeDirection::Undefined; }); + auto reversedSize = reversed.end() - reversedFirst; + ti2.m_tubeParts.reserve(reversed.size() + 2); + ti2.m_tubeParts.assign(reversedFirst, reversed.end()); + ti2.m_tubeParts.push_back(ETubeDirection::Undefined); + + return ti2; +} + +static const ETubeDirection kDiffToDir[3][3] = { + {ETubeDirection::TopLeft, ETubeDirection::Top, ETubeDirection::TopRight}, // xadd == -1 + {ETubeDirection::Left, ETubeDirection::Undefined, ETubeDirection::Right}, // xadd == 0 + {ETubeDirection::BottomLeft, ETubeDirection::Bottom, ETubeDirection::BottomRight} // xadd == 1 +}; + +bool CTube::isEqual(const CTube& r, bool ignoreId) const +{ + if (!ignoreId) + return *this == r; + + const auto& largerTubeParts = r.m_tubeParts.size() >= m_tubeParts.size() ? r.m_tubeParts : m_tubeParts; + const auto& smallerTubeParts = r.m_tubeParts.size() < m_tubeParts.size() ? r.m_tubeParts : m_tubeParts; + for (auto i = 0; i < smallerTubeParts.size(); ++i) + { + if (largerTubeParts[i] != smallerTubeParts[i]) + return false; + } + for (auto i = smallerTubeParts.size(); i < largerTubeParts.size(); ++i) + { + if (largerTubeParts[i] != ETubeDirection::Undefined) + return false; + } + + return m_direction == r.m_direction && m_startX == r.m_startX && m_startY == r.m_startY && r.m_endX == r.m_endX && r.m_endY == r.m_endY; +} + +CTube CTube::autocreate(std::uint16_t startX, std::uint16_t startY, std::uint16_t endX, std::uint16_t endY, int straightStartParts) +{ + CTube ti; + ti.m_startX = startX; + ti.m_startY = startY; + ti.m_endX = startX; + ti.m_endY = startY; + ti.append(endX, endY, straightStartParts); + return ti; + + /* + int curx = startX; + int cury = startY; + + CTube ti; + ti.m_startX = startX; + ti.m_startY = startY; + ti.m_endX = endX; + ti.m_endY = endY; + + + + int xadd = sgn(endX - curx); + int yadd = sgn(endY - cury); + if (straightStartTiles > 0) + { + const bool xMajor = abs(endX - startX) > abs(endY - startY); + xadd = xMajor ? xadd : 0; + yadd = xMajor ? 0 : yadd; + } + + curx += xadd; + cury += yadd; + ti.m_direction = kDiffToDir[xadd + 1][yadd + 1]; + + int n = 1; + while (endX != curx || endY != cury) + { + xadd = n < straightStartTiles ? xadd : sgn(endX - curx); // keep initial direction for straightStartTiles + yadd = n < straightStartTiles ? yadd : sgn(endY - cury); + n++; + curx += xadd; + cury += yadd; + ti.m_tubeParts.push_back(kDiffToDir[xadd + 1][yadd + 1]); + } + + ti.m_tubeParts.push_back(ETubeDirection::Undefined); + return ti; + */ +} + +ETubeDirection opposite_dir(const ETubeDirection dir) +{ + static const ETubeDirection opposite_dir_tbl[8] = { + ETubeDirection::Bottom, + ETubeDirection::BottomLeft, + ETubeDirection::Left, + ETubeDirection::TopLeft, + ETubeDirection::Top, + ETubeDirection::TopRight, + ETubeDirection::Right, + ETubeDirection::BottomRight + }; + const auto iDir = to_int(dir); + if (iDir < 0 || iDir > 7) + return ETubeDirection::Undefined; + return opposite_dir_tbl[iDir]; +} + + +bool dir_to_xy(ETubeDirection dir, MapVec& vec) +{ + static int dir_to_xy_table[8][2] = { + {0, -1}, // 0 + {1, -1}, // 1 + {1, 0}, // 2 + {1, 1}, // 3 + {0, 1}, // 4 + {-1, 1}, // 5 + {-1, 0}, // 6 + {-1, -1}, // 7 + }; + const auto iDir = to_int(dir); + if (iDir < 0 || iDir > 7) + { + vec.x = 0; + vec.y = 0; + return false; + } + vec.x = dir_to_xy_table[iDir][1]; // swap x/y + vec.y = dir_to_xy_table[iDir][0]; + return true; +} + +ETubeDirection CTube::getLastDirection() const +{ + if (m_tubeParts.empty()) + return m_direction; + auto last = std::find_if(m_tubeParts.crbegin(), m_tubeParts.crend(), [](ETubeDirection dir) { return dir != ETubeDirection::Undefined; }); + return last == m_tubeParts.crend() ? m_direction : *last; +} + +bool CTube::touches(const MapCoords& mc) const +{ + bool touches = false; + walk([this, &mc, &touches](const auto& wi) { + if (wi.pos == mc) + { + touches = true; + return false; + } + return true; + }); + return touches; +} + +std::string CTube::toString() const +{ + auto partsAsInt = m_tubeParts | std::views::transform([](auto dir) {return to_int(dir); }) | std::views::common; + + std::vector values; + values.reserve(5 + m_tubeParts.size()); + values.assign({ m_startY, m_startX, to_int(m_direction), m_endY, m_endX }); + values.insert(values.end(), partsAsInt.begin(), partsAsInt.end()); + + std::string res = Join(",", values | std::views::transform([](auto v) {return std::to_string(v); })); + if (m_tubeParts.empty() || m_tubeParts.back() != ETubeDirection::Undefined) + res += ",-1"; // TS/RA2 crash when no delimiter exists + return res; +} + +bool CTube::append(std::uint16_t endX, std::uint16_t endY, int forceStraightParts) +{ + auto newTubeParts = m_tubeParts; + MapCoords end(endX, endY); + + // remove delimiters + auto oldLast = std::find(newTubeParts.begin(), newTubeParts.end(), ETubeDirection::Undefined); + newTubeParts.resize(oldLast - newTubeParts.begin()); + + // now find current x/y + MapCoords cur = getStartCoords(); + std::vector existingPositions; + if(!walk([&cur, &existingPositions](const WalkInfo& wi) { + cur = wi.pos; + existingPositions.push_back(wi.pos); + return true; + })) + return false; + + // if no enter direction was given, set it now - this should only be true if there are no existingPositions + if (m_direction == ETubeDirection::Undefined) + { + const bool xMajor = abs(end.x - m_startX) > abs(end.y - m_startY); + MapVec add(sgn(end.x - m_startX), sgn(end.y - m_startY)); + add.x = xMajor ? add.x : 0; + add.y = xMajor ? 0 : add.y; + m_direction = kDiffToDir[add.x + 1][add.y + 1]; + } + + auto endOnExistingIt = std::find(existingPositions.begin(), existingPositions.end(), end); + if (endOnExistingIt != existingPositions.end()) + { + if (endOnExistingIt == existingPositions.begin()) + return false; // zero length remaining + + // shorten + auto remaining = endOnExistingIt - existingPositions.begin(); + newTubeParts.resize(remaining); + newTubeParts.push_back(ETubeDirection::Undefined); + m_endX = end.x; + m_endY = end.y; + m_tubeParts = std::move(newTubeParts); + return true; + } + + int n = 0; + while (end != cur) + { + MapVec add(sgn(end.x - cur.x), sgn(end.y - cur.y)); + if (newTubeParts.size() < 1 && forceStraightParts < 0) + { + // the first tube part should be in the same direction as the enter direction + dir_to_xy(m_direction, add); + } + if (n++ < forceStraightParts) + { + const bool xMajorPart = abs(end.x - m_endX) > abs(end.y - m_endY); + add.x = xMajorPart ? add.x : 0; + add.y = xMajorPart ? 0 : add.y; + } + cur += add; + //if (std::find(existingPositions.begin(), existingPositions.end(), std::make_pair(curX, curY)) != existingPositions.end()) + // return false; // intersection - maybe shorten? maybe we can even allow it if TS accepts it? + newTubeParts.push_back(kDiffToDir[add.x + 1][add.y + 1]); + } + + newTubeParts.push_back(ETubeDirection::Undefined); + m_endX = cur.x; + m_endY = cur.y; + m_tubeParts = std::move(newTubeParts); + + return true; +} + +bool CTube::walk(const std::function& walker) const +{ + MapVec diff; + WalkInfo wi; + wi.pos = MapCoords(m_startX, m_startY); + + for (auto dir : m_tubeParts) + { + wi.direction = dir; + dir_to_xy(wi.direction, diff); + wi.next_pos = (wi.direction == ETubeDirection::Undefined) ? MapCoords(-1, -1) : wi.pos + diff; + if (!walker(wi)) + return false; + if (wi.direction == ETubeDirection::Undefined) + break; + wi.pos = wi.next_pos; + } + return true; +} + + +#endif \ No newline at end of file diff --git a/MissionEditor/Tube.h b/MissionEditor/Tube.h new file mode 100644 index 0000000..dfdcbc6 --- /dev/null +++ b/MissionEditor/Tube.h @@ -0,0 +1,144 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#pragma once + +#include +#include +#include +#include "Structs.h" + +enum class ETubeDirection : char +{ + Undefined = -1, + Top=0, + TopRight=1, + Right=2, + BottomRight=3, + Bottom=4, + BottomLeft=5, + Left=6, + TopLeft=7, +}; + +inline ETubeDirection ToTubeDirection(const std::underlying_type_t dir) +{ + if (dir > 7 || dir < -1) + return ETubeDirection::Undefined; + return static_cast(dir); +} + +inline auto to_int(const ETubeDirection dir) +{ + return static_cast>(dir); +} + +ETubeDirection opposite_dir(ETubeDirection dir); +bool dir_to_xy(ETubeDirection dir, MapVec& y); + +class CTube +{ +public: + struct WalkInfo + { + MapCoords pos; + ETubeDirection direction = ETubeDirection::Undefined; + MapCoords next_pos; + }; + +public: + CTube() = default; + CTube(std::uint16_t tubeId, const std::string& s); + CTube( + std::uint16_t tubeID, + std::uint16_t startX, + std::uint16_t startY, + ETubeDirection direction, + std::uint16_t endX, + std::uint16_t endY, + const std::vector& tubeParts + ); + CTube( + std::uint16_t startX, + std::uint16_t startY, + ETubeDirection direction, + std::uint16_t endX, + std::uint16_t endY, + const std::vector& tubeParts + ); + + CTube reverse(std::uint16_t newTubeID=0xFFFF) const; + + // full equivalency including id + bool operator==(const CTube& r) const = default; + + bool isEqual(const CTube& r, bool ignoreId) const; + + // Create tube with simple algorithm + static CTube autocreate(std::uint16_t startX, std::uint16_t startY, std::uint16_t endX, std::uint16_t endY, int straightStartParts=1); + + + const std::vector& GetTubeParts() const + { + return m_tubeParts; + } + + void setId(std::uint16_t id) + { + m_tubeId = id; + } + + bool isCounterpart(const CTube& other) const + { + return getStartCoords() == other.getEndCoords() && getEndCoords() == other.getStartCoords(); + } + + bool hasId() const + { + return m_tubeId != 0xFFFF; + } + auto getId() const { return m_tubeId; } + auto getStartX() const { return m_startX; } + auto getStartY() const { return m_startY; } + MapCoords getStartCoords() const { return MapCoords(m_startX, m_startY); } + auto getInitialDirection() const { return m_direction; } + ETubeDirection getLastDirection() const; + auto getEndX() const { return m_endX; } + auto getEndY() const { return m_endY; } + MapCoords getEndCoords() const { return MapCoords(m_endX, m_endY); } + + bool touches(const MapCoords& mc) const; + + std::string toString() const; + + bool append(std::uint16_t endX, std::uint16_t endY, int forceStraightParts=-1); + + bool walk(const std::function& walker) const; + + bool isValid() const; + +private: + std::uint16_t m_tubeId = 0xFFFF; // ID of tube + std::uint16_t m_startX = 0; + std::uint16_t m_startY = 0; + ETubeDirection m_direction = ETubeDirection::Undefined; + std::uint16_t m_endX = 0; + std::uint16_t m_endY = 0; + std::vector m_tubeParts; +}; \ No newline at end of file diff --git a/MissionEditor/TubeTool.cpp b/MissionEditor/TubeTool.cpp new file mode 100644 index 0000000..5c9c8ff --- /dev/null +++ b/MissionEditor/TubeTool.cpp @@ -0,0 +1,251 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "StdAfx.h" +#include "TubeTool.h" +#include "MapData.h" +#include "IsoView.h" +#include "Structs.h" +#include "inlines.h" +#include +#include + +std::unique_ptr findTubeEndAt(const MapCoords& mapCoords3d, const ProjectedCoords& projCoords, const CMapData& map) +{ + const auto& tubes = map.GetTubes(); + auto it = std::find_if(tubes.begin(), tubes.end(), [mapCoords3d](const auto& tube) { return tube->getEndCoords() == mapCoords3d; }); + if (it != tubes.end()) + return std::make_unique(**it); + // if not found, also try with z - 4 (e.g. behind cliffs) + auto backMapCoords = map.ToMapCoords3d(projCoords, map.GetHeightAt(mapCoords3d) - 4); + it = std::find_if(tubes.begin(), tubes.end(), [backMapCoords](const auto& tube) { return tube->getEndCoords() == backMapCoords; }); + if (it != tubes.end()) + return std::make_unique(**it); + return nullptr; +} + +std::vector findTubesAt(const ProjectedCoords& projCoords, const CMapData& map) +{ + std::vector foundTubes; + for (auto& t : map.GetTubes()) + { + auto coords = map.ToMapCoords3d(projCoords, map.GetHeightAt(t->getStartCoords())); + if (t->touches(coords)) + foundTubes.push_back(t->getId()); + } + return foundTubes; +} + +AddTubeTool::AddTubeTool(CMapData& map, CIsoView& view, bool bidirectional): MapTool(map, view), + m_bidirectional(bidirectional) +{ + +} + +void AddTubeTool::finish() +{ + if (m_tube) { + if (m_tube->isValid()) + { + getMap().SetTube(m_tube.get()); + if (m_bidirectional) + { + auto t2 = m_tube->reverse(); + getMap().SetTube(&t2); + } + } + getView().RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + m_mm_tube.reset(); + m_tube.reset(); + m_modified_tubes.clear(); +} + +bool AddTubeTool::onRButtonUp(const ProjectedCoords& projCoords, const MapCoords& mapCoords3d, MapToolMouseFlags flags) +{ + if (!m_modified_tubes.empty()) + { + // reset modified tubes to original state + for (auto& tube : m_modified_tubes) + { + getMap().SetTube(tube.get()); + } + } + bool ret = m_tube != nullptr; + m_mm_tube.reset(); + m_tube.reset(); + m_modified_tubes.clear(); + getView().RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + return ret; // if we were adding or modifying a tube, a right click should just cancel this current tube, not the whole tool +} + +void AddTubeTool::onLButtonDblClick(const ProjectedCoords& projCoords, const MapCoords& mapCoords3d, MapToolMouseFlags flags) +{ +} + +void AddTubeTool::onLButtonUp(const ProjectedCoords& projCoords, const MapCoords& mapCoords3d, MapToolMouseFlags flags) +{ + if (!m_tube) { + // first check if there is already a tube at the given location and take ownership if existing + auto tube = getTubeToModify(mapCoords3d, projCoords, flags); + if (tube) { + m_tube = std::move(tube); + + // also find reverse direction + if (m_bidirectional) + { + const auto& tubes = getMap().GetTubes(); + auto reversed = m_tube->reverse(); + auto reverseIt = std::find_if(tubes.begin(), tubes.end(), [&reversed](const auto& tube) { return tube->isEqual(reversed, true); }); + if (reverseIt != tubes.end()) + { + m_modified_tubes.push_back(std::make_unique(**reverseIt)); + getMap().DeleteTube((*reverseIt)->getId()); + } + } + m_modified_tubes.push_back(std::make_unique(*m_tube)); + getMap().DeleteTube(m_tube->getId()); + } + + if (!m_tube) { + // create a new tube, first click + m_tube = std::move(createNewTube(mapCoords3d)); + } + } + else + { + int z = getMap().GetHeightAt(m_tube->getStartCoords()); + auto mc = getMap().ToMapCoords3d(projCoords, z); + if (m_tube->getEndCoords() == MapCoords(mc.x, mc.y)) + { + finish(); + } + else + { + m_tube->append(mc.x, mc.y, m_tube->GetTubeParts().empty() ? 2 : 0); + } + + } + + getView().RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); +} + +std::unique_ptr AddTubeTool::createNewTube(const MapCoords& mapCoords3d) const +{ + return std::make_unique(mapCoords3d.x, mapCoords3d.y, ETubeDirection::Undefined, mapCoords3d.x, mapCoords3d.y, std::vector()); +} + +std::unique_ptr AddTubeTool::getTubeToModify(const MapCoords& mapCoords3d, const ProjectedCoords& projCoords, MapToolMouseFlags flags) const +{ + if ((flags & MapToolMouseFlags::SHIFT) == MapToolMouseFlags::SHIFT) + return findTubeEndAt(mapCoords3d, projCoords, getMap()); + return nullptr; +} + +void AddTubeTool::onMouseMove(const ProjectedCoords& projCoords, const MapCoords& mapCoords3d, MapToolMouseFlags flags) +{ + if (m_tube) { + m_mm_tube.reset(new CTube(*m_tube)); + int z = getMap().GetHeightAt(m_tube->getStartCoords()); + auto mc = getMap().ToMapCoords3d(projCoords, z); + m_mm_tube->append(mc.x, mc.y, m_tube->GetTubeParts().empty() ? 2 : 0); + getView().RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else + { + auto tube = getTubeToModify(mapCoords3d, projCoords, flags); + if (tube) + { + m_hover_tube = std::move(tube); + getView().RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + else if (m_hover_tube) + { + m_hover_tube.reset(); + getView().RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + } +} + +void AddTubeTool::render() +{ + if (m_mm_tube) + { + // mouse-move tube + getView().DrawTube(*m_mm_tube); + } + else if (m_tube) { + getView().DrawTube(*m_tube); + } + else if (m_hover_tube) + { + COLORREF col = RGB(0, 255, 0); + getView().DrawTube(*m_hover_tube, nullptr, &col); + } + +} + +RemoveTubeTool::RemoveTubeTool(CMapData& map, CIsoView& view) : MapTool(map, view) +{ +} + +void RemoveTubeTool::onMouseMove(const ProjectedCoords& projCoords, const MapCoords& mapCoords3d, MapToolMouseFlags flags) +{ + auto& m = getMap(); + std::vector tubes = findTubesAt(projCoords, getMap()); + + if ((flags & MapToolMouseFlags::LBUTTON) == MapToolMouseFlags::LBUTTON) + { + for (auto& id : tubes) + { + m.DeleteTube(id); + } + } + else + { + m_hover_tubes.reserve(tubes.size()); + std::transform(tubes.begin(), tubes.end(), std::back_inserter(m_hover_tubes), [this](std::uint16_t tubeId) { return std::make_unique(*getMap().GetTube(tubeId)); }); + } + getView().RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + m_hover_tubes.clear(); +} + +void RemoveTubeTool::render() +{ + for(auto& tube: m_hover_tubes) + { + COLORREF col = RGB(0, 255, 0); + getView().DrawTube(*tube, nullptr, &col); + } +} + +ModifyTubeTool::ModifyTubeTool(CMapData& map, CIsoView& view, bool bidirectional): AddTubeTool(map, view, bidirectional) +{ +} + +std::unique_ptr ModifyTubeTool::getTubeToModify(const MapCoords& mapCoords3d, const ProjectedCoords& projCoords, MapToolMouseFlags flags) const +{ + return findTubeEndAt(mapCoords3d, projCoords, getMap()); +} + +std::unique_ptr ModifyTubeTool::createNewTube(const MapCoords& mapCoords3d) const +{ + return nullptr; +} diff --git a/MissionEditor/TubeTool.h b/MissionEditor/TubeTool.h new file mode 100644 index 0000000..bb11779 --- /dev/null +++ b/MissionEditor/TubeTool.h @@ -0,0 +1,85 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include "MapTool.h" +#include +class CTube; + +class AddTubeTool: public MapTool +{ +public: + AddTubeTool(CMapData& map, CIsoView& view, bool bidirectional); + virtual ~AddTubeTool() = default; + + void finish(); + + virtual bool onRButtonUp(const ProjectedCoords& projCoords, const MapCoords& mapCoords3d, MapToolMouseFlags flags); + virtual void onLButtonDblClick(const ProjectedCoords& projCoords, const MapCoords& mapCoords3d, MapToolMouseFlags flags); + virtual void onLButtonUp(const ProjectedCoords& projCoords, const MapCoords& mapCoords3d, MapToolMouseFlags flags); + virtual void onMouseMove(const ProjectedCoords& projCoords, const MapCoords& mapCoords3d, MapToolMouseFlags flags); + virtual void render(); + +protected: + AddTubeTool& operator=(const AddTubeTool& other) = delete; + + virtual std::unique_ptr getTubeToModify(const MapCoords& mapCoords3d, const ProjectedCoords& projCoords, MapToolMouseFlags flags) const; + virtual std::unique_ptr createNewTube(const MapCoords& mapCoords3d) const; + +private: + std::unique_ptr m_tube; + std::unique_ptr m_mm_tube; + std::unique_ptr m_hover_tube; + std::vector> m_modified_tubes; + bool m_bidirectional; +}; + +class ModifyTubeTool : public AddTubeTool +{ +public: + ModifyTubeTool(CMapData& map, CIsoView& view, bool bidirectional); + virtual ~ModifyTubeTool() = default; + +protected: + ModifyTubeTool& operator=(const AddTubeTool& other) = delete; + + virtual std::unique_ptr getTubeToModify(const MapCoords& mapCoords3d, const ProjectedCoords& projCoords, MapToolMouseFlags flags) const; + virtual std::unique_ptr createNewTube(const MapCoords& mapCoords3d) const; + +private: +}; + +class RemoveTubeTool : public MapTool +{ +public: + RemoveTubeTool(CMapData& map, CIsoView& view); + virtual ~RemoveTubeTool() = default; + + virtual void onMouseMove(const ProjectedCoords& projCoords, const MapCoords& mapCoords3d, MapToolMouseFlags flags); + virtual void render(); + +protected: + RemoveTubeTool& operator=(const RemoveTubeTool& other) = delete; + +private: + std::vector> m_hover_tubes; +}; + diff --git a/MissionEditor/Unit.cpp b/MissionEditor/Unit.cpp new file mode 100644 index 0000000..42b716b --- /dev/null +++ b/MissionEditor/Unit.cpp @@ -0,0 +1,169 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Unit.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "Unit.h" +#include "resource.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CUnit + + +CUnit::CUnit(CWnd* pParent /*=NULL*/) + : CDialog(CUnit::IDD, pParent) +{ + //{{AFX_DATA_INIT(CUnit) + m_direction = _T(""); + m_flag1 = _T(""); + m_flag2 = _T(""); + m_house = _T(""); + m_flag3 = _T(""); + m_flag4 = _T(""); + m_flag5 = _T(""); + m_flag6 = _T(""); + m_action = _T(""); + m_tag = _T(""); + //}}AFX_DATA_INIT +} + + +void CUnit::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CUnit) + DDX_Control(pDX, IDC_STRENGTH, m_strength_ctrl); + DDX_CBString(pDX, IDC_DIRECTION, m_direction); + DDX_Text(pDX, IDC_P1, m_flag1); + DDX_Text(pDX, IDC_P2, m_flag2); + DDX_CBString(pDX, IDC_HOUSE, m_house); + DDX_Text(pDX, IDC_P3, m_flag3); + DDX_Text(pDX, IDC_P4, m_flag4); + DDX_Text(pDX, IDC_P5, m_flag5); + DDX_Text(pDX, IDC_P6, m_flag6); + DDX_CBString(pDX, IDC_STATE, m_action); + DDX_CBString(pDX, IDC_TAG, m_tag); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CUnit, CDialog) + //{{AFX_MSG_MAP(CUnit) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CUnit + +void CUnit::Init(CString house, CString strength, CString direction, CString action, CString tag, CString flag1, CString flag2, CString flag3, CString flag4, CString flag5, CString flag6) +{ + CIniFile& ini=Map->GetIniFile(); + + if(house=="") + { + m_house=*rules.sections["Houses"].GetValue(0); + if(ini.sections.find("Houses")!=ini.sections.end()) + if(ini.sections["Houses"].values.size()>0) + m_house=TranslateHouse(*ini.sections["Houses"].GetValue(0), TRUE); + } + else + m_house=TranslateHouse(house, TRUE); + + m_flag1=flag1; + m_flag2=flag2; + m_flag3=flag3; + m_flag4=flag4; + m_flag5=flag5; + m_flag6=flag6; + m_action=action; + m_strength=strength; + m_tag=tag; + m_direction=direction; +} + +BOOL CUnit::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // init the common (!) dialog things + int i; + CComboBox* house, *tag; + house=(CComboBox*)GetDlgItem(IDC_HOUSE); + tag=(CComboBox*)GetDlgItem(IDC_TAG); + + ListHouses(*house, FALSE); + ListTags(*tag,TRUE); + + + + UpdateData(FALSE); + m_strength_ctrl.SetRange(0,256); + m_strength_ctrl.SetPos(atoi(m_strength)); + + UpdateStrings(); + + return TRUE; +} + +void CUnit::OnOK() +{ + CDialog::OnOK(); + m_strength=GetText(&m_strength_ctrl); + UpdateData(); + TruncSpace(m_tag); + m_house=TranslateHouse(m_house); + + + +} + +void CUnit::UpdateStrings() +{ + + + SetWindowText(GetLanguageStringACP("UnitCap")); + SetDlgItemText(IDC_DESC, GetLanguageStringACP("UnitDesc")); + SetDlgItemText(IDC_LHOUSE, GetLanguageStringACP("UnitHouse")); + SetDlgItemText(IDC_LSTRENGTH, GetLanguageStringACP("UnitStrength")); + SetDlgItemText(IDC_LSTATE, GetLanguageStringACP("UnitState")); + SetDlgItemText(IDC_LDIRECTION, GetLanguageStringACP("UnitDirection")); + SetDlgItemText(IDC_LTAG, GetLanguageStringACP("UnitTag")); + SetDlgItemText(IDC_LP1, GetLanguageStringACP("UnitP1")); + SetDlgItemText(IDC_LP2, GetLanguageStringACP("UnitP2")); + SetDlgItemText(IDC_LP3, GetLanguageStringACP("UnitP3")); + SetDlgItemText(IDC_LP4, GetLanguageStringACP("UnitP4")); + SetDlgItemText(IDC_LP5, GetLanguageStringACP("UnitP5")); + SetDlgItemText(IDC_LP6, GetLanguageStringACP("UnitP6")); + + SetDlgItemText(IDOK, GetLanguageStringACP("OK")); + SetDlgItemText(IDCANCEL, GetLanguageStringACP("Cancel")); +} diff --git a/MissionEditor/Unit.h b/MissionEditor/Unit.h new file mode 100644 index 0000000..e191286 --- /dev/null +++ b/MissionEditor/Unit.h @@ -0,0 +1,80 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_UNIT_H__44A11CC3_84B6_11D3_B63B_F881F458F743__INCLUDED_) +#define AFX_UNIT_H__44A11CC3_84B6_11D3_B63B_F881F458F743__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Unit.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CUnit + +class CUnit : public CDialog +{ +// Konstruktion +public: + void UpdateStrings(); + CString m_strength; + void Init(CString house="", CString strength="256", CString direction="64", CString action="Guard", CString tag="None", CString flag1="0", CString flag2="0", CString flag3="0", CString flag4="0", CString flag5="0", CString flag6="0"); + CUnit(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CUnit) + enum { IDD = IDD_UNIT }; + CSliderCtrl m_strength_ctrl; + CString m_direction; + CString m_flag1; + CString m_flag2; + CString m_house; + CString m_flag3; + CString m_flag4; + CString m_flag5; + CString m_flag6; + CString m_action; + CString m_tag; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CUnit) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CUnit) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_UNIT_H__44A11CC3_84B6_11D3_B63B_F881F458F743__INCLUDED_ diff --git a/MissionEditor/UserScriptsDlg.cpp b/MissionEditor/UserScriptsDlg.cpp new file mode 100644 index 0000000..a932135 --- /dev/null +++ b/MissionEditor/UserScriptsDlg.cpp @@ -0,0 +1,3292 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// UserScriptsDlg.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "finalsun.h" +#include "UserScriptsDlg.h" +#include +#include +#include +#include +#include "variables.h" +#include "functions.h" +#include "inlines.h" +#include "combouinputdlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +using namespace std; + +struct FunctionData +{ + CString* name; + CString* param; +public: + void Init(); + FunctionData(); + int paramcount; + void AddParam(); + ~FunctionData(); +}; + +struct JumpLineData +{ + CString name; + int line; +}; + +class CUserScript +{ +public: + void RaiseErr(int n, const char* str); + char errortext[250]; + int error; + int functioncount; + int GetFunction(int index, CString* name, CString *params[], int* paramcount); + int FindJumpLine(CString name); + int LoadFile(const char* filename); + CUserScript(); + virtual ~CUserScript(); + +private: + int AllocateFunction(); + FunctionData* functiondata; + map jumplinedata; + + + CString filename; +}; + +CUserScript::CUserScript() +{ + functioncount=0; + functiondata=NULL; + +} + +CUserScript::~CUserScript() +{ + if(functiondata!=NULL) free( functiondata); +} + +int CUserScript::FindJumpLine(CString name) +{ + if(jumplinedata.find(name)==jumplinedata.end()) return -1; + return jumplinedata[name]; +} + +int CUserScript::LoadFile(const char *setupfile) +{ + filename=setupfile; + + int file=_open(setupfile, _O_RDONLY); + if(file==-1) + { + MessageBox(0, "Error opening script file", "Error", MB_ICONERROR); + return -1; + } + + int parsepos=0, filesize=0; + BOOL inFunction=FALSE; + BOOL inParam=FALSE; + BOOL inComment=FALSE; + BOOL inFunctionHead=FALSE; + BOOL inNewOrder=TRUE; + BOOL inJumpLine=FALSE; + + + + while(!(_eof(file))) + { + unsigned char c; + int res=_read(file,(void*) &c, 1); + if(res>0) filesize++; + } + + _lseek(file, 0, SEEK_SET); + unsigned char *data=new(unsigned char[filesize+5]); + data[filesize]=0; + for (parsepos=0;parseposdata(), 0); + + + } + else + { + + // add character to param + functiondata[functioncount-1].param[functiondata[functioncount-1].paramcount-1]+=data[parsepos]; + if(data[parsepos]=='"' && data[parsepos+1]=='"') parsepos++; // ignore the next " + + + } + } + else if(inFunction==TRUE && inParam==FALSE && inFunctionHead==FALSE) + { + if(IsCharAlphaNumeric(data[parsepos])!=0) + { + *functiondata[functioncount-1].name+=data[parsepos]; + } + else + { + inFunction=FALSE; + //MessageBox(0, functiondata[functioncount-1].name->data(), "FUNCTIONAME", 0); + } + } + + else if(inFunctionHead==TRUE && inParam==FALSE) + { + if(data[parsepos]=='"') + { + // add a param! + inParam=TRUE; + functiondata[functioncount-1].AddParam(); + functiondata[functioncount-1].param[functiondata[functioncount-1].paramcount-1]=""; + } + if(data[parsepos]==')') + { + inFunctionHead=FALSE; + //MessageBox(0, (char*)&data[parsepos], "", 0); + } + } + + else if(inJumpLine==TRUE) + { + if(data[parsepos]!=':') + { + char d[2]; + d[0]=data[parsepos]; + d[1]=0; + strcat((char*)jumplinename, d); + } + else + { + jumplinedata[jumplinename]=functioncount; + //MessageBox(0,(char*)jumplinename,"",0); + memset(jumplinename, 0, 512); + inJumpLine=FALSE; + inNewOrder=TRUE; + } + } + + + + + } + ///////////////////////// + + + + + delete[] (data); + return 0; +} + +int CUserScript::GetFunction(int index, CString *name, CString * params[], int* paramcount) +{ + if(index<0 || index>=functioncount) return -1; + + *name=*functiondata[index].name; + *paramcount=functiondata[index].paramcount; + + //if(params==NULL) return 0; + if (*paramcount>0) + { + *params=new(CString[*paramcount]); + } + else *params=0; + + + int i; + for(i=0;i<*paramcount;i++) + { + //params[i]=new(CString); + CString* str=*params; + str[i]=functiondata[index].param[i]; + //memcpy((void*)params[i], (void*) &functiondata[index].param[i], &function + //MessageBox(0,functiondata[index].param[i].data(),"",0); + } + + + return 0; +} + +void FunctionData::AddParam() +{ + //CString* tmp=NULL; + //if(paramcount>0) + //{ + + //tmp=new(CString[paramcount]); + //memcpy((void*)tmp, param, sizeof(CString)*paramcount); + + //delete[] (functiondata); //delete is bad-> CStrings would be deallocated! + //delete[](param); + //param=NULL; + //} + //param=(CString*)realloc(param, (paramcount+1)*sizeof(CString)); + //param[paramcount]=CString(); + //CString hack; + //memset(¶m[paramcount], 0, sizeof(CString)); + //memcpy(¶m[paramcount], &hack, sizeof(CString)); + //param[paramcount]=""; + //param=new(CString[paramcount+1]); + // + //memcpy((void*) param, (void*) tmp, sizeof(CString)*paramcount); + + //name=""; + + CString* newparam=new(CString[paramcount+1]); + int i; + for(i=0;i0) + { + + tmp=new(FunctionData[functioncount]); + memcpy((void*)tmp, functiondata, sizeof(FunctionData)*functioncount); + delete[] functiondata; + functiondata=NULL; + } + + functiondata=new(FunctionData[functioncount+1]); + + memcpy((void*) functiondata, (void*) tmp, sizeof(FunctionData)*functioncount); + + functiondata[functioncount].name="";*/ + functiondata=(FunctionData*)realloc(functiondata, sizeof(FunctionData)*(functioncount+1)); + + functiondata[functioncount].Init(); + + *functiondata[functioncount].name="HUHU"; + + functioncount++; + //delete[] (tmp); + return functioncount; +} + +void CUserScript::RaiseErr(int n, const char *str) +{ + +} + +void FunctionData::Init() +{ + paramcount=0; + param=NULL; + name=new(CString); +} + + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CUserScriptsDlg + + +CUserScriptsDlg::CUserScriptsDlg(CWnd* pParent /*=NULL*/) + : CDialog(CUserScriptsDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CUserScriptsDlg) + m_Script = _T(""); + m_Report = _T(""); + //}}AFX_DATA_INIT +} + + +void CUserScriptsDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CUserScriptsDlg) + DDX_LBString(pDX, IDC_SCRIPTS, m_Script); + DDX_Text(pDX, IDC_REPORT, m_Report); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CUserScriptsDlg, CDialog) + //{{AFX_MSG_MAP(CUserScriptsDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CUserScriptsDlg + +#define ASK_CONTINUE "AskContinue" +#define ADD_TRIGGER "AddTrigger" +#define MESSAGE "Message" +#define SET_INI_KEY "SetIniKey" +#define SET_SAFE_MODE "SetSafeMode" +#define SET_VARIABLE "SetVariable" +#define SET_VARIABLE_IF "SetVariableIf" +#define ADD "Add" +#define MULTI "Multi" +#define SUBSTRACT "Substract" +#define DIVIDE "Divide" +#define SET_WAYPOINT "SetWaypoint" +#define REQUIRES_MP "RequiresMP" +#define REQUIRES_SP "RequiresSP" +#define ADD_AI_TRIGGER "AddAITrigger" +#define ADD_TAG "AddTag" +#define RESIZE "Resize" +#define IS "Is" +#define CANCEL "Cancel" +#define PRINT "Print" +#define TOLOWER "LowerCase" +#define TOUPPER "UpperCase" +#define GET_FREE_WAYPOINT "GetFreeWaypoint" +#define UINPUT_GET_INTEGER "UInputGetInteger" +#define UINPUT_GET_STRING "UInputGetString" +#define JUMP_TO_LINE "JumpTo" +#define SET_AUTO_UPDATE "SetAutoUpdate" +#define GET_RANDOM "GetRandom" +#define ADD_TERRAIN "AddTerrain" +#define GET_INI_KEY "GetIniKey" +#define MODULO "Mod" +#ifdef SMUDGE_SUPP +#define ADD_SMUDGE "AddSmudge" +#endif +#define INSERT "Insert" +#define LENGTH "Length" +#define TRIM "Trim" +#define GETCHAR "GetChar" +#define REPLACE "Replace" +#define REMOVE "Remove" +#define GET_WAYPOINT_POS "GetWaypointPos" +#define GET_PARAM "GetParam" +#define SET_PARAM "SetParam" +#define GET_PARAM_COUNT "GetParamCount" +#define ALLOW_DELETE "AllowDelete" +#define DELETE_TERRAIN "DeleteTerrain" +#define DELETE_INFANTRY "DeleteInfantry" +#define DELETE_AIRCRAFT "DeleteAircraft" +#define DELETE_STRUCTURE "DeleteStructure" +#define DELETE_VEHICLE "DeleteVehicle" +#define IS_INFANTRY_DELETED "IsInfantryDeleted" +#define IS_TERRAIN_DELETED "IsTerrainDeleted" +#define ADD_INFANTRY "AddInfantry" +#define ALLOW_ADD "AllowAdd" +#define ADD_VEHICLE "AddVehicle" +#define ADD_AIRCRAFT "AddAircraft" +#define ADD_STRUCTURE "AddStructure" +#define GET_INFANTRY "GetInfantry" +#define GET_AIRCRAFT "GetAircraft" +#define GET_STRUCTURE "GetStructure" +#define GET_VEHICLE "GetVehicle" +#define UINPUT_GET_HOUSE "UInputGetHouse" +#define UINPUT_GET_COUNTRY "UInputGetCountry" +#define UINPUT_GET_TRIGGER "UInputGetTrigger" +#define UINPUT_GET_TAG "UInputGetTag" +#define MESSAGE_YES_NO "Ask" +#define GET_HOUSE "GetHouse" +#define GET_COUNTRY "GetCountry" +#define GET_HOUSE_INDEX "GetHouseIndex" +#define OR "Or" +#define AND "And" +#define NOT "Not" +#define UINPUT_GET_MANUAL "UInputSelect" + +#define ID_ASK_CONTINUE 0 +#define ID_ADD_TRIGGER 1 +#define ID_MESSAGE 2 +#define ID_SET_INI_KEY 3 +#define ID_SET_SAFE_MODE 4 +#define ID_SET_VARIABLE 5 +#define ID_SET_VARIABLE_IF 6 +#define ID_ADD 7 +#define ID_MULTI 8 +#define ID_SUBSTRACT 9 +#define ID_DIVIDE 10 +#define ID_SET_WAYPOINT 11 +#define ID_REQUIRES_MP 12 +#define ID_REQUIRES_SP 13 +#define ID_ADD_AI_TRIGGER 14 +#define ID_ADD_TAG 15 +#define ID_RESIZE 16 +#define ID_IS 17 +#define ID_CANCEL 18 +#define ID_PRINT 19 +#define ID_TOLOWER 20 +#define ID_TOUPPER 21 +#define ID_GET_FREE_WAYPOINT 22 +#define ID_UINPUT_GET_INTEGER 23 +#define ID_UINPUT_GET_STRING 24 +#define ID_JUMP_TO_LINE 25 +#define ID_SET_AUTO_UPDATE 26 +#define ID_GET_RANDOM 27 +#define ID_ADD_TERRAIN 28 +#define ID_GET_INI_KEY 29 +#define ID_MODULO 30 +#ifdef SMUDGE_SUPP +#define ID_ADD_SMUDGE 31 +#endif +#define ID_INSERT 32 +#define ID_LENGTH 33 +#define ID_TRIM 34 +#define ID_GETCHAR 35 +#define ID_REPLACE 36 +#define ID_REMOVE 37 +#define ID_GET_WAYPOINT_POS 38 +#define ID_GET_PARAM 39 +#define ID_SET_PARAM 40 +#define ID_GET_PARAM_COUNT 41 +#define ID_ALLOW_DELETE 42 +#define ID_DELETE_TERRAIN 43 +#define ID_DELETE_INFANTRY 44 +#define ID_DELETE_STRUCTURE 45 +#define ID_DELETE_AIRCRAFT 46 +#define ID_DELETE_VEHICLE 47 +#define ID_IS_INFANTRY_DELETED 48 +#define ID_IS_TERRAIN_DELETED 49 +#define ID_ADD_INFANTRY 50 +#define ID_ALLOW_ADD 51 +#define ID_ADD_VEHICLE 52 +#define ID_ADD_AIRCRAFT 53 +#define ID_ADD_STRUCTURE 54 +#define ID_GET_INFANTRY 55 +#define ID_GET_AIRCRAFT 56 +#define ID_GET_STRUCTURE 57 +#define ID_GET_VEHICLE 58 +#define ID_UINPUT_GET_HOUSE 59 +#define ID_UINPUT_GET_COUNTRY 60 +#define ID_UINPUT_GET_TRIGGER 61 +#define ID_UINPUT_GET_TAG 62 +#define ID_MESSAGE_YES_NO 63 +#define ID_GET_HOUSE 64 +#define ID_GET_COUNTRY 65 +#define ID_GET_HOUSE_INDEX 66 +#define ID_OR 67 +#define ID_AND 68 +#define ID_NOT 69 +#define ID_UINPUT_GET_MANUAL 70 + + +extern CString GetFree(const char* section); + +BOOL IsValSet(CString val) +{ + val.MakeLower(); + if(val=="false" || val=="no") return FALSE; // val is not set + if(val=="true" || val=="yes") return TRUE; + if(atoi(val)) return TRUE; + return FALSE; +} + +int get_player_count() +{ + if(Map->IsMultiplayer()==FALSE) return 1; + + int i; + int wp_count=0; + for(i=0;iGetWaypointCount();i++) + { + CString id; + DWORD pos; + Map->GetWaypointData(i, &id, &pos); + int idi; + idi=atoi(id); + if(idi!=i) break; + if(idi>=0 && idi<8) + { + wp_count++; + } + } + + return wp_count; +} + +struct FUNC_INFO +{ + int type; + CString name; + CString* params; + int paramcount; +}; + +void CUserScriptsDlg::OnOK() +{ + UpdateData(TRUE); + + //srand((unsigned)time(NULL)); + + if(m_Script.GetLength()==0) return; + + CUserScript s; + s.LoadFile((CString)AppPath+(CString)"\\Scripts\\"+m_Script); + + CIniFile& ini=Map->GetIniFile(); + + BOOL bUpdate=FALSE; + BOOL bUpdateOnlyMission=TRUE; + BOOL bNoRepos=TRUE; + BOOL bSafeMode=TRUE; + + map variables; + char c[50]; + + + CString report=m_Script+" Report:\r\n\r\n"; + + BOOL bAutoUpdate=TRUE; + BOOL bAllowLoop=TRUE; // for now we enable this, as we´ve introduced a loop counter + + // stuff for faster CMapData processing: + BOOL bUpdateWaypoints=FALSE; + BOOL bOldUpdate=Map->m_noAutoObjectUpdate; + + BOOL bDeleteAllowed=FALSE; // shall the script be able to delete stuff? + BOOL bAddAllowed=FALSE; // " delete stuff + + + + + + // for delete/add stuff: + int lastInfantryDeleted=-1; + CString lastStructureDeleted=""; + int lastTerrainDeleted=-1; + CString lastUnitDeleted=""; + CString lastAircraftDeleted=""; + + + BOOL bIgnoreLoopCounts=FALSE; + int loop_count=0; + + + map functions; + + // get function ids + int i; + for(i=0;iGetWidth(), c, 10); + variables["%Width%"]=c; + itoa(Map->GetHeight(), c, 10); + variables["%Height%"]=c; + itoa(Map->GetIsoSize(), c, 10); + variables["%IsoSize%"]=c; + itoa(Map->GetWaypointCount(), c, 10); + variables["%WaypointCount%"]=c; + itoa(Map->GetUnitCount(), c, 10); + variables["%UnitCount%"]=c; + itoa(Map->GetInfantryCount(), c, 10); + variables["%InfantryCount%"]=c; + itoa(Map->GetStructureCount(), c, 10); + variables["%StructureCount%"]=c; + itoa(Map->GetAircraftCount(), c, 10); + variables["%AircraftCount%"]=c; + itoa(Map->GetTerrainCount(), c, 10); + variables["%TerrainCount%"]=c; + variables["%Theater%"]=Map->GetTheater(); + itoa(get_player_count(), c, 10); + variables["%PlayerCount%"]=c; + itoa(Map->GetHousesCount(FALSE), c, 10); + variables["%HousesCount%"]=c; + itoa(Map->GetHousesCount(TRUE), c, 10); + variables["%CountriesCount%"]=c; + + if(bDeleteAllowed) + { + variables["%DeleteAllowed%"]="1"; + } + else + variables["%DeleteAllowed%"]="0"; + + if(bAddAllowed) + { + variables["%AddAllowed%"]="1"; + } + else + variables["%AddAllowed%"]="0"; + + if(bSafeMode) + variables["%SafeMode%"]="1"; + else + variables["%SafeMode%"]="0"; + + //CString name; + int name=functions[i].type; + + int paramcount=functions[i].paramcount; + + CString* params=NULL; + + if(paramcount) + { + params=new(CString[paramcount]); + int e; + for(e=0;e::iterator e; + + + for(e=variables.begin();e!=variables.end();e++) + { + for(h=0;hfirst, e->second); + } + } + } + + + delete[] replaceVariables; + + + if(name==ID_ASK_CONTINUE) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + int res=MessageBox(params[0], "Continue?", MB_YESNO); + if(res==IDNO) break; + } + else if(name==ID_MESSAGE) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + MessageBox(params[0], params[1]); + } + else if(name==ID_MESSAGE_YES_NO) + { + if(paramcount<3) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>3) + { + if(params[3].GetLength()>0) + { + if(!IsValSet(params[3])) goto nextline; + } + } + + int res=MessageBox(params[1], params[2], MB_YESNO); + if(res==IDYES) + { + variables[params[0]]="1"; + } + else + variables[params[0]]="0"; + } + else if(name==ID_ADD_TRIGGER) + { + if(paramcount<5) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>5) + { + if(params[5].GetLength()>0) + { + if(!IsValSet(params[5])) goto nextline; + } + } + + if(!bAddAllowed) goto nextline; + + + CString ID_T=GetFreeID(); + + if(params[0].GetLength()>0) + { + variables[params[0]]=ID_T; + } + + ini.sections["Triggers"].values[ID_T]=params[1]; + ini.sections["Events"].values[ID_T]=params[2]; + ini.sections["Actions"].values[ID_T]=params[3]; + + BOOL tag=TRUE; + params[4].MakeLower(); + if(params[4]=="false" || params[4]=="no") tag=FALSE; + + if(tag) + { + CString ID_TAG=GetFreeID(); + ini.sections["Tags"].values[ID_TAG]="0,"; + ini.sections["Tags"].values[ID_TAG]+=GetParam(params[1],2); + ini.sections["Tags"].values[ID_TAG]+=","; + ini.sections["Tags"].values[ID_TAG]+=ID_T; + } + + report+="Trigger " + GetParam(params[1],2) + " added\r\n"; + + bUpdate=TRUE; + } + else if(name==ID_SET_INI_KEY) + { + if(paramcount<3) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>3) + { + if(params[3].GetLength()>0) + { + if(!IsValSet(params[3])) goto nextline; + } + } + + //if(ini.sections[params[0]].FindName(params[1])>=0) + { + if(bSafeMode) goto nextline; + } + + ini.sections[params[0]].values[params[1]]=params[2]; + + report +=params[0]+(CString)"->"+params[1]+(CString) " set to \"" + params[2] + "\"\r\n"; + + bUpdate=TRUE; + bUpdateOnlyMission=FALSE; + } + else if(name==ID_GET_INI_KEY) + { + if(paramcount<3) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>3) + { + if(params[3].GetLength()>0) + { + if(!IsValSet(params[3])) goto nextline; + } + } + + if(ini.sections.find(params[1])==ini.sections.end() || ini.sections[params[1]].FindName(params[2])<0) + { + variables[params[0]]=""; + } + else + variables[params[0]]=ini.sections[params[1]].values[params[2]]; + } + else if(name==ID_SET_SAFE_MODE) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + BOOL enabled=TRUE; + params[0].MakeLower(); + if(params[0]=="false" || params[0]=="no") enabled=FALSE; + + if(!enabled) + { + CString s; + s="This script wants to disable INI protection. For some scripts this may be necessary, but it can seriously damage your Map-> Reason why script wants to disable INI protection:\n"; + s+=params[1]; + s+="\n\nDisable INI protection?"; + + int res=MessageBox(s, "Disable INI protection?", MB_YESNO | MB_DEFBUTTON2); + if(res==IDNO) goto nextline; + } + + if(!enabled) report+="INI Protection disabled\r\n"; + if(enabled) report+="INI Protection enabled\r\n"; + + bSafeMode=enabled; + } + else if(name==ID_SET_VARIABLE) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + variables[params[0]]=params[1]; + } + else if(name==ID_ADD) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + int n; + n=atoi(variables[params[0]]); + int n2=atoi(params[1]); + n+=n2; + char c[50]; + itoa(n, c, 10); + variables[params[0]]=c; + } + else if(name==ID_INSERT) + { + if(paramcount<3) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>3) + { + if(params[3].GetLength()>0) + { + if(!IsValSet(params[3])) goto nextline; + } + } + + int pos=atoi(params[2]); + + if(pos<0) + { + pos=variables[params[0]].GetLength(); + } + + variables[params[0]].Insert(pos, params[1]); + } + else if(name==ID_REPLACE) + { + if(paramcount<3) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>3) + { + if(params[3].GetLength()>0) + { + if(!IsValSet(params[3])) goto nextline; + } + } + + variables[params[0]].Replace(params[1], params[2]); + } + else if(name==ID_TRIM) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + variables[params[0]].TrimLeft(); + variables[params[0]].TrimRight(); + } + else if(name==ID_NOT) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + if(IsValSet(variables[params[0]])) + variables[params[0]]="0"; + else + variables[params[0]]="1"; + } + else if(name==ID_AND) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + BOOL bSet=TRUE; + + int k; + for(k=1;k2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + int len=params[1].GetLength(); + char c[50]; + itoa(len, c, 10); + variables[params[0]]=c; + } + else if(name==ID_REMOVE) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + if(atoi(params[1])>=variables[params[0]].GetLength() || atoi(params[1])<0 || atoi(params[2])<0) + { + MessageBox("Invalid index or length for remove command, script cancelled.","Error"); + delete[] params; + break; + } + + variables[params[0]].Delete(atoi(params[1]),atoi(params[2])); + } + else if(name==ID_GETCHAR) + { + if(paramcount<3) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>3) + { + if(params[3].GetLength()>0) + { + if(!IsValSet(params[3])) goto nextline; + } + } + + if(atoi(params[2])>=params[1].GetLength() || atoi(params[2])<0) + { + MessageBox("Invalid index for GetChar command, script cancelled.","Error"); + delete[] params; + break; + } + + variables[params[0]]=params[1].GetAt(atoi(params[2])); + } + else if(name==ID_SUBSTRACT) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + int n; + n=atoi(variables[params[0]]); + int n2=atoi(params[1]); + n-=n2; + char c[50]; + itoa(n, c, 10); + variables[params[0]]=c; + } + else if(name==ID_MULTI) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + int n; + n=atoi(variables[params[0]]); + int n2=atoi(params[1]); + n=n*n2; + char c[50]; + itoa(n, c, 10); + variables[params[0]]=c; + } + else if(name==ID_DIVIDE) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + int n; + n=atoi(variables[params[0]]); + int n2=atoi(params[1]); + + if(n2==0) + { + MessageBox("Division through 0, script cancelled", "Division through 0"); + delete[] params; + break; + } + + n=n/n2; + char c[50]; + itoa(n, c, 10); + variables[params[0]]=c; + } + else if(name==ID_MODULO) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + int n; + n=atoi(variables[params[0]]); + int n2=atoi(params[1]); + + if(n2==0) + { + MessageBox("Division through 0, script cancelled", "Division through 0"); + delete[] params; + break; + } + + n=n%n2; + char c[50]; + itoa(n, c, 10); + variables[params[0]]=c; + } + else if(name==ID_SET_WAYPOINT) + { + if(paramcount<3) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>3) + { + if(params[3].GetLength()>0) + { + if(!IsValSet(params[3])) goto nextline; + } + } + + int n=atoi(params[0]); + CString id=params[0]; + if(n<0) + { + id=""; + } + + if(bSafeMode && n>=0) + { + if(ini.sections["Waypoints"].FindName(id)>=0) + { + goto nextline; + } + } + + + DWORD pos=atoi(params[1])+atoi(params[2])*Map->GetIsoSize(); + + if(posGetIsoSize()*Map->GetIsoSize()) + { + //Map->m_noAutoObjectUpdate=TRUE; + Map->AddWaypoint(id, pos); + bUpdateWaypoints=TRUE; + //Map->m_noAutoObjectUpdate=bOldUpdate; + report+="Waypoint " + id + " set.\r\n"; + } + else + { + report+="Waypoint " + id + " moving failed!\r\n"; + } + + bUpdate=TRUE; + bUpdateOnlyMission=FALSE; + } + else if(name==ID_REQUIRES_MP) + { + // check bool + if(paramcount>0) + { + if(params[0].GetLength()>0) + { + if(!IsValSet(params[0])) goto nextline; + } + } + + if(Map->IsMultiplayer()==FALSE) + { + MessageBox("This script requires a multiplayer map and cannot be used with singleplayer maps", "Error"); + break; + } + } + else if(name==ID_REQUIRES_SP) + { + // check bool + if(paramcount>0) + { + if(params[0].GetLength()>0) + { + if(!IsValSet(params[0])) goto nextline; + } + } + + if(Map->IsMultiplayer()==TRUE) + { + MessageBox("This script requires a singleplayer map and cannot be used with multiplayer maps", "Error"); + break; + } + } + else if(name==ID_ADD_AI_TRIGGER) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + if(!bAddAllowed) goto nextline; + + CString ID_T=GetFreeID(); + + if(params[0].GetLength()>0) + { + variables[params[0]]=ID_T; + } + + ini.sections["AITriggerTypes"].values[ID_T]=params[1]; + + report+="AI Trigger " + GetParam(params[1],0) + " added\r\n"; + + bUpdate=TRUE; + } + else if(name==ID_ADD_TAG) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + if(!bAddAllowed) goto nextline; + + CString ID_T=GetFreeID(); + + if(params[0].GetLength()>0) + { + variables[params[0]]=ID_T; + } + + CString ID_TAG=ID_T; //GetFreeID(); + ini.sections["Tags"].values[ID_TAG]=params[1]; + + report+="Tag " + GetParam(params[1],1) + " added\r\n"; + + bUpdate=TRUE; + } + else if(name==ID_RESIZE) + { + if(paramcount<4) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>4) + { + if(params[4].GetLength()>0) + { + if(!IsValSet(params[4])) goto nextline; + } + } + + int res=MessageBox("This script wants to resize the map. Resize map?", "Resize map?", MB_YESNO); + if(res==IDNO) goto nextline; + + + if(atoi(params[2])>200 || atoi(params[3])>200) + { + MessageBox("Resizing map failed. Script cancelled.", "Error"); + break; + } + + Map->ResizeMap(atoi(params[0]), atoi(params[1]), atoi(params[2]), atoi(params[3])); + + bUpdate=TRUE; + bUpdateOnlyMission=FALSE; + bNoRepos=FALSE; + } + else if(name==ID_IS) + { + if(paramcount<4) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>4) + { + if(params[4].GetLength()>0) + { + if(!IsValSet(params[4])) goto nextline; + } + } + + BOOL bIs=FALSE; + + if(params[1]=="<") + { + if(atoi(params[0])=") + { + if(atoi(params[0])>=atoi(params[2])) bIs=TRUE; + } + if(params[1]==">") + { + if(atoi(params[0])>atoi(params[2])) bIs=TRUE; + } + if(params[1]=="!=") + { + if(atoi(params[0])!=atoi(params[2])) bIs=TRUE; + if(params[0]!=params[2]) bIs=TRUE; + } + + + + CString s="0"; + if(bIs) s="1"; + + + + variables[params[3]]=s; + + } + else if(name==ID_CANCEL) + { + // check bool + if(paramcount>0) + { + if(params[0].GetLength()>0) + { + if(!IsValSet(params[0])) goto nextline; + } + } + + break; + } + else if(name==ID_PRINT) + { + + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + report+=params[0]; + report+="\r\n"; + + + } + else if(name==ID_TOLOWER) + { + + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + variables[params[0]].MakeLower(); + + + } + else if(name==ID_TOUPPER) + { + + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + variables[params[0]].MakeUpper(); + + } + else if(name==ID_GET_FREE_WAYPOINT) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + variables[params[0]]=GetFree("Waypoints"); + } + else if(name==ID_UINPUT_GET_INTEGER) + { + + if(paramcount<4) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>4) + { + if(params[4].GetLength()>0) + { + if(!IsValSet(params[4])) goto nextline; + } + } + + BOOL ok=FALSE; + int n=0; + while(!ok) + { + CString s=InputBox(params[1], "Enter Integer"); + ok=TRUE; + + if(s.GetLength()==0) ok=FALSE; + + n=atoi(s); + if(params[2].GetLength()>0) + { + if(n0) + { + if(n>atoi(params[3])) ok=FALSE; + } + } + + char c[50]; + itoa(n, c, 10); + variables[params[0]]=c; + } + else if(name==ID_UINPUT_GET_STRING) + { + + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + BOOL ok=FALSE; + CString s; + while(!ok) + { + s=InputBox(params[1], "Enter String"); + ok=TRUE; + + if (s.GetLength()==0) ok=FALSE; + } + variables[params[0]]=s; + } + else if(name==ID_UINPUT_GET_HOUSE) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + CComboUInputDlg dlg; + dlg.m_type=COMBOUINPUT_HOUSES; + dlg.m_Caption=params[1]; + + dlg.DoModal(); + + variables[params[0]]=dlg.m_Combo; + } + else if(name==ID_UINPUT_GET_COUNTRY) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + CComboUInputDlg dlg; + dlg.m_type=COMBOUINPUT_COUNTRIES; + dlg.m_Caption=params[1]; + + dlg.DoModal(); + + variables[params[0]]=dlg.m_Combo; + } + else if(name==ID_UINPUT_GET_TRIGGER) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + CComboUInputDlg dlg; + dlg.m_type=COMBOUINPUT_TRIGGERS; + dlg.m_Caption=params[1]; + + dlg.DoModal(); + + variables[params[0]]=dlg.m_Combo; + } + else if(name==ID_UINPUT_GET_TAG) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + CComboUInputDlg dlg; + dlg.m_type=COMBOUINPUT_TAGS; + dlg.m_Caption=params[1]; + + dlg.DoModal(); + + variables[params[0]]=dlg.m_Combo; + } + /*else if(name==ID_UINPUT_GET_MANUAL) + { + if(paramcount<4) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>4) + { + if(params[4].GetLength()>0) + { + if(!IsValSet(params[4])) goto nextline; + } + } + + CComboUInputDlg dlg; + dlg.m_type=COMBOUINPUT_MANUAL; + dlg.m_Caption=params[1]; + dlg.bTruncateStrings=IsValSet(params[2]); + + + + dlg.DoModal(); + + variables[params[0]]=dlg.m_Combo; + }*/ + else if(name==ID_JUMP_TO_LINE) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + + if(!bAllowLoop) + { + int res=MessageBox("This script tries to use loops. Some scripts may require this. However, this holds the risk of infinite loops, which may cause the FinalSun/FinalAlert2 to crash. Do you want to allow looping for this script?", "Allow looping?", MB_YESNO); + if(res==IDYES) + { + bAllowLoop=TRUE; + }else + + goto nextline; // not allowed in safe mode because of possible infinte loops# + } + + if(!bIgnoreLoopCounts) + { + loop_count++; + + if(loop_count>300) + { + int res=MessageBox("This script has exceeded the 300 loops limit. Do you want to remove the loop limit (not recommended, inherits risk of infinite loops if script has bugs)? If you press no, the script will stop after another 300 loops to ask you again. If you press cancel, the script will be cancelled.", "Loop Limit exceeded", MB_YESNOCANCEL | MB_DEFBUTTON2); + if(res==IDYES) bIgnoreLoopCounts=TRUE; + if(res==IDNO) loop_count=0; + if(res==IDCANCEL) + { + delete[] params; + break; + } + + } + } + + + int n=s.FindJumpLine(params[0]); + if(n<0 || n>s.functioncount) + { + + ReportScriptError(i); + delete[] params; + break; + } + + + i=n-1; // not n, as the for loop adds 1 again! + goto nextline_no_update; + } + else if(name==ID_SET_AUTO_UPDATE) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + bAutoUpdate=IsValSet(params[0]); + + goto nextline; + } + else if(name==ID_GET_RANDOM) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + int n=rand(); // 0 and 32767 + + char c[50]; + itoa(n, c, 10); + variables[params[0]]=c; + } + else if(name==ID_ADD_TERRAIN) + { + if(paramcount<3) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>3) + { + if(params[3].GetLength()>0) + { + if(!IsValSet(params[3])) goto nextline; + } + } + + if(!bAddAllowed) goto nextline; + + DWORD pos; + pos=atoi(params[1])+atoi(params[2])*Map->GetIsoSize(); + + if(Map->GetTerrainAt(pos)<0) + { + Map->AddTerrain(params[0], pos); + + report+="Terrain added: " + params[0] + (CString)" at " + params[1] + (CString)"/" + params[2] + "\r\n"; + + bUpdate=TRUE; + bUpdateOnlyMission=FALSE; + } + } +#ifdef SMUDGE_SUPP + else if(name==ID_ADD_SMUDGE) + { + if(paramcount<3) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>3) + { + if(params[3].GetLength()>0) + { + if(!IsValSet(params[3])) goto nextline; + } + } + DWORD pos; + pos=atoi(params[1])+atoi(params[2])*Map->GetIsoSize(); + + FIELDDATA* fd=Map->GetFielddataAt(pos); + if(fd->smudge<0) + { + SMUDGE s; + s.deleted=0; + s.type=params[0]; + s.x=atoi(params[1]); + s.y=atoi(params[2]); + Map->AddSmudge(&s); + + report+="Smudge added: " + params[0] + (CString) " at " + params[1] + (CString)"/" + params[2] + "\r\n"; + + bUpdate=TRUE; + bUpdateOnlyMission=FALSE; + } + } +#endif + else if(name==ID_GET_WAYPOINT_POS) + { + if(paramcount<3) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>3) + { + if(params[3].GetLength()>0) + { + if(!IsValSet(params[3])) goto nextline; + } + } + + BOOL bFound=FALSE; + DWORD pos; + int k; + for(k=0;kGetWaypointCount();k++) + { + CString id; + Map->GetWaypointData(k, &id, &pos); + + if(id==params[0]) + { + bFound=TRUE; + break; + } + } + + if(!bFound) pos=0; + + int x=pos%Map->GetIsoSize(); + int y=pos/Map->GetIsoSize(); + + char c[50]; + itoa(x, c, 10); + variables[params[1]]=c; + itoa(y, c, 10); + variables[params[2]]=c; + } + else if(name==ID_GET_PARAM) + { + if(paramcount<3) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>3) + { + if(params[3].GetLength()>0) + { + if(!IsValSet(params[3])) goto nextline; + } + } + + variables[params[0]]=GetParam(params[1], atoi(params[2])); + } + else if(name==ID_SET_PARAM) + { + if(paramcount<3) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>3) + { + if(params[3].GetLength()>0) + { + if(!IsValSet(params[3])) goto nextline; + } + } + + variables[params[0]]=SetParam(variables[params[0]], atoi(params[1]), params[2]); + } + else if(name==ID_GET_PARAM_COUNT) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + int k; + int count=1; // we start at 1 param even if no , exists! + for(k=0;k1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + + { + CString s; + s="This script wants to delete objects or triggers from your map. For some scripts this may be necessary, but it can seriously damage your map. Reason why script wants to delete objects:\n"; + s+=params[0]; + s+="\n\nDo you want to allow the script to do this?"; + + int res=MessageBox(s, "Allow deletion of objects?", MB_YESNO | MB_DEFBUTTON2); + if(res==IDNO) goto nextline; + } + + bDeleteAllowed=TRUE; + } + else if(name==ID_ALLOW_ADD) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + + { + CString s; + s="This script wants to add objects or triggers to your map. For some scripts this may be necessary, but it can seriously damage your map. Reason why script wants to add objects:\n"; + s+=params[0]; + s+="\n\nDo you want to allow the script to do this?"; + + int res=MessageBox(s, "Allow adding of objects?", MB_YESNO | MB_DEFBUTTON2); + if(res==IDNO) goto nextline; + } + + bAddAllowed=TRUE; + } + else if(name==ID_DELETE_TERRAIN) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + if(!bDeleteAllowed ) goto nextline; + + int index=atoi(params[0]); + if(index<0 || index>=Map->GetTerrainCount()) + { + report+="Terrain deletion failed, invalid index\r\n"; + goto nextline; + } + + lastTerrainDeleted=index; + Map->DeleteTerrain(index); + + report+="Terrain deleted\r\n"; + + bUpdate=TRUE; + bUpdateOnlyMission=FALSE; + } + else if(name==ID_DELETE_INFANTRY) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + if(!bDeleteAllowed ) goto nextline; + + int index=atoi(params[0]); + if(index<0 || index>=Map->GetInfantryCount()) + { + report+="Infantry deletion failed, invalid index\r\n"; + goto nextline; + } + + lastInfantryDeleted=index; + Map->DeleteInfantry(index); + + report+="Infantry deleted\r\n"; + + bUpdate=TRUE; + bUpdateOnlyMission=FALSE; + } + else if(name==ID_DELETE_STRUCTURE) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + if(!bDeleteAllowed ) goto nextline; + + int index=atoi(params[0]); + if(index<0 || index>=Map->GetStructureCount()) + { + report+="Structure deletion failed, invalid index\r\n"; + goto nextline; + } + + lastStructureDeleted=*ini.sections["Structures"].GetValueName(index); + Map->DeleteStructure(index); + + report+="Structure deleted\r\n"; + + bUpdate=TRUE; + bUpdateOnlyMission=FALSE; + } + else if(name==ID_DELETE_VEHICLE) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + if(!bDeleteAllowed ) goto nextline; + + int index=atoi(params[0]); + if(index<0 || index>=Map->GetUnitCount()) + { + report+="Vehicle deletion failed, invalid index\r\n"; + goto nextline; + } + + lastUnitDeleted=*ini.sections["Units"].GetValueName(index); + Map->DeleteUnit(index); + + report+="Vehicle deleted\r\n"; + + bUpdate=TRUE; + bUpdateOnlyMission=FALSE; + } + else if(name==ID_DELETE_AIRCRAFT) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + + if(!bDeleteAllowed ) goto nextline; + + int index=atoi(params[0]); + if(index<0 || index>=Map->GetAircraftCount()) + { + report+="Aircraft deletion failed, invalid index\r\n"; + goto nextline; + } + + lastAircraftDeleted=*ini.sections["Aircraft"].GetValueName(index); + Map->DeleteAircraft(index); + + report+="Aircraft deleted\r\n"; + + bUpdate=TRUE; + bUpdateOnlyMission=FALSE; + } + else if(name==ID_IS_INFANTRY_DELETED) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + CString deleted="1"; + int index=atoi(params[1]); + if(index>=0 && indexGetInfantryCount()) + { + INFANTRY id; + Map->GetInfantryData(index, &id); + if(id.deleted==0) deleted="0"; + } + + variables[params[0]]=deleted; + } + else if(name==ID_IS_TERRAIN_DELETED) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + CString deleted="1"; + int index=atoi(params[1]); + if(index>=0 && indexGetTerrainCount()) + { + TERRAIN id; + Map->GetTerrainData(index, &id); + if(id.deleted==0) deleted="0"; + } + + variables[params[0]]=deleted; + } + else if(name==ID_ADD_INFANTRY) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + // check param count + int count=1; // we start at 1 param even if no , exists! + int k; + for(k=0;kAddInfantry(&id, NULL, NULL, NULL, lastInfantryDeleted)==FALSE) + { + report+="AddInfantry failed\r\n"; + } + else + { + report+="Infantry added\r\n"; + bUpdate=TRUE; + bUpdateOnlyMission=FALSE; + } + } + else if(name==ID_ADD_VEHICLE) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + // check param count + int count=1; // we start at 1 param even if no , exists! + int k; + for(k=0;kGetUnitAt(atoi(unit.x)+atoi(unit.y)*Map->GetIsoSize())>=0) + { + report+="AddVehicle failed\r\n"; + goto nextline; + } + + if(Map->AddUnit(&unit, NULL, NULL, NULL, lastUnitDeleted)==FALSE) + { + report+="AddVehicle failed\r\n"; + } + else + { + report+="Vehicle added\r\n"; + bUpdate=TRUE; + bUpdateOnlyMission=FALSE; + } + } + else if(name==ID_ADD_AIRCRAFT) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + // check param count + int count=1; // we start at 1 param even if no , exists! + int k; + for(k=0;kGetAirAt(atoi(air.x)+atoi(air.y)*Map->GetIsoSize())>=0) + { + report+="AddAircraft failed\r\n"; + goto nextline; + } + + if(Map->AddAircraft(&air, NULL, NULL, NULL, lastAircraftDeleted)==FALSE) + { + report+="AddAircraft failed\r\n"; + } + else + { + report+="Aircraft added\r\n"; + bUpdate=TRUE; + bUpdateOnlyMission=FALSE; + } + } + else if(name==ID_ADD_STRUCTURE) + { + if(paramcount<1) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>1) + { + if(params[1].GetLength()>0) + { + if(!IsValSet(params[1])) goto nextline; + } + } + + // check param count + int count=1; // we start at 1 param even if no , exists! + int k; + for(k=0;kGetStructureAt(atoi(structure.x)+atoi(structure.y)*Map->GetIsoSize())>=0) + { + report+="AddStructure failed\r\n"; + goto nextline; + } + + if(Map->AddStructure(&structure, NULL, NULL, NULL, lastStructureDeleted)==FALSE) + { + report+="AddStructure failed\r\n"; + } + else + { + report+="Structure added\r\n"; + bUpdate=TRUE; + bUpdateOnlyMission=FALSE; + } + } + else if(name==ID_GET_INFANTRY) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + int index=atoi(params[1]); + CString s; + if(index>=0 && indexGetInfantryCount()) + { + INFANTRY id; + Map->GetInfantryINIData(index, &s); + } + + variables[params[0]]=s; + } + else if(name==ID_GET_AIRCRAFT) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + int index=atoi(params[1]); + CString s; + if(index>=0 && indexGetAircraftCount()) + { + s=*ini.sections["Aircraft"].GetValue(index); + } + + variables[params[0]]=s; + } + else if(name==ID_GET_STRUCTURE) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + int index=atoi(params[1]); + CString s; + if(index>=0 && indexGetStructureCount()) + { + s=*ini.sections["Structures"].GetValue(index); + } + + variables[params[0]]=s; + } + else if(name==ID_GET_VEHICLE) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + int index=atoi(params[1]); + CString s; + if(index>=0 && indexGetUnitCount()) + { + s=*ini.sections["Units"].GetValue(index); + } + + variables[params[0]]=s; + } + else if(name==ID_GET_HOUSE) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + int index=atoi(params[1]); + + CString s; + if(index>=0 && indexGetHousesCount(FALSE)) + { + s=Map->GetHouseID(index, FALSE); + } + + variables[params[0]]=s; + } + else if(name==ID_GET_COUNTRY) + { + if(paramcount<2) + { + ReportScriptError(i); + delete[] params; + break; + } + + // check bool + if(paramcount>2) + { + if(params[2].GetLength()>0) + { + if(!IsValSet(params[2])) goto nextline; + } + } + + int index=atoi(params[1]); + + CString s; + if(index>=0 && indexGetHousesCount(TRUE)) + { + s=Map->GetHouseID(index, TRUE); + } + + variables[params[0]]=s; + } + + else + { + ReportScriptError(i); + delete[] params; + break; + } + +nextline: + if(bAutoUpdate) + { + m_Report=report; + UpdateData(FALSE); + } + +nextline_no_update: + + delete[] params; + + } + + for(i=0;iUpdateIniFile(MAPDATA_UPDATE_FROM_INI); + + if(bUpdate) ((CFinalSunDlg*)theApp.GetMainWnd())->UpdateDialogs(bUpdateOnlyMission, bNoRepos); + + // CDialog::OnOK(); +} + +BOOL CUserScriptsDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + int k; + CFileFind ff; + + + CString scripts=(CString)AppPath+"\\Scripts\\*.fscript"; + { + + CFileFind ff; + if(ff.FindFile(scripts)) + { + CListBox* lb=(CListBox*)GetDlgItem(IDC_SCRIPTS); + + BOOL bWorking=TRUE; + + while(bWorking) + { + bWorking=ff.FindNextFile(); + lb->AddString(ff.GetFileName()); + } + } + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} + +void CUserScriptsDlg::ReportScriptError(int line) +{ + char c[50]; + itoa(line, c, 10); + + MessageBox("Script error in line " + (CString)c + ". Probably wrong parameter count or unknown function call.","Error"); +} diff --git a/MissionEditor/UserScriptsDlg.h b/MissionEditor/UserScriptsDlg.h new file mode 100644 index 0000000..f04f550 --- /dev/null +++ b/MissionEditor/UserScriptsDlg.h @@ -0,0 +1,69 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_USERSCRIPTSDLG_H__6A37EE40_9653_11D5_89B3_00E07D97C331__INCLUDED_) +#define AFX_USERSCRIPTSDLG_H__6A37EE40_9653_11D5_89B3_00E07D97C331__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// UserScriptsDlg.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CUserScriptsDlg + +class CUserScriptsDlg : public CDialog +{ +// Konstruktion +public: + void ReportScriptError(int line); + CUserScriptsDlg(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CUserScriptsDlg) + enum { IDD = IDD_USERSCRIPTS }; + CString m_Script; + CString m_Report; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CUserScriptsDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CUserScriptsDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_USERSCRIPTSDLG_H__6A37EE40_9653_11D5_89B3_00E07D97C331__INCLUDED_ diff --git a/MissionEditor/Vec2.h b/MissionEditor/Vec2.h new file mode 100644 index 0000000..2876ff8 --- /dev/null +++ b/MissionEditor/Vec2.h @@ -0,0 +1,243 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#pragma once + +#include + +struct CSMap {}; +struct CSProjected {}; + +template +struct Vec2 +{ +public: + Vec2() = default; + Vec2(T x_, T y_) : x(x_), y(y_) {} + bool operator==(const Vec2& other) const = default; + + inline Vec2& operator +=(const Vec2& other) { + x += other.x; + y += other.y; + return *this; + } + + inline Vec2& operator -=(const Vec2& other) { + x -= other.x; + y -= other.y; + return *this; + } + + inline Vec2& operator *=(const T v) + { + x *= v; + y *= v; + return *this; + } + + inline Vec2& operator *=(const Vec2& other) + { + x *= other.x; + y *= other.y; + return *this; + } + + inline Vec2& operator /=(const Vec2& other) + { + x /= other.x; + y /= other.y; + return *this; + } + + inline Vec2& operator /=(const T v) + { + x /= v; + y /= v; + return *this; + } + + void set(const T x_, const T y_) + { + x = x_; + y = y_; + } + + template + inline Vec2 convertT() const + { + return Vec2(static_cast(x), static_cast(y)); + } + + inline Vec2 inverted() const + { + return Vec2(1.0f / static_cast(x), 1.0f / static_cast(y)); + } + + inline Vec2 negated() const + { + return Vec2(-x, -y); + } + +public: + T x = 0; + T y = 0; +}; + +template +inline Vec2 operator+(const Vec2& l, const Vec2& r) +{ + auto res = l; + res += r; + return res; +} + +template +inline Vec2 operator-(const Vec2& l, const Vec2& r) +{ + auto res = l; + res -= r; + return res; +} + +template +inline Vec2 operator*(const Vec2& l, const Vec2& r) +{ + auto res = l; + res *= r; + return res; +} + +template +inline Vec2 operator*(const Vec2& l, const Vec2& r) +{ + return Vec2(l.x * r.x, l.y * r.y); +} + +template +inline Vec2 operator*(const Vec2& l, const T r) +{ + auto res = l; + res *= r; + return res; +} + +template +inline Vec2 operator/(const Vec2& l, const Vec2& r) +{ + auto res = l; + res /= r; + return res; +} + +template +inline Vec2 operator/(const Vec2& l, const Vec2& r) +{ + return Vec2(l.x / r.x, l.y / r.y); +} + +template +inline Vec2 operator/(const Vec2& l, const T r) +{ + auto res = l; + res /= r; + return res; +} + +template +struct Coords2 +{ + Coords2() = default; + Coords2(T x_, T y_) : x(x_), y(y_) {} + bool operator==(const Coords2& other) const = default; + T x = 0; + T y = 0; + Coords2& operator +=(const Vec2& other) { + x += other.x; + y += other.y; + return *this; + } + Coords2& operator -=(const Vec2& other) { + x -= other.x; + y -= other.y; + return *this; + } + void set(const T x_, const T y_) + { + x = x_; + y = y_; + } + template + inline Coords2 convertT() const + { + return Coords2(static_cast(x), static_cast(y)); + } +}; + + +template +inline Coords2 operator+(const Coords2& l, const Vec2& r) +{ + auto res = l; + res += r; + return res; +} + +template +inline Coords2 operator-(const Coords2& l, const Vec2& r) +{ + auto res = l; + res -= r; + return res; +} + +template +inline Vec2 operator-(const Coords2& l, const Coords2& r) +{ + return Vec2(l.x - r.x, l.y - r.y); +} + +template +inline Coords2 operator*(const Coords2& l, const Vec2& r) +{ + return Coords2(l.x * r.x, l.y * r.y); +} + +template +inline Coords2 operator*(const Coords2& l, const Vec2& r) +{ + return Coords2(l.x * r.x, l.y * r.y); +} + +template +inline Coords2 operator/(const Coords2& l, const Vec2& r) +{ + return Coords2(l.x / r.x, l.y / r.y); +} + + +typedef Vec2 MapVec; + +/// +/// Logical map coordinates in tiles +/// +typedef Coords2 MapCoords; + +typedef Vec2 ProjectedVec; +typedef Coords2 ProjectedCoords; \ No newline at end of file diff --git a/MissionEditor/ViewObjects.cpp b/MissionEditor/ViewObjects.cpp new file mode 100644 index 0000000..28a0782 --- /dev/null +++ b/MissionEditor/ViewObjects.cpp @@ -0,0 +1,1407 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// ViewObjects.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "ViewObjects.h" +#include "FinalSunDlg.h" +#include "structs.h" +#include "mapdata.h" +#include "variables.h" +#include "functions.h" +#include "inlines.h" +#include "rtpdlg.h" +#include "TubeTool.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CViewObjects + +const int valadded=10000; + +IMPLEMENT_DYNCREATE(CViewObjects, CTreeView) + +CViewObjects::CViewObjects() +{ + m_ready=FALSE; + +} + +CViewObjects::~CViewObjects() +{ +} + + +BEGIN_MESSAGE_MAP(CViewObjects, CTreeView) + //{{AFX_MSG_MAP(CViewObjects) + ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged) + ON_WM_CREATE() + ON_NOTIFY_REFLECT(TVN_KEYDOWN, OnKeydown) + ON_WM_KEYDOWN() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +extern int overlay_number[]; +extern CString overlay_name[]; +extern BOOL overlay_visible[]; +extern BOOL overlay_trail[]; + + +extern int overlay_count; + + +extern ACTIONDATA AD; + +///////////////////////////////////////////////////////////////////////////// +// Zeichnung CViewObjects + +void CViewObjects::OnDraw(CDC* pDC) +{ + CDocument* pDoc = GetDocument(); + // ZU ERLEDIGEN: Code zum Zeichnen hier einfĂ¼gen +} + +///////////////////////////////////////////////////////////////////////////// +// Diagnose CViewObjects + +#ifdef _DEBUG +void CViewObjects::AssertValid() const +{ + CTreeView::AssertValid(); +} + +void CViewObjects::Dump(CDumpContext& dc) const +{ + CTreeView::Dump(dc); +} +#endif //_DEBUG + +CString GetTheaterLanguageString(LPCSTR lpString) +{ + CString s=lpString; + CString t=lpString; + + if((tiledata)==&t_tiledata) t+="TEM"; + if((tiledata)==&s_tiledata) t+="SNO"; + if((tiledata)==&u_tiledata) t+="URB"; + if((tiledata)==&un_tiledata) t+="UBN"; + if((tiledata)==&l_tiledata) t+="LUN"; + if((tiledata)==&d_tiledata) t+="DES"; + + CString res=GetLanguageStringACP(t); + if(res.GetLength()==0) res=GetLanguageStringACP(s); + + return res; +} + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CViewObjects + + +void CViewObjects::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult) +{ + CIniFile& ini=Map->GetIniFile(); + + NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; + + int val=pNMTreeView->itemNew.lParam; + if(val<0){ // return; + if(val==-2) { + AD.reset(); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + } + return; + } + + if(valm_view.m_isoview, true)); + break; + } + case 51: + { + AD.mode = ACTIONMODE_MAPTOOL; + AD.tool.reset(new ModifyTubeTool(*Map, *((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview, true)); + break; + } + case 52: + { + AD.mode = ACTIONMODE_MAPTOOL; + AD.tool.reset(new AddTubeTool(*Map, *((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview, false)); + break; + } + case 53: + { + AD.mode = ACTIONMODE_MAPTOOL; + AD.tool.reset(new ModifyTubeTool(*Map, *((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview, false)); + break; + } + case 54: + { + AD.mode=ACTIONMODE_MAPTOOL; + AD.tool.reset(new RemoveTubeTool(*Map, *((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview)); + break; + } + + case 61: + if(!tiledata_count) break; + AD.type=0; + AD.mode=ACTIONMODE_SETTILE; + AD.data=0; + AD.z_data=0; + HandleBrushSize(0); + break; + + case 62: + int i; + if(!tiledata_count) break; + for(i=0;i<(*tiledata_count);i++) + if((*tiledata)[i].wTileSet==atoi((*tiles).sections["General"].values["SandTile"])) break; + AD.type=i; + AD.mode=ACTIONMODE_SETTILE; + AD.data=0; + AD.z_data=0; + HandleBrushSize(i); + break; + case 63: + if(!tiledata_count) break; + for(i=0;i<(*tiledata_count);i++) + if((*tiledata)[i].wTileSet==atoi((*tiles).sections["General"].values["RoughTile"])) break; + AD.type=i; + AD.mode=ACTIONMODE_SETTILE; + AD.data=0; + AD.z_data=0; + HandleBrushSize(i); + break; + case 64: + if(!tiledata_count) break; + for(i=0;i<(*tiledata_count);i++) + if((*tiledata)[i].wTileSet==waterset) break; + + if(((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_x<2 || + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_y<2) + { + + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_settingsbar.m_BrushSize=1; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_settingsbar.UpdateData(FALSE); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_x=2; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_y=2; + } + + AD.type=i; + AD.mode=ACTIONMODE_SETTILE; + AD.data=1; // use water placement logic + AD.z_data=0; + break; + case 65: + if(!tiledata_count) break; + for(i=0;i<(*tiledata_count);i++) + if((*tiledata)[i].wTileSet==atoi((*tiles).sections["General"].values["GreenTile"])) break; + AD.type=i; + AD.mode=ACTIONMODE_SETTILE; + AD.data=0; + AD.z_data=0; + HandleBrushSize(i); + break; + case 66: + if(!tiledata_count) break; + for(i=0;i<(*tiledata_count);i++) + if((*tiledata)[i].wTileSet==atoi((*tiles).sections["General"].values["PaveTile"])) break; + AD.type=i; + AD.mode=ACTIONMODE_SETTILE; + AD.data=0; + AD.z_data=0; + HandleBrushSize(i); + break; + case 67: + if(!tiledata_count) break; + for(i=0;i<(*tiledata_count);i++) + if((*tiledata)[i].wTileSet==atoi(g_data.sections["NewUrbanInfo"].values["Morphable2"])) break; + AD.type=i; + AD.mode=ACTIONMODE_SETTILE; + AD.data=0; + AD.z_data=0; + HandleBrushSize(i); + break; + + + } + } + else + { + int subpos=val%valadded; + int pos=val/valadded; + + AD.mode=1; + AD.type=pos; + AD.data=subpos; + + if(pos==1) + { + CString sec="InfantryTypes"; + + if(subpos=30) {AD.data=30;AD.data2=subpos%1000;} + } + } + else if(pos==7) + { + // set owner + //if(ini.sections.find(MAPHOUSES)!=ini.sections.end() && ini.sections[MAPHOUSES].values.size()>0) + if(ini.sections.find(MAPHOUSES)!=ini.sections.end() && ini.sections[MAPHOUSES].values.size()>0) + { + AD.data_s=*ini.sections[MAPHOUSES].GetValue(subpos); + } + else + { + AD.data_s=*rules.sections[HOUSES].GetValue(subpos); + } + + currentOwner=AD.data_s; + } +#ifdef SMUDGE_SUPP + else if(pos==8) + { + + + CString sec="SmudgeTypes"; + + if(subposGetIniFile(); + + tree.Select(0,TVGN_CARET ); + tree.DeleteAllItems(); + + CString sTreeRoots[15]; + sTreeRoots[0]=GetLanguageStringACP("InfantryObList"); + sTreeRoots[1]=GetLanguageStringACP("VehiclesObList"); + sTreeRoots[2]=GetLanguageStringACP("AircraftObList"); + sTreeRoots[3]=GetLanguageStringACP("StructuresObList"); + sTreeRoots[4]=GetLanguageStringACP("TerrainObList"); + sTreeRoots[5]=GetLanguageStringACP("OverlayObList"); + sTreeRoots[6]=GetLanguageStringACP("WaypointsObList"); + sTreeRoots[7]=GetLanguageStringACP("CelltagsObList"); + sTreeRoots[8]=GetLanguageStringACP("BaseNodesObList"); + sTreeRoots[9]=GetLanguageStringACP("TunnelObList"); + sTreeRoots[10]=GetLanguageStringACP("DelObjObList"); + sTreeRoots[11]=GetLanguageStringACP("ChangeOwnerObList"); + sTreeRoots[12]=GetLanguageStringACP("StartpointsObList"); + sTreeRoots[13]=GetLanguageStringACP("GroundObList"); + sTreeRoots[14]=GetLanguageStringACP("SmudgesObList"); + + int i=0; + + //TV_InsertItemW(tree.m_hWnd, L"HELLO", 5, TVI_LAST, TVI_ROOT, -2); + + HTREEITEM first=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, + TranslateStringACP(GetLanguageStringACP("NothingObList")), i, i, 0, 0, -2, TVI_ROOT, TVI_LAST); + + HTREEITEM rootitems[15]; + + // we want the change owner at the top + + if(!Map->IsMultiplayer() || !theApp.m_Options.bEasy) + rootitems[11]=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, + TranslateStringACP(sTreeRoots[11]), i, i, 0, 0, i, TVI_ROOT, TVI_LAST); + + + for(i=0;i<10;i++) + { + BOOL bAllow=TRUE; + if(theApp.m_Options.bEasy) + { + if(i>=6 && i<=9) + bAllow=FALSE; + } + + // no tunnels in ra2 mode + if(editor_mode==ra2_mode && i==9 && !isTrue(g_data.sections["Debug"].values["AllowTunnels"])) bAllow=FALSE; + + if(bAllow) + rootitems[i]=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, + sTreeRoots[i], i, i, 0, 0, i, TVI_ROOT, TVI_LAST); + } + + + rootitems[13]=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, TranslateStringACP(sTreeRoots[13]), 13, 13, 0, 0, 13, TVI_ROOT, first); + + rootitems[12]=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, + TranslateStringACP(sTreeRoots[12]), 12,12, 0, 0, 12, TVI_ROOT, TVI_LAST); + + rootitems[10]=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, + TranslateStringACP(sTreeRoots[10]), 10, 10, 0, 0, 10, TVI_ROOT, TVI_LAST); + +#ifdef SMUDGE_SUPP + rootitems[14]=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, + TranslateStringACP(sTreeRoots[14]), 14, 14, 0, 0, 10, TVI_ROOT, rootitems[4]); +#endif + + + HTREEITEM structhouses[64]; +#ifdef RA2_MODE + HTREEITEM hAllied=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("Allied"), 0, 0,0,0,-1,rootitems[3], TVI_LAST); + HTREEITEM hSoviet=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("Soviet"), 0, 0,0,0,-1,rootitems[3], TVI_LAST); + HTREEITEM hYuri=NULL; + if(yuri_mode) + { + hYuri=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("Yuri"), 0, 0, 0, 0, -1, rootitems[3], TVI_LAST); + } + + for(i=0;iIsMultiplayer()) + max=1; + else + { + + } + for(e=0;eGetTheater()==THEATER3) + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetTheaterLanguageString("GroundPave2ObList"),0,0,0,0,67,rootitems[13], TVI_LAST); +#endif + + if(!theApp.m_Options.bEasy) + { + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("CreateCelltagObList"), 0,0,0,0, 36, rootitems[7], TVI_LAST ); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("DelCelltagObList"), 0,0,0,0, 37, rootitems[7], TVI_LAST ); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("CelltagPropObList"), 0,0,0,0, 38, rootitems[7], TVI_LAST ); + } + + if(!theApp.m_Options.bEasy) + { + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("CreateNodeNoDelObList"), 0,0,0,0, 40, rootitems[8], TVI_LAST ); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("CreateNodeDelObList"), 0,0,0,0, 41, rootitems[8], TVI_LAST ); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("DelNodeObList"), 0,0,0,0, 42, rootitems[8], TVI_LAST ); + } + + + HTREEITEM deleteoverlay=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("DelOvrlObList"), 0,0,0,0, -1, rootitems[5], TVI_LAST ); + HTREEITEM tiberium=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("GrTibObList"), 0,0,0,0, -1, rootitems[5], TVI_LAST ); + //HTREEITEM bluetiberium=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("BlTibObList"), 0,0,0,0, -1, rootitems[5], TVI_LAST ); +#ifndef RA2_MODE + HTREEITEM veinhole=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("VeinholeObList"), 0,0,0,0, -1, rootitems[5], TVI_LAST ); +#endif + HTREEITEM bridges=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("BridgesObList"), 0,0,0,0, -1, rootitems[5], TVI_LAST ); + HTREEITEM alloverlay=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("OthObList"), 0,0,0,0, -1, rootitems[5], TVI_LAST ); + HTREEITEM everyoverlay=NULL; + + if(!theApp.m_Options.bEasy) + { + everyoverlay=tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("AllObList"), 0,0,0,0, -1, rootitems[5], TVI_LAST ); + } + + + if(!theApp.m_Options.bEasy) + { + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("OvrlManuallyObList"), 0,0,0,0, valadded*6+1, rootitems[5], TVI_LAST ); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("OvrlDataManuallyObList"), 0,0,0,0, valadded*6+2, rootitems[5], TVI_LAST ); + } + + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("DelOvrl0ObList"), 0,0,0,0, valadded*6+100+0, deleteoverlay, TVI_LAST ); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("DelOvrl1ObList"), 0,0,0,0, valadded*6+100+1, deleteoverlay, TVI_LAST ); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("DelOvrl2ObList"), 0,0,0,0, valadded*6+100+2, deleteoverlay, TVI_LAST ); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("DelOvrl3ObList"), 0,0,0,0, valadded*6+100+3, deleteoverlay, TVI_LAST ); + + //tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("DrawRanTibObList"), 0,0,0,0, valadded*6+200+0, tiberium, TVI_LAST ); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("DrawTibObList"), 0,0,0,0, valadded*6+200+10, tiberium, TVI_LAST ); + //tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("IncTibSizeObList"), 0,0,0,0, valadded*6+200+20, tiberium, TVI_LAST ); + //tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("DecTibSizeObList"), 0,0,0,0, valadded*6+200+21, tiberium, TVI_LAST ); + + //tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("DrawRanTibObList"), 0,0,0,0, valadded*6+300+0, bluetiberium, TVI_LAST ); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("DrawTib2ObList"), 0,0,0,0, valadded*6+300+10, tiberium, TVI_LAST ); + //tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("IncTibSizeObList"), 0,0,0,0, valadded*6+300+20, bluetiberium, TVI_LAST ); + //tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("DecTibSizeObList"), 0,0,0,0, valadded*6+300+21, bluetiberium, TVI_LAST ); +#ifndef RA2_MODE + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("VeinholeObList"), 0,0,0,0, valadded*6+400+0, veinhole, TVI_LAST ); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("VeinsObList"), 0,0,0,0, valadded*6+400+1, veinhole, TVI_LAST ); +#endif + + if(Map->GetTheater()!=THEATER4 && Map->GetTheater()!=THEATER5) + { + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("SmallBridgeObList"), 0,0,0,0, valadded*6+500+1, bridges, TVI_LAST ); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("BigBridgeObList"), 0,0,0,0, valadded*6+500+0, bridges, TVI_LAST ); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("BigTrackBridgeObList"), 0,0,0,0, valadded*6+500+2, bridges, TVI_LAST ); +#ifdef RA2_MODE + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("SmallConcreteBridgeObList"), 0,0,0,0, valadded*6+500+3, bridges, TVI_LAST ); +#endif + } + else + { + if(Map->GetTheater()==THEATER5) + { + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("SmallBridgeObList"), 0,0,0,0, valadded*6+500+1, bridges, TVI_LAST ); +#ifdef RA2_MODE + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("SmallConcreteBridgeObList"), 0,0,0,0, valadded*6+500+3, bridges, TVI_LAST ); +#endif + } + + } + +#ifndef RA2_MODE + if (!theApp.m_Options.bEasy && isTrue(g_data.sections["Debug"].values["AllowTunnels"])) + { + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("NewTunnelObList"), 0, 0, 0, 0, 50, rootitems[9], TVI_LAST); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("ModifyTunnelObList"), 0, 0, 0, 0, 51, rootitems[9], TVI_LAST); + if (isTrue(g_data.sections["Debug"].values["AllowUnidirectionalTunnels"])) + { + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("NewTunnelSingleObList"), 0, 0, 0, 0, 52, rootitems[9], TVI_LAST); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("ModifyTunnelSingleObList"), 0, 0, 0, 0, 53, rootitems[9], TVI_LAST); + } + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("DelTunnelObList"), 0, 0, 0, 0, 54, rootitems[9], TVI_LAST); + } +#else + if (!theApp.m_Options.bEasy && isTrue(g_data.sections["Debug"].values["AllowTunnels"])) + { + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("NewTunnelObList"), 0, 0, 0, 0, 50, rootitems[9], TVI_LAST); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("ModifyTunnelObList"), 0, 0, 0, 0, 51, rootitems[9], TVI_LAST); + if (isTrue(g_data.sections["Debug"].values["AllowUnidirectionalTunnels"])) + { + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("NewTunnelSingleObList"), 0, 0, 0, 0, 52, rootitems[9], TVI_LAST); + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("ModifyTunnelSingleObList"), 0, 0, 0, 0, 53, rootitems[9], TVI_LAST); + } + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("DelTunnelObList"), 0,0,0,0, 54, rootitems[9], TVI_LAST ); + } +#endif + + + int lv=1; + + if(!theApp.m_Options.bEasy || !Map->IsMultiplayer()) + { + if(ini.sections.find(MAPHOUSES)!=ini.sections.end() && ini.sections[MAPHOUSES].values.size()>0) + { + for(i=0;i0) + { + if(ini.sections[MAPHOUSES].FindValue("Neutral")>=0) + currentOwner="Neutral"; + else + currentOwner=*ini.sections[MAPHOUSES].GetValue(0); + } + else + currentOwner="Neutral"; + + } + + + for(i=0;i=0) id = id.Left(id.Find(' ')); + if(id.GetLength()>0) + { + + CString unitname=*rules.sections["OverlayTypes"].GetValue(i); + +#ifdef RA2_MODE + if (Map->GetTheater()==THEATER0 && g_data.sections["IgnoreTemperateRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER1 && g_data.sections["IgnoreSnowRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER2 && g_data.sections["IgnoreUrbanRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER3 && g_data.sections["IgnoreNewUrbanRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER4 && g_data.sections["IgnoreLunarRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER5 && g_data.sections["IgnoreDesertRA2"].FindValue(unitname) >= 0) continue; +#else + if (Map->GetTheater()==THEATER0 && g_data.sections["IgnoreTemperateTS"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER1 && g_data.sections["IgnoreSnowTS"].FindValue(unitname) >= 0) continue; +#endif + +#ifdef RA2_MODE + if((i>=39 && i<=60) || (i>=180 && i<=201) || i==239 || i==178 || i==167 || i==126 + || (i>=122 && i<=125) || i==1 || (i>=0x03 && i<=0x17) || (i>=0x3d && i<=0x43) + || (i>=0x4a && i<=0x65) || (i>=0xcd && i<=0xec)) + { + if(!isTrue(g_data.sections["Debug"].values["DisplayAllOverlay"])) + { + e++; + continue; + } + } + + +#endif + + CString val=*rules.sections["OverlayTypes"].GetValue(i); +#ifdef RA2_MODE + val.Replace("TIB", "ORE"); +#endif + + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, val , 0,0,0,0, valadded*6+3000+e, everyoverlay, TVI_LAST ); + e++; + } + } + } + + + for(i=0;iGetTheater()==THEATER0 && g_data.sections["IgnoreTemperateRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER1 && g_data.sections["IgnoreSnowRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER2 && g_data.sections["IgnoreUrbanRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER3 && g_data.sections["IgnoreNewUrbanRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER4 && g_data.sections["IgnoreLunarRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER5 && g_data.sections["IgnoreDesertRA2"].FindValue(unitname) >= 0) continue; +#else + if (Map->GetTheater()==THEATER0 && g_data.sections["IgnoreTemperateTS"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER1 && g_data.sections["IgnoreSnowTS"].FindValue(unitname) >= 0) continue; +#endif + +#ifdef RA2_MODE + if(g_data.sections["IgnoreRA2"].FindValue(unitname)>=0) continue; +#else + if(g_data.sections["IgnoreTS"].FindValue(unitname) >= 0) continue; +#endif + + WCHAR* addedString=Map->GetUnitName(unitname); + if(!addedString) continue; + + //addedString=TranslateStringACP(addedString); + + //addedString+=" ("; + //addedString+=unitname+")"; + + TV_InsertItemW(tree.m_hWnd, addedString, wcslen(addedString), TVI_LAST, rootitems[0], valadded*1+i); + + //tree.InsertItem(TVIF_PARAM | TVIF_TEXT, addedString, 0,0,0,0, valadded*1+i, rootitems[0], TVI_LAST ); + lv=i; + } + lv+=1; + // okay, now the user-defined types: + for(i=0;iGetLength()==0) continue; + + if(strlen(ini.sections[*ini.sections["InfantryTypes"].GetValue(i)].values["Name"])>0) + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, ini.sections[*ini.sections["InfantryTypes"].GetValue(i)].values["Name"], 0,0,0,0, valadded*1+rules.sections["InfantryTypes"].values.size()+i, rootitems[0], TVI_LAST ); + else + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, (*ini.sections["InfantryTypes"].GetValue(i)+" NOTDEFINED"), 0,0,0,0, valadded*1+rules.sections["InfantryTypes"].values.size()+i, rootitems[0], TVI_LAST ); + + + } + + CString theater=Map->GetTheater(); + + + auto needed_terrain=TheaterChar::None; + if(tiledata==&s_tiledata) needed_terrain=TheaterChar::A; + else if(tiledata==&t_tiledata) needed_terrain=TheaterChar::T; + + for(i=0;iGetTheater()==THEATER0 && g_data.sections["IgnoreTemperateRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER1 && g_data.sections["IgnoreSnowRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER2 && g_data.sections["IgnoreUrbanRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER3 && g_data.sections["IgnoreNewUrbanRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER4 && g_data.sections["IgnoreLunarRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER5 && g_data.sections["IgnoreDesertRA2"].FindValue(unitname) >= 0) continue; +#else + if (Map->GetTheater()==THEATER0 && g_data.sections["IgnoreTemperateTS"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER1 && g_data.sections["IgnoreSnowTS"].FindValue(unitname) >= 0) continue; +#endif + +#ifdef RA2_MODE + if (g_data.sections["IgnoreRA2"].FindValue(unitname) >= 0) continue; +#else + if (g_data.sections["IgnoreTS"].FindValue(unitname) >= 0) continue; +#endif + if (!isTrue(g_data.sections["Debug"].GetValueByName("ShowBuildingsWithToTile", "0")) && !rules.sections[unitname].GetValueByName("ToTile").IsEmpty()) + continue; + + + WCHAR* addedString=Map->GetUnitName(unitname); + if(!addedString) continue; + + + + CString owner=rules.sections[unitname].values["Owner"]; + int baseplanningside=-1; +#ifdef RA2_MODE + baseplanningside=-1; +#endif + if(rules.sections[unitname].values.find("AIBasePlanningSide")!=rules.sections[unitname].values.end()) + { + baseplanningside=atoi(rules.sections[unitname].values["AIBasePlanningSide"]); + } + if(g_data.sections.find(unitname)!=g_data.sections.end() && g_data.sections[unitname].values.find("AIBasePlanningSide")!=g_data.sections[unitname].values.end()) + { + baseplanningside=atoi(g_data.sections[unitname].values["AIBasePlanningSide"]); + } + + + int id=Map->GetBuildingID(unitname); + if(id<0 /*|| (buildinginfo[id].pic[0].bTerrain!=0 && buildinginfo[id].pic[0].bTerrain!=needed_terrain)*/) + continue; + + if(theater==THEATER0 && !buildinginfo[id].bTemp) { /*MessageBox("Ignored", unitname,0);*/ continue;} + if(theater==THEATER1 && !buildinginfo[id].bSnow) { /*MessageBox("Ignored", unitname,0);*/ continue;} + if(theater==THEATER2 && !buildinginfo[id].bUrban) { /*MessageBox("Ignored", unitname,0);*/ continue;} + + // check if mapfile contains other value for owner + if(ini.sections.find(unitname)!=ini.sections.end()) + { + if(ini.sections[unitname].values.find("Owner")!=ini.sections[unitname].values.end()) + owner=ini.sections[unitname].values["Owner"]; + } + + //addedString=TranslateStringACP(addedString); + + //addedString+=" ("; + //addedString+=unitname+")"; + + BOOL addedfor[3]={FALSE,FALSE,FALSE}; + + // MW fixed below for YR... uhhh... + int e; + BOOL bAdded=FALSE; + for(e=0;eGetLength()==0) continue; + + int id=Map->GetBuildingID(*ini.sections["BuildingTypes"].GetValue(i)); + if(id<0 || (buildinginfo[id].pic[0].bTerrain!=TheaterChar::None && buildinginfo[id].pic[0].bTerrain!=needed_terrain)) + continue; + + int e=2; + CString owner; + BOOL bAdded=FALSE; + owner=ini.sections[*ini.sections["BuildingTypes"].GetValue(i)].values["Owner"]; + owner.MakeUpper(); + if(strlen(ini.sections[*ini.sections["BuildingTypes"].GetValue(i)].values["Name"])>0) + { + CString addedString=ini.sections[*ini.sections["BuildingTypes"].GetValue(i)].values["Name"]; + int e; + for(e=0;eGetTheater()==THEATER0 && g_data.sections["IgnoreTemperateRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER1 && g_data.sections["IgnoreSnowRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER2 && g_data.sections["IgnoreUrbanRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER3 && g_data.sections["IgnoreNewUrbanRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER4 && g_data.sections["IgnoreLunarRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER5 && g_data.sections["IgnoreDesertRA2"].FindValue(unitname) >= 0) continue; +#else + if (Map->GetTheater()==THEATER0 && g_data.sections["IgnoreTemperateTS"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER1 && g_data.sections["IgnoreSnowTS"].FindValue(unitname) >= 0) continue; +#endif + +#ifdef RA2_MODE + if (g_data.sections["IgnoreRA2"].FindValue(unitname) >= 0) continue; +#else + if (g_data.sections["IgnoreTS"].FindValue(unitname) >= 0) continue; +#endif + + WCHAR* addedString=Map->GetUnitName(unitname); + if(!addedString) continue; + + //addedString=TranslateStringACP(addedString); + + //addedString+=" ("; + //addedString+=unitname+")"; + + TV_InsertItemW(tree.m_hWnd, addedString, wcslen(addedString), TVI_LAST, rootitems[2], valadded*3+i); + + //tree.InsertItem(TVIF_PARAM | TVIF_TEXT, addedString, 0,0,0,0, valadded*3+i, rootitems[2], TVI_LAST ); + lv=i; + } + lv+=1; + // okay, now the user-defined types: + for(i=0;iGetLength()==0) continue; + + if(strlen(ini.sections[*ini.sections["AircraftTypes"].GetValue(i)].values["Name"])>0) + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, ini.sections[*ini.sections["AircraftTypes"].GetValue(i)].values["Name"], 0,0,0,0, valadded*3+i+rules.sections["AircraftTypes"].values.size(), rootitems[2], TVI_LAST ); + else + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, (*ini.sections["AircraftTypes"].GetValue(i)+" NOTDEFINED"), 0,0,0,0, valadded*3+i+rules.sections["AircraftTypes"].values.size(), rootitems[2], TVI_LAST ); + + + } + + + for(i=0;iGetTheater()==THEATER0 && g_data.sections["IgnoreTemperateRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER1 && g_data.sections["IgnoreSnowRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER2 && g_data.sections["IgnoreUrbanRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER3 && g_data.sections["IgnoreNewUrbanRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER4 && g_data.sections["IgnoreLunarRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER5 && g_data.sections["IgnoreDesertRA2"].FindValue(unitname) >= 0) continue; +#else + if (Map->GetTheater()==THEATER0 && g_data.sections["IgnoreTemperateTS"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER1 && g_data.sections["IgnoreSnowTS"].FindValue(unitname) >= 0) continue; +#endif + +#ifdef RA2_MODE + if (g_data.sections["IgnoreRA2"].FindValue(unitname) >= 0) continue; +#else + if (g_data.sections["IgnoreTS"].FindValue(unitname) >= 0) continue; +#endif + + WCHAR* addedString=Map->GetUnitName(unitname); + if(!addedString) continue; + + //addedString=TranslateStringACP(addedString); + + //addedString+=" ("; + //addedString+=unitname+")"; + + TV_InsertItemW(tree.m_hWnd, addedString, wcslen(addedString), TVI_LAST, rootitems[1], valadded*4+i); + + //tree.InsertItem(TVIF_PARAM | TVIF_TEXT, addedString, 0,0,0,0, valadded*4+i, rootitems[1], TVI_LAST ); + lv=i; + } + lv+=1; + // okay, now the user-defined types: + for(i=0;iGetLength()==0) continue; + + if(strlen(ini.sections[*ini.sections["VehicleTypes"].GetValue(i)].values["Name"])>0) + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, ini.sections[*ini.sections["VehicleTypes"].GetValue(i)].values["Name"], 0,0,0,0, valadded*4+i+rules.sections["VehicleTypes"].values.size(), rootitems[1], TVI_LAST ); + else + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, (*ini.sections["VehicleTypes"].GetValue(i)+" NOTDEFINED"), 0,0,0,0, valadded*4+i+rules.sections["VehicleTypes"].values.size(), rootitems[1], TVI_LAST ); + + + } + + + #ifdef RA2_MODE + HTREEITEM hTrees=tree.InsertItem(GetLanguageStringACP("TreesObList"), rootitems[4], TVI_LAST); + HTREEITEM hTL=tree.InsertItem(GetLanguageStringACP("TrafficLightsObList"), rootitems[4], TVI_LAST); + HTREEITEM hSigns=tree.InsertItem(GetLanguageStringACP("SignsObList"), rootitems[4], TVI_LAST); + HTREEITEM hLightPosts=tree.InsertItem(GetLanguageStringACP("LightPostsObList"), rootitems[4], TVI_LAST); + #endif + + // random tree placer +#ifdef RA2_MODE + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("RndTreeObList"), 0,0,0,0, valadded*5+999, hTrees, TVI_LAST); +#else + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, GetLanguageStringACP("RndTreeObList"), 0,0,0,0, valadded*5+999, rootitems[4], TVI_LAST); +#endif + + for(i=0;iGetUnitName(unitname); + +#ifdef RA2_MODE + if (Map->GetTheater()==THEATER0 && g_data.sections["IgnoreTemperateRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER1 && g_data.sections["IgnoreSnowRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER2 && g_data.sections["IgnoreUrbanRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER3 && g_data.sections["IgnoreNewUrbanRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER4 && g_data.sections["IgnoreLunarRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER5 && g_data.sections["IgnoreDesertRA2"].FindValue(unitname) >= 0) continue; +#else + if (Map->GetTheater()==THEATER0 && g_data.sections["IgnoreTemperateTS"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER1 && g_data.sections["IgnoreSnowTS"].FindValue(unitname) >= 0) continue; +#endif + +#ifdef RA2_MODE + if (g_data.sections["IgnoreRA2"].FindValue(unitname) >= 0) continue; +#else + if (g_data.sections["IgnoreTS"].FindValue(unitname) >= 0) continue; +#endif +#ifdef RA2_MODE + if (g_data.sections["IgnoreTerrainRA2"].FindValue(unitname) >= 0) continue; +#else + if (g_data.sections["IgnoreTerrainTS"].FindValue(unitname) >= 0) continue; +#endif + + addedString=TranslateStringACP(addedString); + + UINT flags=MF_STRING; + + HTREEITEM howner=rootitems[4]; + + #ifdef RA2_MODE + if(unitname.Find("SIGN")>=0) howner=hSigns; + if(unitname.Find("TRFF")>=0) howner=hTL; + if(unitname.Find("TREE")>=0) howner=hTrees; + if(unitname.Find("LT")>=0) howner=hLightPosts; + #endif + +#ifdef RA2_MODE + if(howner==hTrees) + { + int TreeMin=atoi(g_data.sections[Map->GetTheater()+"Limits"].values["TreeMin"]); + int TreeMax=atoi(g_data.sections[Map->GetTheater()+"Limits"].values["TreeMax"]); + + CString id=unitname; + id.Delete(0, 4); + int n=atoi(id); + + if(nTreeMax) continue; + } +#endif + + if(unitname.GetLength()>0 && unitname!="VEINTREE" && unitname.Find("ICE")<0 && unitname.Find("BOXES")<0 && unitname.Find("SPKR")<0) // out with it :-) + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, (addedString+ " (" + unitname +")"), 0,0,0,0, valadded*5+i, howner, TVI_LAST ); + + lv=i; + } + +#ifdef SMUDGE_SUPP + for(i=0;iGetTheater()==THEATER0 && g_data.sections["IgnoreTemperateRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER1 && g_data.sections["IgnoreSnowRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER2 && g_data.sections["IgnoreUrbanRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER3 && g_data.sections["IgnoreNewUrbanRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER4 && g_data.sections["IgnoreLunarRA2"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER5 && g_data.sections["IgnoreDesertRA2"].FindValue(unitname) >= 0) continue; +#else + if (Map->GetTheater()==THEATER0 && g_data.sections["IgnoreTemperateTS"].FindValue(unitname) >= 0) continue; + if (Map->GetTheater()==THEATER1 && g_data.sections["IgnoreSnowTS"].FindValue(unitname) >= 0) continue; +#endif + +#ifdef RA2_MODE + if (g_data.sections["IgnoreRA2"].FindValue(unitname) >= 0) continue; +#else + if (g_data.sections["IgnoreTS"].FindValue(unitname) >= 0) continue; +#endif + + addedString=TranslateStringACP(addedString); + + UINT flags=MF_STRING; + + HTREEITEM howner=rootitems[14]; + + + if(unitname.GetLength()>0) + tree.InsertItem(TVIF_PARAM | TVIF_TEXT, unitname, 0,0,0,0, valadded*8+i, howner, TVI_LAST ); + + lv=i; + } +#endif + + + + OutputDebugString("Objectbrowser redraw finished\n"); + + +} + +int CViewObjects::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + lpCreateStruct->style|=TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_SHOWSELALWAYS; + if (CTreeView::OnCreate(lpCreateStruct) == -1) + return -1; + + + return 0; +} + +void CViewObjects::OnInitialUpdate() +{ + CTreeView::OnInitialUpdate(); + + + m_ready=TRUE; +} + +void CViewObjects::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult) +{ + TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR; + // TODO: Code fĂ¼r die Behandlungsroutine der Steuerelement-Benachrichtigung hier einfĂ¼gen + + *pResult = 0; +} + +void CViewObjects::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + // TODO: Code fĂ¼r die Behandlungsroutine fĂ¼r Nachrichten hier einfĂ¼gen und/oder Standard aufrufen + + // CTreeView::OnKeyDown(nChar, nRepCnt, nFlags); +} + +void CViewObjects::HandleBrushSize(int iTile) +{ + if(iTile>=*tiledata_count) return; + + int i; + for(i=0;i=0) + { + int tset=atoi((*tiles).sections["General"].values[n]); + if(tset==(*tiledata)[iTile].wTileSet) + { + int bs=atoi(*g_data.sections["StdBrushSize"].GetValue(i)); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_settingsbar.m_BrushSize=bs-1; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_settingsbar.UpdateData(FALSE); + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_x=bs; + ((CFinalSunDlg*)theApp.m_pMainWnd)->m_view.m_isoview->m_BrushSize_y=bs; + } + } + } + +} diff --git a/MissionEditor/ViewObjects.h b/MissionEditor/ViewObjects.h new file mode 100644 index 0000000..a431e83 --- /dev/null +++ b/MissionEditor/ViewObjects.h @@ -0,0 +1,86 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_VIEWOBJECTS_H__360F4320_9B82_11D3_B63B_EC44EDA1D441__INCLUDED_) +#define AFX_VIEWOBJECTS_H__360F4320_9B82_11D3_B63B_EC44EDA1D441__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ViewObjects.h : Header-Datei +// +#include + + + +///////////////////////////////////////////////////////////////////////////// +// Ansicht CViewObjects + +class CViewObjects : public CTreeView +{ +protected: + CViewObjects(); // Dynamische Erstellung verwendet geschĂ¼tzten Konstruktor + DECLARE_DYNCREATE(CViewObjects) + +// Attribute +public: + +// Operationen +public: + CTreeCtrl* tree; + BOOL m_ready; + void UpdateDialog(); + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CViewObjects) + public: + virtual void OnInitialUpdate(); + protected: + virtual void OnDraw(CDC* pDC); // Ăœberschrieben zum Zeichnen dieser Ansicht + //}}AFX_VIRTUAL + +// Implementierung +protected: + virtual ~CViewObjects(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + // Generierte Nachrichtenzuordnungsfunktionen +protected: + //{{AFX_MSG(CViewObjects) + afx_msg void OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnKeydown(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + void HandleBrushSize(int iTile); +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_VIEWOBJECTS_H__360F4320_9B82_11D3_B63B_EC44EDA1D441__INCLUDED_ diff --git a/MissionEditor/WaypointID.cpp b/MissionEditor/WaypointID.cpp new file mode 100644 index 0000000..8d59d70 --- /dev/null +++ b/MissionEditor/WaypointID.cpp @@ -0,0 +1,110 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// WaypointID.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "FinalSun.h" +#include "WaypointID.h" +#include "mapdata.h" +#include "variables.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CWaypointID + + +CWaypointID::CWaypointID(CWnd* pParent /*=NULL*/) + : CDialog(CWaypointID::IDD, pParent) +{ + //{{AFX_DATA_INIT(CWaypointID) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Elementinitialisierung ein + //}}AFX_DATA_INIT +} + + +void CWaypointID::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CWaypointID) + DDX_Control(pDX, IDC_ID, m_id); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CWaypointID, CDialog) + //{{AFX_MSG_MAP(CWaypointID) + ON_BN_CLICKED(IDC_FREE, OnFree) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CWaypointID + +void CWaypointID::OnFree() +{ + CIniFile& ini=Map->GetIniFile(); + + int i; + CString freen; + + for(i=0;i>-1;i++) + { + char d[50]; + itoa(i,d,10); + if(ini.sections["Waypoints"].values.find(d)==ini.sections["Waypoints"].values.end()) + { + freen=d; + break; + } + } + + m_id.SetWindowText(freen); +} + +void CWaypointID::OnOK() +{ + CString h; + m_id.GetWindowText(h); + if(h.GetLength()<1) + { + return; + } + + m_value=atoi(h); + + CDialog::OnOK(); +} + +BOOL CWaypointID::OnInitDialog() +{ + CDialog::OnInitDialog(); + + OnFree(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} diff --git a/MissionEditor/WaypointID.h b/MissionEditor/WaypointID.h new file mode 100644 index 0000000..11f023a --- /dev/null +++ b/MissionEditor/WaypointID.h @@ -0,0 +1,69 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_WAYPOINTID_H__7F75C740_89FE_11D3_B63B_F82C84AD2A41__INCLUDED_) +#define AFX_WAYPOINTID_H__7F75C740_89FE_11D3_B63B_F82C84AD2A41__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// WaypointID.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CWaypointID + +class CWaypointID : public CDialog +{ +// Konstruktion +public: + int m_value; + CWaypointID(CWnd* pParent = NULL); // Standardkonstruktor + +// Dialogfelddaten + //{{AFX_DATA(CWaypointID) + enum { IDD = IDD_WAYPOINT }; + CEdit m_id; + //}}AFX_DATA + + +// Ăœberschreibungen + // Vom Klassen-Assistenten generierte virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CWaypointID) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CWaypointID) + afx_msg void OnFree(); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_WAYPOINTID_H__7F75C740_89FE_11D3_B63B_F82C84AD2A41__INCLUDED_ diff --git a/MissionEditor/Waypoints.cpp b/MissionEditor/Waypoints.cpp new file mode 100644 index 0000000..ef9a014 --- /dev/null +++ b/MissionEditor/Waypoints.cpp @@ -0,0 +1,205 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +// Waypoints.cpp: Implementierungsdatei +// + +#include "stdafx.h" +#include "TiberianSun Mission Editor.h" +#include "Waypoints.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Eigenschaftenseite CWaypoints + +IMPLEMENT_DYNCREATE(CWaypoints, CPropertyPage) + +CWaypoints::CWaypoints() : CPropertyPage(CWaypoints::IDD) +{ + //{{AFX_DATA_INIT(CWaypoints) + // HINWEIS: Der Klassen-Assistent fĂ¼gt hier Elementinitialisierung ein + //}}AFX_DATA_INIT +} + +CWaypoints::~CWaypoints() +{ +} + +void CWaypoints::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CWaypoints) + DDX_Control(pDX, IDC_DBG, m_dbg); + DDX_Control(pDX, IDC_WAYPOINTS, m_Waypoints); + DDX_Control(pDX, IDC_POS, m_Pos); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CWaypoints, CPropertyPage) + //{{AFX_MSG_MAP(CWaypoints) + ON_LBN_SELCHANGE(IDC_WAYPOINTS, OnSelchangeWaypoints) + ON_EN_KILLFOCUS(IDC_POS, OnKillfocusPos) + ON_WM_KILLFOCUS() + ON_WM_SHOWWINDOW() + ON_BN_CLICKED(IDC_DELETE, OnDelete) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// Behandlungsroutinen fĂ¼r Nachrichten CWaypoints + +void CWaypoints::UpdateDialog() +{ + m_Waypoints.SetRedraw(FALSE); + + // first clear the list + while(m_Waypoints.DeleteString(0)!=LB_ERR); + + // okay add all trees + + int i; + CIniFileSection& sec=ini.sections["Waypoints"]; + + char c[50]; + for(i=0;idata(); + + + str+=", "; + str+=sec.GetValue(i)->data(); + + int x,y,z; + GetXYPos((char*)sec.GetValue(i)->data(), &x, &y); + + + itoa(x, c,10); + str+=", "; + str+=c; + itoa(y, c,10); + str+="/"; + str+=c; + + z=GetPos(x, y, 0); + itoa(z, c, 10); + str+="/"; + str+=c; + + /*int pos=atoi(str); + + str+=(CString)" "+ sec.GetValue(i)->data(); + int x,y; + GetXYPos(atoi(sec.GetValueName(i)->data()), x, y); + char c[50]; + itoa(x, c, 10); + str+=" ("; + str+=c; + str+="/"; + itoa(y, c, 10); + str+=c; + str+=")";*/ + + m_Waypoints.InsertString(-1, str); + + } + + m_Waypoints.SetRedraw(TRUE); + +} + +void CWaypoints::OnSelchangeWaypoints() +{ + int i=m_Waypoints.GetCurSel(); + if(i==-1) return; + + CString str; + m_Waypoints.GetText(i, str); + + str.SetAt(str.Find(",",0), 0); + + // ok str now specifies the waypoint id + m_Pos.SetWindowText(ini.sections["Waypoints"].values[(char*)(LPCTSTR)str].data()); +} + +void CWaypoints::OnKillfocusPos() +{ + int i=m_Waypoints.GetCurSel(); + if(i==-1) return; + + CString str; + m_Waypoints.GetText(i, str); + + str.SetAt(str.Find(",",0), 0); + + // ok str now specifies the waypoint id + ini.sections["Waypoints"].values[(char*)(LPCTSTR)str]=GetText(&m_Pos); + + UpdateDialog(); + m_Waypoints.SetCurSel(i); +} + +void CWaypoints::OnKillFocus(CWnd* pNewWnd) +{ + CPropertyPage::OnKillFocus(pNewWnd); + + +} + +void CWaypoints::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CPropertyPage::OnShowWindow(bShow, nStatus); + + OnKillfocusPos(); +} + +void CWaypoints::OnDelete() +{ + int pos=m_Waypoints.GetCurSel(); + if(pos==-1) return; + + CString cuwayp; + //m_TreeList.GetText(pos, cutree); + cuwayp=ini.sections["Waypoints"].GetValueName(pos)->data(); + + ini.sections["Waypoints"].values.erase((string)(char*)(LPCTSTR) cuwayp); + + m_Waypoints.SetRedraw(FALSE); + UpdateDialog(); + m_Waypoints.SetCurSel(pos); + m_Waypoints.SetRedraw(TRUE); +} + +BOOL CWaypoints::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + CBitmap m; + m.LoadBitmap(IDB_DBG); + m_dbg.SetBitmap(m); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX-Eigenschaftenseiten sollten FALSE zurĂ¼ckgeben +} diff --git a/MissionEditor/Waypoints.h b/MissionEditor/Waypoints.h new file mode 100644 index 0000000..ab438a0 --- /dev/null +++ b/MissionEditor/Waypoints.h @@ -0,0 +1,77 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if !defined(AFX_WAYPOINTS_H__B0ED0400_7374_11D3_99E1_BB3FC259EC06__INCLUDED_) +#define AFX_WAYPOINTS_H__B0ED0400_7374_11D3_99E1_BB3FC259EC06__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Waypoints.h : Header-Datei +// + +///////////////////////////////////////////////////////////////////////////// +// Dialogfeld CWaypoints + +class CWaypoints : public CPropertyPage +{ + DECLARE_DYNCREATE(CWaypoints) + +// Konstruktion +public: + void UpdateDialog(); + CWaypoints(); + ~CWaypoints(); + +// Dialogfelddaten + //{{AFX_DATA(CWaypoints) + enum { IDD = IDD_WAYPOINTS }; + CStatic m_dbg; + CListBox m_Waypoints; + CEdit m_Pos; + //}}AFX_DATA + + +// Ăœberschreibungen + // Der Klassen-Assistent generiert virtuelle FunktionsĂ¼berschreibungen + //{{AFX_VIRTUAL(CWaypoints) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV-UnterstĂ¼tzung + //}}AFX_VIRTUAL + +// Implementierung +protected: + // Generierte Nachrichtenzuordnungsfunktionen + //{{AFX_MSG(CWaypoints) + afx_msg void OnSelchangeWaypoints(); + afx_msg void OnKillfocusPos(); + afx_msg void OnKillFocus(CWnd* pNewWnd); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + afx_msg void OnDelete(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ fĂ¼gt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein. + +#endif // AFX_WAYPOINTS_H__B0ED0400_7374_11D3_99E1_BB3FC259EC06__INCLUDED_ diff --git a/MissionEditor/constants.cpp b/MissionEditor/constants.cpp new file mode 100644 index 0000000..76c60e9 --- /dev/null +++ b/MissionEditor/constants.cpp @@ -0,0 +1,19 @@ +/* + FinalSun/FinalAlert 2 Mission Editor + + Copyright (C) 1999-2024 Electronic Arts, Inc. + Authored by Matthias Wagner + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ diff --git a/MissionEditor/data/FinalAlert2/FAData.ini b/MissionEditor/data/FinalAlert2/FAData.ini new file mode 100644 index 0000000..16d63d0 --- /dev/null +++ b/MissionEditor/data/FinalAlert2/FAData.ini @@ -0,0 +1,1245 @@ +; FAData.ini - Data file for FinalAlert 2: Yuri's Revenge +; This file offers data for FinalAlert 2 +; last change: Matthias Wagner, Feb 12, 2024 + +; Debug section: use carefully! +[Debug] +;DisplayAllOverlay=Yes ; Doesn´t cripple the overlay list in any way +;EnableTrackLogic=Yes ; Enables Track Logic +;IgnoreSHPImageHeadUnused=Yes ; Use this *carefully* to make SHP graphics of some mods work that incorrectly have the shadow flag set +AllowTunnels=yes +AllowUnidirectionalTunnels=yes +;ShowBuildingsWithToTile=no + +[ForceUnitPalettePrefix] +0=TIBTRE + +[ForceIsoPalettePrefix] + +; voxel turret locations (Original FA2 values) +[BuildingVoxelTurretsRA2OLD] +GTGCANX=00 +GTGCANY=44;-6 +NASAMY=-3;2 +NALASRX=0 +NALASRY=10;-3 +NAFLAKY=6;10 ; flak needs additional correction below for every direction +NAFLAKX=-5; +NAFLAKX0=5 +NAFLAKX2=-4; +NAFLAKY2=5 +NAFLAKX3=-5; +NAFLAKY3=10 +NAFLAKX4=5 +NAFLAKY4=14 +NAFLAKX5=10 +NAFLAKY5=8 +NAFLAKX6=15 +NAFLAKY6=5 +NAFLAKX7=12 +NAFLAKY7=1 +CAOUTPX=-30 +CAOUTPY=12 +YAREFNX=-30 +YAREFNY=30 +YAGGUNY=7 +YAGGUNX=-5 +YAGGUNX7=5; gattling gun needs some correction +YAGGUNY7=-3 +YAGGUNX6=11 +YAGGUNY6=3 +YAGGUNX5=10 +YAGGUNY5=3 +YAGGUNX4=3 +YAGGUNY4=2 +YAGGUNX0=5 + +[BuildingVoxelTurretsRA2] +GTGCANX=-5 +GTGCANY=5 +GTGCANX=-2 +GTGCANY=2 + +; voxel barrel locations (Original FA2 values) +[BuildingVoxelBarrelsRA2OLD] +GTGCANX0=0 +GTGCANY0=30;-6 +GTGCANX1=-18 +GTGCANY1=35;-6 +GTGCANX2=-28 +GTGCANY2=50;-6 +GTGCANX3=-27 +GTGCANY3=67;-6 +GTGCANX4=00 +GTGCANY4=73;-6 +GTGCANX5=23 +GTGCANY5=60;-6 +GTGCANX6=30 +GTGCANY6=48;-6 +GTGCANX7=20 +GTGCANY7=35;-6 + + +[BuildingVoxelBarrelsRA2] +GTGCANX=-5 +GTGCANY=5 + + +; not NOSURFACES: +;[BuildingVoxelTurretsRA2] +;GTGCANX=-1 +;GTGCANY=0;-6 +;NASAMY=0;2 +;NALASRX=0 +;NALASRY=0;-3 +;NAFLAKY=10;10 + +[VehicleVoxelTurretsRA2Disabled] +;DISKX=-10 +;DISKY=-10 +;YTNKY=-30 +SREFX=4 +SREFY=3 + +[IgnoreArtImage] +BFRT=1 +CAML=1 + +[IgnoreSuperAnim1] +[IgnoreSuperAnim2] +NAMISL=1 +GACSPH=1 + +[IgnoreSuperAnim3] +NAMISL=1 +GACSPH=1 + +[IgnoreSuperAnim4] +NAMISL=1 +GACSPH=1 + +; fix for building list: +[GTGCAN] +AIBasePlanningSide=0 + +[YACOMD] +AIBasePlanningSide=2 + +[YADEPT] +AIBasePlanningSide=0 + +[NASPYB] +AIBasePlanningSide=2 + +; rename list for objects. ObjectID=StringID +[Rename] +AMRADR=N_AMRADR +SENGINEER=N_SENGINEER +ENGINEER=N_ENGINEER +YENGINEER=N_YENGINEER +SCHD=N_SCHD +GACSPH=N_GACSPH +CALOND04=N_CALOND04 +CALOND05=N_CALOND05 +CATRAN03=N_CATRAN03 + +[MovieList] +Start=66; Anything below will not be listed! + +[StdBrushSize] +ClearTile=2 +RoughTile=2 +SandTile=2 +GreenTile=2 +PaveTile=2 +WaterSet=2 + +[MinBrushSizeInWater] ; if completely surrounded by water ; currently ignored +ClearTile=2 +RoughTile=2 +SandTile=2 +GreenTile=2 +PaveTile=2 + +; SlopeSetPieces for cliffs have a specific direction. +; used for AutoLevel logic +; CURRENTLY IGNORED +[SlopeSetPiecesDirections] +Count=10 +0=Right_1 +1=Left_1 +2=Top_1 +3=Bottom_1 +4=Right_2 +5=Left_2 +6=Left_2 +7=Bottom_2 +8=Top_2 +9=Top_2 + +[LUNARLimits] +TreeMax=999 +TreeMin=999 + +[URBANLimits] +TreeMax=999 +;TreeMax=27 + +[TEMPERATELimits] +TreeMax=999 +;TreeMax=27 + +[SNOWLimits] +TreeMax=999 +;TreeMax=27 + +[NEWURBANLimits] +TreeMax=999 +;TreeMax=27 + +[DESERTLimits] +TreeMin=30 +TreeMax=999 + +; tileset ini overwritings +; only used by FinalAlert +[IgnoreSetTEMPERATE] +0=77 +1=78 +2=79 + +[IgnoreSetSNOW] +0=8 +1=46 + +[IgnoreSetURBAN] +0=49 +1=50 +2=51 +5=56 +7=30 +8=91 +9=92 +10=93 +11=94 +12=95 +13=96 +14=97 +15=98 +16=99 +17=100 +;3=53; Tunnel +;4=54; Tunnel Side +;6=73; Dirt Tunnel + +[IgnoreSetNEWURBAN] +0=101 + +[IgnoreSetDESERT] +0=19 +1=54 +2=53 +3=56 +4=73 +5=80 + +[IgnoreSetLUNAR] + +[UseSetTEMPERATE] +0=57 + +[UseSetSNOW] +[UseSetURBAN] + +[NewUrbanInfo] +Morphable2=114 +Ramps2=117 +Cliffs2=110 +CliffsWater2=112 + +; The following section is for finding out if a map is RA2 original or Yuri's Revenge only! +; If a ground tile id exceeds this number, FA2 will assume the map is a YR map +[RA2TileMax] +Temperat=838 +Urban=1077 +Snow=798 + +[YRInfantry] +YENGINEER=1 +GGI=1 +INIT=1 +BORIS=1 +BRUTE=1 +VIRUS=1 +CLNT=1 +ARND=1 +STLN=1 +CAML=1 +EINS=1 +MUMY=1 +RMNV=1 +LUNR=1 +DNOA=1 +DNOB=1 +SLAV=1 +WWLF=1 +YDOG=1 +YADOG=1 + +[YRUnits] +YHVR=1 +PCV=1 +SMIN=1 +SMON=1 +YCAB=1 +YTNK=1 +BFRT=1 +TELE=1 +CAOS=1 +DDBX=1 +BCAB=1 +BSUB=1 +SCHP=1 +JEEP=1 +MIND=1 +DISK=1 +UTNK=1 +ROBO=1 +YDUM=1 +SCHD=1 +DOLY=1 +CBLC=1 +FTRK=1 +AMBU=1 +CIVP=1 + +[YRBuildings] +YACNST=1 +YAPOWR=1 +YABRCK=1 +YAWEAP=1 +YAYARD=1 +YADEPT=1 +YATECH=1 +GAFWLL=1 +YAGGUN=1 +YAPSYT=1 +NAINDP=1 +YAGRND=1 +YAGNTC=1 +CASLAB=1 +CATIME=1 +YAPPET=1 +CALOND04=1 +CALOND05=1 +CALOND06=1 +CAMOON01=1 +CATRAN03=1 +CAEAST01=1 +CAEGYP01=1 +CAEGYP02=1 +CAEGYP03=1 +CALA01=1 +CALA02=1 +CALA03=1 +CALA04=1 +CALA05=1 +CALOND01=1 +CALOND02=1 +CALOND03=1 +CAMORR01=1 +CAMORR02=1 +CAMORR03=1 +CASANF01=1 +CASANF02=1 +CASANF03=1 +CASANF04=1 +CASANF05=1 +CASEAT01=1 +NATBNK=1 +GAGATE_A=1 +CASANF09=1 +CASANF10=1 +CASANF11=1 +CASANF12=1 +CASANF13=1 +CASANF14=1 +CASANF06=1 +CASANF07=1 +CASANF08=1 +CASEAT02=1 +YACOMD=1 +YAPPPT=1 +GAROBO=1 +YAREFN=1 +YAROCK=1 +NABNKR=1 +CASANF15=1 +CASANF16=1 +CASANF17=1 +CASANF18=1 +CASIN03E=1 +CASIN03S=1 +CAURB01=1 +CAURB02=1 +CAURB03=1 +CAPOWR=1 +CALA07=1 +CAEGYP06=1 +CALA08=1 +CAEAST02=1 +CABARR01=1 +CABARR02=1 +CAMORR04=1 +CAMORR05=1 +CALA09=1 +CAEGYP04=1 +CAEGYP05=1 +CALA06=1 +CAMORR06=1 +CAMORR07=1 +CAMORR08=1 +CAMORR09=1 +CAMORR10=1 +CATIME01=1 +CATIME02=1 +CALA10=1 +CALA11=1 +CALA12=1 +CALA13=1 +CAPARK04=1 +CAPARK05=1 +CAPARK06=1 +CALA14=1 +CALA15=1 +CABUNK03=1 +CABUNK04=1 +CALUNR01=1 +CALUNR02=1 + +[YRTerrain] +TREE31=1 +TREE32=1 +TREE33=1 +TREE34=1 +TREE35=1 +TREE36=1 + +[YRAircraft] +BPLN=1 +SPYP=1 +CMISL=1 + +[YROverlay] +Begin=243; which number is the first from new YR overlay? + +; things only FinalAlert will ignore +; these are usually all dummies and leftovers from TS +[IgnoreRA2] +0=GAARMORY +1=APACHE +2=DeathDummy +3=WEEDGUY +4=GADUMY +5=NAWAST +6=GARADR +7=CAIRSFGL +8=CALIT01E +9=CALIT01N +10=CALIT01S +11=CALIT01W +12=CALIT03E +13=CALIT03N +14=CALIT03S +15=CALIT03W +16=CALIT02L +17=CALIT02R +18=NAHPAD +19=CAEURO01 +20=CACITY01 +21=CACITY02 +22=CACITY03 +23=CACITY04 +24=CITY06 +25=CITY05 +26=CITY04 +27=CITY03 +28=CITY02 +29=CITY01 +30=CAARMR +31=TREE29 +32=TREE30 +33=CANEWY05 +34=REDLAMP +35=GRENLAMP +36=BLUELAMP +37=YELWLAMP +38=PURPLAMP +39=INORANLAMP +;40=NEGLAMP ; NEGLAMP added again, invisible in game +41=NEGRED +42=TSTLAMP +43=CAPOL01E +44=CAPOL01N +45=CAPOL01S +46=CAPOL01W +47=CASIN01E +48=CASIN01N +49=CASIN01W +50=CASIN01S +51=GAGREEN +52=GALITE +53=CARGOPLANE +54=CAHOSP +55=XCOMET +56=CAKRMW +57=CAFNCB +58=CAFNCW +59=CAFNCP +60=CR1 +61=CR2 +62=CR3 +63=CR4 +64=CR5 +65=CR6 +66=BURN01 +67=BURN02 +68=BURN03 +69=BURN04 +70=BURN05 +71=BURN06 +72=BURN07 +73=BURN08 +74=BURN09 +75=BURN10 +76=BURN11 +77=BURN12 +78=BURN13 +79=BURN14 +80=BURN15 +Another one :) =BURN16 +82=CASYDN01 +83=CATIME +84=CALOND02;? +;85=CAMORR01 +;86=CAMORR02 +;87=CAMORR03 +;88=CAEGYP06 +;89=CAMORR04 +;90=CAEGYP04 +;91=CAEGYP05 +;92=CALA06 + +97=DNOB;? +98=GAWRONG +99=CALA02;? +100=CAMOON01 +;101=CAEGYP01 +102=UTNK +103=YDUM +104=WWLF +105=YADOG +106=YDOG +107=SMON +108=CMON +109=YADEPT +110=CALOND06;? +;111=TREE32 + +; hacks for shore pieces +; shore id_pos=iswater +; pos: count from left top to right, then next "row" + +; RA2 only needs one fix (for URBAN specifically) +[ShoreTerrainRA2] +12_4=1 +12_5=1 + +; But TS needs all :( +[ShoreTerrainTS] +0_0=0 +0_1=0 +0_2=1 +0_3=1 +1_0=0 +1_1=0 +2_0=0 +2_1=0 +3_0=0 +4_0=0 +4_1=0 +4_3=0 +5_0=0 +5_1=0 +5_2=0 +6_0=0 +7_0=0 +8_0=0 +8_2=0 +9_0=0 +9_2=0 +10_0=0 +10_2=0 +11_0=0 +12_0=0 +12_1=0 +12_3=0 +13_0=0 +13_3=0 +13_4=0 +14_2=0 +15_2=0 +16_2=0 +16_3=0 +17_2=0 +17_3=0 +18_2=0 +18_3=0 +19_1=0 +20_3=0 +20_4=0 +20_5=0 +21_2=0 +21_4=0 +21_5=0 +22_3=0 +23_3=0 +24_1=0 +24_3=0 +25_1=0 +25_3=0 +26_1=0 +26_3=0 +27_1=0 +28_1=0 +28_2=0 +28_5=0 +29_2=0 +29_4=0 +29_5=0 +30_1=0 +31_1=0 +32_0=0 +32_1=0 +32_2=0 +33_0=0 +33_1=0 +33_2=0 +34_0=0 +34_2=0 +34_3=0 +35_0=0 +35_2=0 +35_3=0 +36_1=0 +36_2=0 +36_3=0 +37_1=0 +37_2=0 +37_3=0 +38_0=0 +38_1=0 +38_3=0 +39_0=0 +39_1=0 +39_3=0 + +; tilesets that may be modified using the shore or a similar logic +[SoftTileSets] +ClearTile=1 +RoughTile=1 +ClearToRoughLat=1 +SandTile =1 +ClearToSandLat=1 +GreenTile=1 +ClearToGreenLat=1 +PaveTile=1 +MiscPaveTile =1 +ClearToPaveLat=1 +RoughGround=0; no +WaterSet=1 +ShorePieces=1 + +; corner strings are: cornerleft, cornerright, cornerbottom, cornertop + +[CliffBackData] +vertic_diag_c=2 +;vertic_diag_2=0 +vertic_diag_0=2 +vertic_diag_1=3 +;vertic_diag_3=1 ; unused at moment +vertic_diag_cornertop_c=1 +;vertic_diag_cornertop_1=0 +vertic_diag_cornertop_0=1 +horiz_c=4 +horiz_0=22 +horiz_1=23 +horiz_2=24 +horiz_3=25 ;2x1, not 2x2, unused at moment +horiz_cornerbottom_c=2 +horiz_cornerbottom_0=28 +horiz_cornerbottom_1=29 +horiz_cornertop_c=0 +;horiz_cornertop_0=31 +vertic_c=4 +vertic_0=34 +vertic_1=35 +vertic_2=36 +vertic_3=37 ;2x1, not 2x2, unused at moment +vertic_cornerright_c=2 +vertic_cornerright_0=29 +vertic_cornerright_1=28 + +[CliffBackDataAlt] +vertic_diag_c=2 +;vertic_diag_2=0 +vertic_diag_0=2 +vertic_diag_1=3 +;vertic_diag_3=1 ; unused at moment +vertic_diag_cornertop_c=1 +;vertic_diag_cornertop_1=0 +vertic_diag_cornertop_0=1 +horiz_c=4 +horiz_0=22 +horiz_1=23 +horiz_2=24 +horiz_3=25 ;2x1, not 2x2, unused at moment +horiz_cornerbottom_c=2 +horiz_cornerbottom_0=28 +horiz_cornerbottom_1=29 +horiz_cornertop_c=0 +;horiz_cornertop_0=31 +vertic_c=4 +vertic_0=34 +vertic_1=35 +vertic_2=36 +vertic_3=37 ;2x1, not 2x2, unused at moment +vertic_cornerright_c=2 +vertic_cornerright_0=29 +vertic_cornerright_1=28 + +[CliffBackDataURBAN] +vertic_diag_c=1 +;vertic_diag_4=0 +vertic_diag_0=2 +;vertic_diag_1=3; other cliff type +;vertic_diag_3=1 ; unused at moment +vertic_diag_cornertop_c=2 +vertic_diag_cornertop_0=0 +vertic_diag_cornertop_1=1 +horiz_c=2 +horiz_0=22 +;horiz_3=23 +;horiz_2=24 +horiz_1=25 ;2x1, not 2x2, unused at moment +horiz_cornerbottom_c=2 +horiz_cornerbottom_0=28 +horiz_cornerbottom_1=29 +vertic_c=4 +vertic_0=34 +vertic_1=35 +vertic_2=36 +vertic_3=37 ;2x1, not 2x2, unused at moment +vertic_cornerright_c=2 +vertic_cornerright_0=29 +vertic_cornerright_1=28 + +[CliffBackDataNEWURBAN] +vertic_diag_c=1 +;vertic_diag_4=0 +vertic_diag_0=2 +;vertic_diag_1=3; other cliff type +;vertic_diag_3=1 ; unused at moment +vertic_diag_cornertop_c=2 +vertic_diag_cornertop_0=0 +vertic_diag_cornertop_1=1 +horiz_c=2 +horiz_0=22 +;horiz_3=23 +;horiz_2=24 +horiz_1=25 ;2x1, not 2x2, unused at moment +horiz_cornerbottom_c=2 +horiz_cornerbottom_0=28 +horiz_cornerbottom_1=29 +vertic_c=4 +vertic_0=34 +vertic_1=35 +vertic_2=36 +vertic_3=37 ;2x1, not 2x2, unused at moment +vertic_cornerright_c=2 +vertic_cornerright_0=29 +vertic_cornerright_1=28 + +[CliffFrontData] +vertic_diag_c=2 +vertic_diag_0=18 +vertic_diag_1=19 +;vertic_diag_2=20 +;vertic_diag_3=21 ; unused at moment +vertic_diag_cornerleft_c=1 +vertic_diag_cornerleft_0=20 +;vertic_diag_cornerleft_1=21 +vertic_diag_cornerright_c=2 +vertic_diag_cornerright_0=32 +vertic_diag_cornerright_1=33 +horiz_c=4 +horiz_0=4 +horiz_1=5 +horiz_2=6 +horiz_3=7 ;2x1, not 2x2, unused at moment +horiz_cornertop_c=1 +horiz_cornertop_0=1 +horiz_diag_c=6 +horiz_diag_0=8 +horiz_diag_1=9 +horiz_diag_2=10 +horiz_diag_3=11 ; unused at moment +horiz_diag_4=12 ; unused at moment +horiz_diag_5=13 ; unused at moment +vertic_c=4 +vertic_0=14 +vertic_1=15 +vertic_2=16 +vertic_3=17 ;2x1, not 2x2, unused at moment +vertic_cornerleft_c=1 +vertic_cornerleft_0=21 + +[CliffFrontDataAlt] +vertic_diag_c=2 +vertic_diag_0=18 +vertic_diag_1=19 +;vertic_diag_2=20 +;vertic_diag_3=21 ; unused at moment +vertic_diag_cornerleft_c=1 +vertic_diag_cornerleft_0=20 +;vertic_diag_cornerleft_1=21 +vertic_diag_cornerright_c=2 +vertic_diag_cornerright_0=32 +vertic_diag_cornerright_1=33 +horiz_c=4 +horiz_0=4 +horiz_1=5 +horiz_2=6 +horiz_3=7 ;2x1, not 2x2, unused at moment +horiz_cornertop_c=1 +horiz_cornertop_0=1 +horiz_diag_c=6 +horiz_diag_0=8 +horiz_diag_1=9 +horiz_diag_2=10 +horiz_diag_3=11 ; unused at moment +horiz_diag_4=12 ; unused at moment +horiz_diag_5=13 ; unused at moment +vertic_c=4 +vertic_0=14 +vertic_1=15 +vertic_2=16 +vertic_3=17 ;2x1, not 2x2, unused at moment +vertic_cornerleft_c=1 +vertic_cornerleft_0=21 + +[CliffFrontDataURBAN] +vertic_diag_c=1 +vertic_diag_0=18 +;vertic_diag_2=19 ; other cliff type +;vertic_diag_3=20 ; other cliff type +;vertic_diag_1=21 ; unused at moment +vertic_diag_cornerleft_c=1 +vertic_diag_cornerleft_0=20 +;vertic_diag_cornerleft_1=21 +vertic_diag_cornerright_c=2 +vertic_diag_cornerright_0=32 +vertic_diag_cornerright_1=33 +horiz_c=2 +horiz_0=4 +;horiz_3=5 ; other cliff type +;horiz_2=6 ; other cliff type +horiz_1=7 ;2x1, not 2x2, unused at moment +horiz_cornertop_c=1 +horiz_cornertop_0=1 +horiz_diag_c=2 +horiz_diag_0=8 +;horiz_diag_4=9 ; other cliff type +;horiz_diag_2=10 ; other cliff type +horiz_diag_1=11 ; unused at moment +;horiz_diag_3=12 ; unused at moment +;horiz_diag_5=13 ; unused at moment +vertic_c=2 +vertic_0=14 +;vertic_3=15 ; other cliff type +;vertic_2=16 ; other cliff type +vertic_1=17 ;2x1, not 2x2, unused at moment +vertic_cornerleft_c=1 +vertic_cornerleft_0=21 + +[CliffFrontDataNEWURBAN] +vertic_diag_c=1 +vertic_diag_0=18 +;vertic_diag_2=19 ; other cliff type +;vertic_diag_3=20 ; other cliff type +;vertic_diag_1=21 ; unused at moment +vertic_diag_cornerleft_c=1 +vertic_diag_cornerleft_0=20 +;vertic_diag_cornerleft_1=21 +vertic_diag_cornerright_c=2 +vertic_diag_cornerright_0=32 +vertic_diag_cornerright_1=33 +horiz_c=2 +horiz_0=4 +;horiz_3=5 ; other cliff type +;horiz_2=6 ; other cliff type +horiz_1=7 ;2x1, not 2x2, unused at moment +horiz_cornertop_c=1 +horiz_cornertop_0=1 +horiz_diag_c=2 +horiz_diag_0=8 +;horiz_diag_4=9 ; other cliff type +;horiz_diag_2=10 ; other cliff type +horiz_diag_1=11 ; unused at moment +;horiz_diag_3=12 ; unused at moment +;horiz_diag_5=13 ; unused at moment +vertic_c=2 +vertic_0=14 +;vertic_3=15 ; other cliff type +;vertic_2=16 ; other cliff type +vertic_1=17 ;2x1, not 2x2, unused at moment +vertic_cornerleft_c=1 +vertic_cornerleft_0=21 + +; EVENTS AND ACTIONS +; param type format: Description,ListType +; ListTypes (all those not implemented yet but stubbed when this ini was written are marked with *): +; 0-Nothing +; 1-Houses +; 2-Teamtypes +; 3-UnitTypes +; 4-InfantryTypes +; 5-AircraftTypes +; 6-BuildingTypes +; 7-Videos +; 8-tutorial texts +; 9-Triggers +; 10-yes/no +; 11=sounds +; 12=themes +; 13=speeches +; 14=special weapons +; 15=animations +; 16=particles +; 17=waypoints +; 18=crate types * +; 19=speech bubble types * +; 20=Global variables <--- wrong, local variables! +; 21=.CSF strings (RA2 only) * +; 22=Tag * +; 23=Meteors * +; 24=Weapons * +; 25=Light behavior * +; 26=Shower * +; 27=Rules Global variables +; 28=Building INI names +; 29=Techtypes + + +; ParamTypes +; Name, ListType, [Code] +[ParamTypes] +-1=Unused,0,1;not listed in FA2 +0=Unused,0 +1=Unknown,0 +2=House,1 +3=Local variable,20 +4=Time,0 +5=Credits,0 +6=Number,0 +7=Teamtype,2 +8=Building,6 +9=Aircraft,5 +10=Infantry,4 +11=Unit,3 +12=Movie,7 +13=Text,8 +14=Trigger,9 +15=Enabled,10 +16=Sound,11 +17=Theme,12 +18=Speech,13 +19=Steps,0 +20=Super weapon,14 +21=Left,0 +22=Top,0 +23=Right,0 +24=Bottom,0 +25=Animation,15 +26=Particle,16 +27=Duration,0 +28=Speed,0 +29=Meteor size,29 +30=Waypoint,17 +31=Crate type,18 +32=Speech bubble,19 +33=String,21 +34=Action,9 +35=Global variable,27 +36=Special Weapon,14 +37=Activated,10 +38=Tag,22 +39=Techtype,0 +40=Quarry,0 +41=Weapon,24 +42=Light behavior,25 +43=Event,9 +44=Shower,26 +45=Float value,0 +46=Techtype,29;,2 +47=Building,28 +48=Number,0,2 + +[DontSaveAsWP] ; which code values indicate that the waypoint param must be saved as normal integer? +0=5 +1=9 +;2=10 +3=11 + +; events format: +; #=Description, P1 type, P2 type, TagNeeded, Obsolete,Desc2,UsedInTS,UsedInRA2,ID,[NeedsYR optional] +; negative number for type currently not supported (only Actions do support yet)! +; NOTE: Actions not listed in [Events] but in [EventsRA2] will be ignored. Use the "used in RA2" to support them. +; NOTE: To overwrite TS events with RA2 special ones, add the new event to the [EventsRA2] section. +; NOTE: ID must be the same like # +[EventsRA2] +0=-No Event-,0,0,0,0,This is a null event. There is no need to ever use this in a real trigger.,0,1,0 +1=Entered by...,0,2,0,0,Triggers when an infantry or vehicle enters the attached object. Typically this trigger is attached to a building or a cell.,0,1,1 +2=Spied upon,0,0,0,0,Detects when a spy has entered the attached building.,0,1,2 +3=Thieved by...,0,2,0,0,Triggers when a thief steals money from the specified house.,0,1,3 +4=Discovered by player,0,0,0,0,Detects when the attached object has been discovered by the player. Discovered means reavealed from under the shroud.,0,1,4 +5=House Discovered...,0,2,0,0,Triggers when the specified house has any of its units or buildings discovered by the player.,0,1,5 +6=Attacked by any house,0,0,0,0,Triggers when the attached unit is attacked in some manner. Incidental damage or friendly fire does not count.,0,1,6 +7=Destroyed by any house,0,0,0,0,Triggers when the attached object has been destroyed. Destroyed by incidental damage or friendly fire doesn't count.,0,1,7 +8=Any Event,0,0,0,0,When used alone%1 it will force the trigger to spring immediately.,0,1,8 +9=Destroyed%1 Units%1 All...,0,2,0,0,Triggers when all units of the specified house have been destroyed. Typically used for end of game conditions.,0,1,9 +10=Destroyed%1 Buildings%1 All...,0,2,0,0,Triggers when all buildings of the specified side have been destroyed. Typically used for end of game conditions.,0,1,10 +11=Destroyed%1 All...,0,2,0,0,Triggers when all objects owned by the specified house have been destroyed. This is the normal (destroy everyone) trigger condition for end of game.,0,1,11 +12=Credits exceed...,0,6,0,0,Triggers when the house (for this trigger) credit total exceeds this specified amount.,0,1,12 +13=Elapsed Time...,0,6,0,0,Triggers when the elapsed time has expired. This time is initialized when the trigger is created. Timer is reset whenever trigger is sprung when trigger is 'persistant'.,0,1,13 +14=Mission Timer Expired,0,0,0,0,Triggers when the global mission timer (as displayed on the screen) has reached zero.,0,1,14 +15=Destroyed%1 Buildings%1 #...,0,6,0,0,Triggers when the number of buildings%1 owned by the trigger's specified house%1 have been destroyed.,0,1,15 +16=Destroyed%1 Units%1 #...,0,6,0,0,Triggers when the number of units%1 owned by the trigger's specified house%1 have been destroyed.,0,1,16 +17=No Factories left,0,0,0,0,Triggers when there are no factories left for the house specified in the trigger.,0,1,17 +18=Civilians Evacuated,0,0,0,0,Triggers when civilians have been evacuated (left the map).,0,1,18 +19=Build Building Type...,0,8,0,0,When the trigger's house builds the building type specified%1 then this event will spring.,0,1,19 +20=Build Unit Type...,0,11,0,0,When the trigger's house builds the unit type specified%1 then this event will spring.,0,1,20 +21=Build Infantry Type...,0,10,0,0,When the trigger's house builds the infantry type specified%1 then this event will spring.,0,1,21 +22=Build Aircraft Type...,0,9,0,0,When the trigger's house builds the aircraft type specified%1 then this event will spring.,0,1,22 +23=Leaves map (team)...,-1,7,0,0,Triggers when the specified team leaves the map. If the team is destroyed%1 it won't trigger. If all but one member is destroyed and that last member leaves the map%1 it WILL spring.,0,1,23 +24=Zone Entry by...,0,2,0,0,Triggers when a unit of the dpecified house enters the same zone that this trigger is located in. This trigger must be located in a cell and only a cell.,0,1,24 +25=Crosses Horizontal Line...,0,2,0,0,Triggers when a unit of the specified house crosses the horizontal line as indicated by the location of this trigger. This trigger must be placed in a cell.,0,1,25 +26=Crosses Vertical Line...,0,2,0,0,Triggers when a unit of the specified house crosses the vertical line as indicated by the location of this trigger. This trigger must be placed in a cell.,0,1,26 +27=Global is set...,0,35,0,0,Triggers when the specifed global (named in Globals.INI) is turned on.,0,1,27 +28=Global is clear...,0,35,0,0,Triggers when the specified global (named in Globals.INI) is turned off.,0,1,28 +29=Destroyed by anything [not infiltrate],0,0,0,0,Triggers when attached object is destroyed%1 but not if it infiltrates a building/unit.,0,1,29 +30=Low Power...,0,2,0,0,Triggers when the specified house's power falls below 100% level.,0,1,30 +31=Bridge destroyed,0,0,0,0,Triggers when the attached bridge is destroyed. A bridge is considered destroyed when an impassable gap is created in the bridge.,0,1,31 +32=Building exists...,0,8,0,0,Triggers when the building (owned by the house of this trigger) specified exists on the map. This works for buildings that are preexisting or constructed by deploying.,0,1,32 +33=Selected by player,0,0,0,0,Triggers when the unit is selected by the player. Use in single-player only.,0,1,33 +34=Comes near waypoint...,0,30,0,0,Triggers when the object comes near the specified waypoint.,0,1,34 +35=Enemy In Spotlight...,0,0,0,0,Triggers when an enemy unit enters the spotlight cast by the attached building.,0,1,35 +36=Local is set...,0,3,0,0,Triggers when the specifed local is turned on.,0,1,36 +37=Local is clear...,0,3,0,0,Triggers when the specified local is turned off.,0,1,37 +38=First damaged (combat only),0,0,0,0,Triggers when first suffering from combat damage from combat damage only.,0,1,38 +39=Half health (combat only),0,0,0,0,Triggers when damaged to half health >from combat damage only.,0,1,39 +40=Quarter health (combat only),0,0,0,0,Triggers when damaged to quarter health from combat damage only.,0,1,40 +41=First damaged (any source),0,0,0,0,Triggers when first suffering from combat damage from any source.,0,1,41 +42=Half health (any source),0,0,0,0,Triggers when damaged to half health >from any source.,0,1,42 +43=Quarter health (any source),0,0,0,0,Triggers when damaged to quarter health from any source.,0,1,43 +44=Attacked by (house)...,0,2,0,0,When attacked by some unit of specified house.,0,1,44 +45=Ambient light <= ...,0,6,0,0,Triggers when the ambient light drops below a certain level. Use numbers between 0 and 100.,0,1,45 +46=Ambient light >= ...,0,6,0,0,Triggers when the ambient light rises above a certain level. Use numbers between 0 and 100.,0,1,46 +47=Elapsed Scenario Time...,0,6,0,0,When time has elapsed since start of scenario.,0,1,47 +48=Destroyed by anything,0,0,0,0,Triggers when destroyed by anything what-so-ever.,0,1,48 +49=Pickup Crate,0,0,0,0,When crate is picked up object the trigger is attached to.,0,1,49 +50=Pickup Crate (any),0,0,0,0,When crate is picked up by any unit.,0,1,50 +51=Random delay...,0,6,0,0,Delays a random time between 50 and 150 percent of time specified.,0,1,51 +52=Credits below...,0,6,0,0,Triggers when the house (for this trigger) credit total is below this specified amount.,0,1,52 +53=Spy entering as House...,0,2,0,0,Triggers if a spy disguised as house specified enters this.,0,1,53 +54=Spy entering as Infantry...,0,10,0,0,Triggers if a spy disguised as this type of infantry enters.,0,1,54 +55=Destroyed%1 Units%1 Naval...,0,2,0,0,Triggers when all naval units of the specified house have been destroyed. Typically used for end of game conditions.,0,1,55 +56=Destroyed%1 Units%1 Land...,0,2,0,0,Triggers when all land units of the specified house have been destroyed. Typically used for end of game conditions.,0,1,56 +57=Building does not exist,0,8,0,0,Triggers when the building (owned by the house of this trigger) specified does not exist on the map.,0,1,57 + +; YR +58=Power Full...,0,2,0,0,Triggers if the specified house's power is at 100%.,0,1,58,1 +59=Entered or Overflown By...,0,2,0,0,Triggers when unit%1 infantry%1 or aircraft move over this cell. ,0,1,59,1 + +; 60 and 61 are tricky! They use code + 2 params... param type 46 includes the code 2, which is put in front of the 2 parameters +60=TechType Exists,48,46,0,0,True if there are at least this many of this type%1 belonging to anyone,0,1,60,1 +61=TechType does not Exist,48,46,0,0,True if there are none of these on the map at all. Number doesn't mean anything.,0,1,61,1 + + +; action format: +; #=Description, P1 type, P2 type, P3 type, P4 type, P5Type, P6Type, uses waypoint, uses tag, Obsolete, used in TS, used in RA2, ID, [YR only - optional] +; if using negative number for type, param will be set to the absolute value of this number +; NOTE: Actions not listed in [Actions] but in [ActionsRA2] will be ignored. Use the "used in RA2" to support them. +; NOTE: To overwrite TS actions with RA2 special ones, add the new action to the [ActionsRA2] section. +; NOTE: ID must be the same like # +[ActionsRA2] +0=-No Action-,0,0,0,0,0,0,0,0,0,This is a null action. It will do nothing and is equivalent to not having an action at all. Why use it?,0,1,0 +1=Winner is...,0,2,0,0,0,0,0,0,0,The winner will be forced to be the house specified. The game will end immediately. Typically%1 the player's house is specified.,0,1,1 +2=Loser is...,0,2,0,0,0,0,0,0,0,The loser will be force to be the house specified. The game will end immediately. Typically%1 the player's house is specified.,0,1,2 +3=Production Begins...,0,2,0,0,0,0,0,0,0,The computer's house (as specified) will begin production of units and structures.,0,1,3 +4=Create Team...,-1,7,0,0,0,0,0,0,0,Creates a team of the type specified (owned by the house of this trigger). The team member are NOT automatically created however.,0,1,4 +5=Destroy Team...,-1,7,0,0,0,0,0,0,0,Destroys all instances of the team type specified. The units in those existing teams will remain and be available for recruiting into other teams.,0,1,5 +6=All to Hunt...,0,2,0,0,0,0,0,0,0,Forces all units%1 of the house specified%1 into 'hunt' mode. They will seek out and destroy their enemies.,0,1,6 +7=Reinforcement (team)...,-1,7,0,0,0,0,0,0,0,Create a reinforcement of the specified team. The members of the team WILL be created magically by this action.,0,1,7 +8=Drop Zone Flare (waypoint)...,0,30,0,0,0,0,0,0,0,Display a drop zone flair at the waypoint specified. The map will also be reaveald around that location.,0,1,8 +9=Fire Sale...,0,2,0,0,0,0,0,0,0,Cause all buildings of the specified house to be sold (for cash and prizes). Typically this is used in the final assault by the computer.,0,1,9 +10=Play Movie...,0,12,0,0,0,0,0,0,0,Displays the specified movie (full screen). The game is paused while this occurs and resumes normally after it completes.,0,1,10 +11=Text Trigger...,-4,13,0,0,0,0,0,0,0,Display the text identified by the string file